xref: /aosp_15_r20/external/vixl/src/aarch32/assembler-aarch32.cc (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1 // Copyright 2017, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 extern "C" {
28 #include <stdint.h>
29 }
30 
31 #include <cassert>
32 #include <cstdio>
33 #include <cstdlib>
34 #include <cstring>
35 #include <iostream>
36 
37 #include "utils-vixl.h"
38 #include "aarch32/assembler-aarch32.h"
39 #include "aarch32/constants-aarch32.h"
40 #include "aarch32/instructions-aarch32.h"
41 #include "aarch32/operands-aarch32.h"
42 
43 namespace vixl {
44 namespace aarch32 {
45 
EmitT32_16(uint16_t instr)46 void Assembler::EmitT32_16(uint16_t instr) {
47   VIXL_ASSERT(buffer_.Is16bitAligned());
48   buffer_.Emit16(instr);
49 }
50 
51 
EmitT32_32(uint32_t instr)52 void Assembler::EmitT32_32(uint32_t instr) {
53   VIXL_ASSERT(buffer_.Is16bitAligned());
54   buffer_.Emit16(static_cast<uint16_t>(instr >> 16));
55   buffer_.Emit16(static_cast<uint16_t>(instr & 0xffff));
56 }
57 
58 
EmitA32(uint32_t instr)59 void Assembler::EmitA32(uint32_t instr) {
60   VIXL_ASSERT(buffer_.Is32bitAligned());
61   buffer_.Emit32(instr);
62 }
63 
64 
65 #ifdef VIXL_DEBUG
PerformCheckIT(Condition condition)66 void Assembler::PerformCheckIT(Condition condition) {
67   if (it_mask_ == 0) {
68     VIXL_ASSERT(IsUsingA32() || condition.Is(al));
69   } else {
70     VIXL_ASSERT(condition.Is(first_condition_));
71     // For A32, AdavanceIT() is not called by the assembler. We must call it
72     // in order to check that IT instructions are used consistently with
73     // the following conditional instructions.
74     if (IsUsingA32()) AdvanceIT();
75   }
76 }
77 #endif
78 
79 
BindHelper(Label * label)80 void Assembler::BindHelper(Label* label) {
81   VIXL_ASSERT(!label->IsBound());
82   label->SetLocation(this, GetCursorOffset());
83   label->MarkBound();
84 }
85 
Link(uint32_t instr,Location * location,const Location::EmitOperator & op,const ReferenceInfo * info)86 uint32_t Assembler::Link(uint32_t instr,
87                          Location* location,
88                          const Location::EmitOperator& op,
89                          const ReferenceInfo* info) {
90   location->SetReferenced();
91   if (location->IsBound()) {
92     return op.Encode(instr, GetCursorOffset(), location);
93   }
94   location->AddForwardRef(GetCursorOffset(), op, info);
95   return instr;
96 }
97 
98 
99 // Start of generated code.
100 class Dt_L_imm6_1 : public EncodingValue {
101   uint32_t type_;
102 
103  public:
104   explicit Dt_L_imm6_1(DataType dt);
GetTypeEncodingValue() const105   uint32_t GetTypeEncodingValue() const { return type_; }
106 };
107 
Dt_L_imm6_1(DataType dt)108 Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
109   switch (dt.GetValue()) {
110     case S8:
111       type_ = 0x0;
112       SetEncodingValue(0x1);
113       break;
114     case U8:
115       type_ = 0x1;
116       SetEncodingValue(0x1);
117       break;
118     case S16:
119       type_ = 0x0;
120       SetEncodingValue(0x2);
121       break;
122     case U16:
123       type_ = 0x1;
124       SetEncodingValue(0x2);
125       break;
126     case S32:
127       type_ = 0x0;
128       SetEncodingValue(0x4);
129       break;
130     case U32:
131       type_ = 0x1;
132       SetEncodingValue(0x4);
133       break;
134     case S64:
135       type_ = 0x0;
136       SetEncodingValue(0x8);
137       break;
138     case U64:
139       type_ = 0x1;
140       SetEncodingValue(0x8);
141       break;
142     default:
143       VIXL_UNREACHABLE();
144       type_ = 0x0;
145       break;
146   }
147 }
148 
149 class Dt_L_imm6_2 : public EncodingValue {
150   uint32_t type_;
151 
152  public:
153   explicit Dt_L_imm6_2(DataType dt);
GetTypeEncodingValue() const154   uint32_t GetTypeEncodingValue() const { return type_; }
155 };
156 
Dt_L_imm6_2(DataType dt)157 Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
158   switch (dt.GetValue()) {
159     case S8:
160       type_ = 0x1;
161       SetEncodingValue(0x1);
162       break;
163     case S16:
164       type_ = 0x1;
165       SetEncodingValue(0x2);
166       break;
167     case S32:
168       type_ = 0x1;
169       SetEncodingValue(0x4);
170       break;
171     case S64:
172       type_ = 0x1;
173       SetEncodingValue(0x8);
174       break;
175     default:
176       VIXL_UNREACHABLE();
177       type_ = 0x0;
178       break;
179   }
180 }
181 
182 class Dt_L_imm6_3 : public EncodingValue {
183  public:
184   explicit Dt_L_imm6_3(DataType dt);
185 };
186 
Dt_L_imm6_3(DataType dt)187 Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
188   switch (dt.GetValue()) {
189     case I8:
190       SetEncodingValue(0x1);
191       break;
192     case I16:
193       SetEncodingValue(0x2);
194       break;
195     case I32:
196       SetEncodingValue(0x4);
197       break;
198     case I64:
199       SetEncodingValue(0x8);
200       break;
201     default:
202       break;
203   }
204 }
205 
206 class Dt_L_imm6_4 : public EncodingValue {
207  public:
208   explicit Dt_L_imm6_4(DataType dt);
209 };
210 
Dt_L_imm6_4(DataType dt)211 Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
212   switch (dt.GetValue()) {
213     case Untyped8:
214       SetEncodingValue(0x1);
215       break;
216     case Untyped16:
217       SetEncodingValue(0x2);
218       break;
219     case Untyped32:
220       SetEncodingValue(0x4);
221       break;
222     case Untyped64:
223       SetEncodingValue(0x8);
224       break;
225     default:
226       break;
227   }
228 }
229 
230 class Dt_imm6_1 : public EncodingValue {
231   uint32_t type_;
232 
233  public:
234   explicit Dt_imm6_1(DataType dt);
GetTypeEncodingValue() const235   uint32_t GetTypeEncodingValue() const { return type_; }
236 };
237 
Dt_imm6_1(DataType dt)238 Dt_imm6_1::Dt_imm6_1(DataType dt) {
239   switch (dt.GetValue()) {
240     case S16:
241       type_ = 0x0;
242       SetEncodingValue(0x1);
243       break;
244     case U16:
245       type_ = 0x1;
246       SetEncodingValue(0x1);
247       break;
248     case S32:
249       type_ = 0x0;
250       SetEncodingValue(0x2);
251       break;
252     case U32:
253       type_ = 0x1;
254       SetEncodingValue(0x2);
255       break;
256     case S64:
257       type_ = 0x0;
258       SetEncodingValue(0x4);
259       break;
260     case U64:
261       type_ = 0x1;
262       SetEncodingValue(0x4);
263       break;
264     default:
265       VIXL_UNREACHABLE();
266       type_ = 0x0;
267       break;
268   }
269 }
270 
271 class Dt_imm6_2 : public EncodingValue {
272   uint32_t type_;
273 
274  public:
275   explicit Dt_imm6_2(DataType dt);
GetTypeEncodingValue() const276   uint32_t GetTypeEncodingValue() const { return type_; }
277 };
278 
Dt_imm6_2(DataType dt)279 Dt_imm6_2::Dt_imm6_2(DataType dt) {
280   switch (dt.GetValue()) {
281     case S16:
282       type_ = 0x1;
283       SetEncodingValue(0x1);
284       break;
285     case S32:
286       type_ = 0x1;
287       SetEncodingValue(0x2);
288       break;
289     case S64:
290       type_ = 0x1;
291       SetEncodingValue(0x4);
292       break;
293     default:
294       VIXL_UNREACHABLE();
295       type_ = 0x0;
296       break;
297   }
298 }
299 
300 class Dt_imm6_3 : public EncodingValue {
301  public:
302   explicit Dt_imm6_3(DataType dt);
303 };
304 
Dt_imm6_3(DataType dt)305 Dt_imm6_3::Dt_imm6_3(DataType dt) {
306   switch (dt.GetValue()) {
307     case I16:
308       SetEncodingValue(0x1);
309       break;
310     case I32:
311       SetEncodingValue(0x2);
312       break;
313     case I64:
314       SetEncodingValue(0x4);
315       break;
316     default:
317       break;
318   }
319 }
320 
321 class Dt_imm6_4 : public EncodingValue {
322   uint32_t type_;
323 
324  public:
325   explicit Dt_imm6_4(DataType dt);
GetTypeEncodingValue() const326   uint32_t GetTypeEncodingValue() const { return type_; }
327 };
328 
Dt_imm6_4(DataType dt)329 Dt_imm6_4::Dt_imm6_4(DataType dt) {
330   switch (dt.GetValue()) {
331     case S8:
332       type_ = 0x0;
333       SetEncodingValue(0x1);
334       break;
335     case U8:
336       type_ = 0x1;
337       SetEncodingValue(0x1);
338       break;
339     case S16:
340       type_ = 0x0;
341       SetEncodingValue(0x2);
342       break;
343     case U16:
344       type_ = 0x1;
345       SetEncodingValue(0x2);
346       break;
347     case S32:
348       type_ = 0x0;
349       SetEncodingValue(0x4);
350       break;
351     case U32:
352       type_ = 0x1;
353       SetEncodingValue(0x4);
354       break;
355     default:
356       VIXL_UNREACHABLE();
357       type_ = 0x0;
358       break;
359   }
360 }
361 
362 class Dt_op_U_size_1 : public EncodingValue {
363  public:
364   explicit Dt_op_U_size_1(DataType dt);
365 };
366 
Dt_op_U_size_1(DataType dt)367 Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
368   switch (dt.GetValue()) {
369     case S8:
370       SetEncodingValue(0x0);
371       break;
372     case S16:
373       SetEncodingValue(0x1);
374       break;
375     case S32:
376       SetEncodingValue(0x2);
377       break;
378     case U8:
379       SetEncodingValue(0x4);
380       break;
381     case U16:
382       SetEncodingValue(0x5);
383       break;
384     case U32:
385       SetEncodingValue(0x6);
386       break;
387     case P8:
388       SetEncodingValue(0x8);
389       break;
390     case P64:
391       SetEncodingValue(0xa);
392       break;
393     default:
394       break;
395   }
396 }
397 
398 class Dt_op_size_1 : public EncodingValue {
399  public:
400   explicit Dt_op_size_1(DataType dt);
401 };
402 
Dt_op_size_1(DataType dt)403 Dt_op_size_1::Dt_op_size_1(DataType dt) {
404   switch (dt.GetValue()) {
405     case I8:
406       SetEncodingValue(0x0);
407       break;
408     case I16:
409       SetEncodingValue(0x1);
410       break;
411     case I32:
412       SetEncodingValue(0x2);
413       break;
414     case P8:
415       SetEncodingValue(0x4);
416       break;
417     default:
418       break;
419   }
420 }
421 
422 class Dt_op_size_2 : public EncodingValue {
423  public:
424   explicit Dt_op_size_2(DataType dt);
425 };
426 
Dt_op_size_2(DataType dt)427 Dt_op_size_2::Dt_op_size_2(DataType dt) {
428   switch (dt.GetValue()) {
429     case S8:
430       SetEncodingValue(0x0);
431       break;
432     case S16:
433       SetEncodingValue(0x1);
434       break;
435     case S32:
436       SetEncodingValue(0x2);
437       break;
438     case U8:
439       SetEncodingValue(0x4);
440       break;
441     case U16:
442       SetEncodingValue(0x5);
443       break;
444     case U32:
445       SetEncodingValue(0x6);
446       break;
447     default:
448       break;
449   }
450 }
451 
452 class Dt_op_size_3 : public EncodingValue {
453  public:
454   explicit Dt_op_size_3(DataType dt);
455 };
456 
Dt_op_size_3(DataType dt)457 Dt_op_size_3::Dt_op_size_3(DataType dt) {
458   switch (dt.GetValue()) {
459     case S16:
460       SetEncodingValue(0x0);
461       break;
462     case S32:
463       SetEncodingValue(0x1);
464       break;
465     case S64:
466       SetEncodingValue(0x2);
467       break;
468     case U16:
469       SetEncodingValue(0x4);
470       break;
471     case U32:
472       SetEncodingValue(0x5);
473       break;
474     case U64:
475       SetEncodingValue(0x6);
476       break;
477     default:
478       break;
479   }
480 }
481 
482 class Dt_U_imm3H_1 : public EncodingValue {
483  public:
484   explicit Dt_U_imm3H_1(DataType dt);
485 };
486 
Dt_U_imm3H_1(DataType dt)487 Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
488   switch (dt.GetValue()) {
489     case S8:
490       SetEncodingValue(0x1);
491       break;
492     case S16:
493       SetEncodingValue(0x2);
494       break;
495     case S32:
496       SetEncodingValue(0x4);
497       break;
498     case U8:
499       SetEncodingValue(0x9);
500       break;
501     case U16:
502       SetEncodingValue(0xa);
503       break;
504     case U32:
505       SetEncodingValue(0xc);
506       break;
507     default:
508       break;
509   }
510 }
511 
512 class Dt_U_opc1_opc2_1 : public EncodingValue {
513  public:
514   explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
515 };
516 
Dt_U_opc1_opc2_1(DataType dt,const DRegisterLane & lane)517 Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
518   switch (dt.GetValue()) {
519     case S8:
520       if ((lane.GetLane() & 7) != lane.GetLane()) {
521         return;
522       }
523       SetEncodingValue(0x8 | lane.GetLane());
524       break;
525     case S16:
526       if ((lane.GetLane() & 3) != lane.GetLane()) {
527         return;
528       }
529       SetEncodingValue(0x1 | (lane.GetLane() << 1));
530       break;
531     case U8:
532       if ((lane.GetLane() & 7) != lane.GetLane()) {
533         return;
534       }
535       SetEncodingValue(0x18 | lane.GetLane());
536       break;
537     case U16:
538       if ((lane.GetLane() & 3) != lane.GetLane()) {
539         return;
540       }
541       SetEncodingValue(0x11 | (lane.GetLane() << 1));
542       break;
543     case Untyped32:
544       if ((lane.GetLane() & 1) != lane.GetLane()) {
545         return;
546       }
547       SetEncodingValue(0x0 | (lane.GetLane() << 2));
548       break;
549     case kDataTypeValueNone:
550       if ((lane.GetLane() & 1) != lane.GetLane()) {
551         return;
552       }
553       SetEncodingValue(0x0 | (lane.GetLane() << 2));
554       break;
555     default:
556       break;
557   }
558 }
559 
560 class Dt_opc1_opc2_1 : public EncodingValue {
561  public:
562   explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
563 };
564 
Dt_opc1_opc2_1(DataType dt,const DRegisterLane & lane)565 Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
566   switch (dt.GetValue()) {
567     case Untyped8:
568       if ((lane.GetLane() & 7) != lane.GetLane()) {
569         return;
570       }
571       SetEncodingValue(0x8 | lane.GetLane());
572       break;
573     case Untyped16:
574       if ((lane.GetLane() & 3) != lane.GetLane()) {
575         return;
576       }
577       SetEncodingValue(0x1 | (lane.GetLane() << 1));
578       break;
579     case Untyped32:
580       if ((lane.GetLane() & 1) != lane.GetLane()) {
581         return;
582       }
583       SetEncodingValue(0x0 | (lane.GetLane() << 2));
584       break;
585     case kDataTypeValueNone:
586       if ((lane.GetLane() & 1) != lane.GetLane()) {
587         return;
588       }
589       SetEncodingValue(0x0 | (lane.GetLane() << 2));
590       break;
591     default:
592       break;
593   }
594 }
595 
596 class Dt_imm4_1 : public EncodingValue {
597  public:
598   explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
599 };
600 
Dt_imm4_1(DataType dt,const DRegisterLane & lane)601 Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
602   switch (dt.GetValue()) {
603     case Untyped8:
604       if ((lane.GetLane() & 7) != lane.GetLane()) {
605         return;
606       }
607       SetEncodingValue(0x1 | (lane.GetLane() << 1));
608       break;
609     case Untyped16:
610       if ((lane.GetLane() & 3) != lane.GetLane()) {
611         return;
612       }
613       SetEncodingValue(0x2 | (lane.GetLane() << 2));
614       break;
615     case Untyped32:
616       if ((lane.GetLane() & 1) != lane.GetLane()) {
617         return;
618       }
619       SetEncodingValue(0x4 | (lane.GetLane() << 3));
620       break;
621     default:
622       break;
623   }
624 }
625 
626 class Dt_B_E_1 : public EncodingValue {
627  public:
628   explicit Dt_B_E_1(DataType dt);
629 };
630 
Dt_B_E_1(DataType dt)631 Dt_B_E_1::Dt_B_E_1(DataType dt) {
632   switch (dt.GetValue()) {
633     case Untyped8:
634       SetEncodingValue(0x2);
635       break;
636     case Untyped16:
637       SetEncodingValue(0x1);
638       break;
639     case Untyped32:
640       SetEncodingValue(0x0);
641       break;
642     default:
643       break;
644   }
645 }
646 
647 class Dt_op_1 : public EncodingValue {
648  public:
649   Dt_op_1(DataType dt1, DataType dt2);
650 };
651 
Dt_op_1(DataType dt1,DataType dt2)652 Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
653   if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
654     SetEncodingValue(0x0);
655     return;
656   }
657   if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
658     SetEncodingValue(0x1);
659     return;
660   }
661   if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
662     SetEncodingValue(0x2);
663     return;
664   }
665   if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
666     SetEncodingValue(0x3);
667     return;
668   }
669 }
670 
671 class Dt_op_2 : public EncodingValue {
672  public:
673   explicit Dt_op_2(DataType dt);
674 };
675 
Dt_op_2(DataType dt)676 Dt_op_2::Dt_op_2(DataType dt) {
677   switch (dt.GetValue()) {
678     case U32:
679       SetEncodingValue(0x0);
680       break;
681     case S32:
682       SetEncodingValue(0x1);
683       break;
684     default:
685       break;
686   }
687 }
688 
689 class Dt_op_3 : public EncodingValue {
690  public:
691   explicit Dt_op_3(DataType dt);
692 };
693 
Dt_op_3(DataType dt)694 Dt_op_3::Dt_op_3(DataType dt) {
695   switch (dt.GetValue()) {
696     case S32:
697       SetEncodingValue(0x0);
698       break;
699     case U32:
700       SetEncodingValue(0x1);
701       break;
702     default:
703       break;
704   }
705 }
706 
707 class Dt_U_sx_1 : public EncodingValue {
708  public:
709   explicit Dt_U_sx_1(DataType dt);
710 };
711 
Dt_U_sx_1(DataType dt)712 Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
713   switch (dt.GetValue()) {
714     case S16:
715       SetEncodingValue(0x0);
716       break;
717     case S32:
718       SetEncodingValue(0x1);
719       break;
720     case U16:
721       SetEncodingValue(0x2);
722       break;
723     case U32:
724       SetEncodingValue(0x3);
725       break;
726     default:
727       break;
728   }
729 }
730 
731 class Dt_op_U_1 : public EncodingValue {
732  public:
733   Dt_op_U_1(DataType dt1, DataType dt2);
734 };
735 
Dt_op_U_1(DataType dt1,DataType dt2)736 Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
737   if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
738     SetEncodingValue(0x0);
739     return;
740   }
741   if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
742     SetEncodingValue(0x1);
743     return;
744   }
745   if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
746     SetEncodingValue(0x2);
747     return;
748   }
749   if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
750     SetEncodingValue(0x3);
751     return;
752   }
753 }
754 
755 class Dt_sz_1 : public EncodingValue {
756  public:
757   explicit Dt_sz_1(DataType dt);
758 };
759 
Dt_sz_1(DataType dt)760 Dt_sz_1::Dt_sz_1(DataType dt) {
761   switch (dt.GetValue()) {
762     case F32:
763       SetEncodingValue(0x0);
764       break;
765     default:
766       break;
767   }
768 }
769 
770 class Dt_F_size_1 : public EncodingValue {
771  public:
772   explicit Dt_F_size_1(DataType dt);
773 };
774 
Dt_F_size_1(DataType dt)775 Dt_F_size_1::Dt_F_size_1(DataType dt) {
776   switch (dt.GetValue()) {
777     case S8:
778       SetEncodingValue(0x0);
779       break;
780     case S16:
781       SetEncodingValue(0x1);
782       break;
783     case S32:
784       SetEncodingValue(0x2);
785       break;
786     case F32:
787       SetEncodingValue(0x6);
788       break;
789     default:
790       break;
791   }
792 }
793 
794 class Dt_F_size_2 : public EncodingValue {
795  public:
796   explicit Dt_F_size_2(DataType dt);
797 };
798 
Dt_F_size_2(DataType dt)799 Dt_F_size_2::Dt_F_size_2(DataType dt) {
800   switch (dt.GetValue()) {
801     case I8:
802       SetEncodingValue(0x0);
803       break;
804     case I16:
805       SetEncodingValue(0x1);
806       break;
807     case I32:
808       SetEncodingValue(0x2);
809       break;
810     case F32:
811       SetEncodingValue(0x6);
812       break;
813     default:
814       break;
815   }
816 }
817 
818 class Dt_F_size_3 : public EncodingValue {
819  public:
820   explicit Dt_F_size_3(DataType dt);
821 };
822 
Dt_F_size_3(DataType dt)823 Dt_F_size_3::Dt_F_size_3(DataType dt) {
824   switch (dt.GetValue()) {
825     case I16:
826       SetEncodingValue(0x1);
827       break;
828     case I32:
829       SetEncodingValue(0x2);
830       break;
831     case F32:
832       SetEncodingValue(0x6);
833       break;
834     default:
835       break;
836   }
837 }
838 
839 class Dt_F_size_4 : public EncodingValue {
840  public:
841   explicit Dt_F_size_4(DataType dt);
842 };
843 
Dt_F_size_4(DataType dt)844 Dt_F_size_4::Dt_F_size_4(DataType dt) {
845   switch (dt.GetValue()) {
846     case U32:
847       SetEncodingValue(0x2);
848       break;
849     case F32:
850       SetEncodingValue(0x6);
851       break;
852     default:
853       break;
854   }
855 }
856 
857 class Dt_U_size_1 : public EncodingValue {
858  public:
859   explicit Dt_U_size_1(DataType dt);
860 };
861 
Dt_U_size_1(DataType dt)862 Dt_U_size_1::Dt_U_size_1(DataType dt) {
863   switch (dt.GetValue()) {
864     case S8:
865       SetEncodingValue(0x0);
866       break;
867     case S16:
868       SetEncodingValue(0x1);
869       break;
870     case S32:
871       SetEncodingValue(0x2);
872       break;
873     case U8:
874       SetEncodingValue(0x4);
875       break;
876     case U16:
877       SetEncodingValue(0x5);
878       break;
879     case U32:
880       SetEncodingValue(0x6);
881       break;
882     default:
883       break;
884   }
885 }
886 
887 class Dt_U_size_2 : public EncodingValue {
888  public:
889   explicit Dt_U_size_2(DataType dt);
890 };
891 
Dt_U_size_2(DataType dt)892 Dt_U_size_2::Dt_U_size_2(DataType dt) {
893   switch (dt.GetValue()) {
894     case S16:
895       SetEncodingValue(0x1);
896       break;
897     case S32:
898       SetEncodingValue(0x2);
899       break;
900     case U16:
901       SetEncodingValue(0x5);
902       break;
903     case U32:
904       SetEncodingValue(0x6);
905       break;
906     default:
907       break;
908   }
909 }
910 
911 class Dt_U_size_3 : public EncodingValue {
912  public:
913   explicit Dt_U_size_3(DataType dt);
914 };
915 
Dt_U_size_3(DataType dt)916 Dt_U_size_3::Dt_U_size_3(DataType dt) {
917   switch (dt.GetValue()) {
918     case S8:
919       SetEncodingValue(0x0);
920       break;
921     case S16:
922       SetEncodingValue(0x1);
923       break;
924     case S32:
925       SetEncodingValue(0x2);
926       break;
927     case S64:
928       SetEncodingValue(0x3);
929       break;
930     case U8:
931       SetEncodingValue(0x4);
932       break;
933     case U16:
934       SetEncodingValue(0x5);
935       break;
936     case U32:
937       SetEncodingValue(0x6);
938       break;
939     case U64:
940       SetEncodingValue(0x7);
941       break;
942     default:
943       break;
944   }
945 }
946 
947 class Dt_size_1 : public EncodingValue {
948  public:
949   explicit Dt_size_1(DataType dt);
950 };
951 
Dt_size_1(DataType dt)952 Dt_size_1::Dt_size_1(DataType dt) {
953   switch (dt.GetValue()) {
954     case Untyped8:
955       SetEncodingValue(0x0);
956       break;
957     default:
958       break;
959   }
960 }
961 
962 class Dt_size_2 : public EncodingValue {
963  public:
964   explicit Dt_size_2(DataType dt);
965 };
966 
Dt_size_2(DataType dt)967 Dt_size_2::Dt_size_2(DataType dt) {
968   switch (dt.GetValue()) {
969     case I8:
970       SetEncodingValue(0x0);
971       break;
972     case I16:
973       SetEncodingValue(0x1);
974       break;
975     case I32:
976       SetEncodingValue(0x2);
977       break;
978     case I64:
979       SetEncodingValue(0x3);
980       break;
981     default:
982       break;
983   }
984 }
985 
986 class Dt_size_3 : public EncodingValue {
987  public:
988   explicit Dt_size_3(DataType dt);
989 };
990 
Dt_size_3(DataType dt)991 Dt_size_3::Dt_size_3(DataType dt) {
992   switch (dt.GetValue()) {
993     case I16:
994       SetEncodingValue(0x0);
995       break;
996     case I32:
997       SetEncodingValue(0x1);
998       break;
999     case I64:
1000       SetEncodingValue(0x2);
1001       break;
1002     default:
1003       break;
1004   }
1005 }
1006 
1007 class Dt_size_4 : public EncodingValue {
1008  public:
1009   explicit Dt_size_4(DataType dt);
1010 };
1011 
Dt_size_4(DataType dt)1012 Dt_size_4::Dt_size_4(DataType dt) {
1013   switch (dt.GetValue()) {
1014     case I8:
1015       SetEncodingValue(0x0);
1016       break;
1017     case I16:
1018       SetEncodingValue(0x1);
1019       break;
1020     case I32:
1021       SetEncodingValue(0x2);
1022       break;
1023     default:
1024       break;
1025   }
1026 }
1027 
1028 class Dt_size_5 : public EncodingValue {
1029  public:
1030   explicit Dt_size_5(DataType dt);
1031 };
1032 
Dt_size_5(DataType dt)1033 Dt_size_5::Dt_size_5(DataType dt) {
1034   switch (dt.GetValue()) {
1035     case S8:
1036       SetEncodingValue(0x0);
1037       break;
1038     case S16:
1039       SetEncodingValue(0x1);
1040       break;
1041     case S32:
1042       SetEncodingValue(0x2);
1043       break;
1044     default:
1045       break;
1046   }
1047 }
1048 
1049 class Dt_size_6 : public EncodingValue {
1050  public:
1051   explicit Dt_size_6(DataType dt);
1052 };
1053 
Dt_size_6(DataType dt)1054 Dt_size_6::Dt_size_6(DataType dt) {
1055   switch (dt.GetValue()) {
1056     case Untyped8:
1057       SetEncodingValue(0x0);
1058       break;
1059     case Untyped16:
1060       SetEncodingValue(0x1);
1061       break;
1062     case Untyped32:
1063       SetEncodingValue(0x2);
1064       break;
1065     case Untyped64:
1066       SetEncodingValue(0x3);
1067       break;
1068     default:
1069       break;
1070   }
1071 }
1072 
1073 class Dt_size_7 : public EncodingValue {
1074  public:
1075   explicit Dt_size_7(DataType dt);
1076 };
1077 
Dt_size_7(DataType dt)1078 Dt_size_7::Dt_size_7(DataType dt) {
1079   switch (dt.GetValue()) {
1080     case Untyped8:
1081       SetEncodingValue(0x0);
1082       break;
1083     case Untyped16:
1084       SetEncodingValue(0x1);
1085       break;
1086     case Untyped32:
1087       SetEncodingValue(0x2);
1088       break;
1089     default:
1090       break;
1091   }
1092 }
1093 
1094 class Dt_size_8 : public EncodingValue {
1095  public:
1096   Dt_size_8(DataType dt, Alignment align);
1097 };
1098 
Dt_size_8(DataType dt,Alignment align)1099 Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
1100   switch (dt.GetValue()) {
1101     case Untyped8:
1102       SetEncodingValue(0x0);
1103       break;
1104     case Untyped16:
1105       SetEncodingValue(0x1);
1106       break;
1107     case Untyped32:
1108       if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
1109         SetEncodingValue(0x2);
1110       } else if (align.Is(k128BitAlign)) {
1111         SetEncodingValue(0x3);
1112       }
1113       break;
1114     default:
1115       break;
1116   }
1117 }
1118 
1119 class Dt_size_9 : public EncodingValue {
1120   uint32_t type_;
1121 
1122  public:
1123   explicit Dt_size_9(DataType dt);
GetTypeEncodingValue() const1124   uint32_t GetTypeEncodingValue() const { return type_; }
1125 };
1126 
Dt_size_9(DataType dt)1127 Dt_size_9::Dt_size_9(DataType dt) {
1128   switch (dt.GetValue()) {
1129     case I16:
1130       type_ = 0x0;
1131       SetEncodingValue(0x1);
1132       break;
1133     case I32:
1134       type_ = 0x0;
1135       SetEncodingValue(0x2);
1136       break;
1137     case F32:
1138       type_ = 0x1;
1139       SetEncodingValue(0x2);
1140       break;
1141     default:
1142       VIXL_UNREACHABLE();
1143       type_ = 0x0;
1144       break;
1145   }
1146 }
1147 
1148 class Dt_size_10 : public EncodingValue {
1149  public:
1150   explicit Dt_size_10(DataType dt);
1151 };
1152 
Dt_size_10(DataType dt)1153 Dt_size_10::Dt_size_10(DataType dt) {
1154   switch (dt.GetValue()) {
1155     case S8:
1156     case U8:
1157     case I8:
1158       SetEncodingValue(0x0);
1159       break;
1160     case S16:
1161     case U16:
1162     case I16:
1163       SetEncodingValue(0x1);
1164       break;
1165     case S32:
1166     case U32:
1167     case I32:
1168       SetEncodingValue(0x2);
1169       break;
1170     default:
1171       break;
1172   }
1173 }
1174 
1175 class Dt_size_11 : public EncodingValue {
1176   uint32_t type_;
1177 
1178  public:
1179   explicit Dt_size_11(DataType dt);
GetTypeEncodingValue() const1180   uint32_t GetTypeEncodingValue() const { return type_; }
1181 };
1182 
Dt_size_11(DataType dt)1183 Dt_size_11::Dt_size_11(DataType dt) {
1184   switch (dt.GetValue()) {
1185     case S16:
1186       type_ = 0x0;
1187       SetEncodingValue(0x1);
1188       break;
1189     case U16:
1190       type_ = 0x1;
1191       SetEncodingValue(0x1);
1192       break;
1193     case S32:
1194       type_ = 0x0;
1195       SetEncodingValue(0x2);
1196       break;
1197     case U32:
1198       type_ = 0x1;
1199       SetEncodingValue(0x2);
1200       break;
1201     default:
1202       VIXL_UNREACHABLE();
1203       type_ = 0x0;
1204       break;
1205   }
1206 }
1207 
1208 class Dt_size_12 : public EncodingValue {
1209   uint32_t type_;
1210 
1211  public:
1212   explicit Dt_size_12(DataType dt);
GetTypeEncodingValue() const1213   uint32_t GetTypeEncodingValue() const { return type_; }
1214 };
1215 
Dt_size_12(DataType dt)1216 Dt_size_12::Dt_size_12(DataType dt) {
1217   switch (dt.GetValue()) {
1218     case S8:
1219       type_ = 0x0;
1220       SetEncodingValue(0x0);
1221       break;
1222     case U8:
1223       type_ = 0x1;
1224       SetEncodingValue(0x0);
1225       break;
1226     case S16:
1227       type_ = 0x0;
1228       SetEncodingValue(0x1);
1229       break;
1230     case U16:
1231       type_ = 0x1;
1232       SetEncodingValue(0x1);
1233       break;
1234     case S32:
1235       type_ = 0x0;
1236       SetEncodingValue(0x2);
1237       break;
1238     case U32:
1239       type_ = 0x1;
1240       SetEncodingValue(0x2);
1241       break;
1242     default:
1243       VIXL_UNREACHABLE();
1244       type_ = 0x0;
1245       break;
1246   }
1247 }
1248 
1249 class Dt_size_13 : public EncodingValue {
1250  public:
1251   explicit Dt_size_13(DataType dt);
1252 };
1253 
Dt_size_13(DataType dt)1254 Dt_size_13::Dt_size_13(DataType dt) {
1255   switch (dt.GetValue()) {
1256     case S16:
1257       SetEncodingValue(0x1);
1258       break;
1259     case S32:
1260       SetEncodingValue(0x2);
1261       break;
1262     default:
1263       break;
1264   }
1265 }
1266 
1267 class Dt_size_14 : public EncodingValue {
1268  public:
1269   explicit Dt_size_14(DataType dt);
1270 };
1271 
Dt_size_14(DataType dt)1272 Dt_size_14::Dt_size_14(DataType dt) {
1273   switch (dt.GetValue()) {
1274     case S16:
1275       SetEncodingValue(0x0);
1276       break;
1277     case S32:
1278       SetEncodingValue(0x1);
1279       break;
1280     case S64:
1281       SetEncodingValue(0x2);
1282       break;
1283     default:
1284       break;
1285   }
1286 }
1287 
1288 class Dt_size_15 : public EncodingValue {
1289  public:
1290   explicit Dt_size_15(DataType dt);
1291 };
1292 
Dt_size_15(DataType dt)1293 Dt_size_15::Dt_size_15(DataType dt) {
1294   switch (dt.GetValue()) {
1295     case Untyped8:
1296       SetEncodingValue(0x0);
1297       break;
1298     case Untyped16:
1299       SetEncodingValue(0x1);
1300       break;
1301     default:
1302       break;
1303   }
1304 }
1305 
1306 class Dt_size_16 : public EncodingValue {
1307  public:
1308   explicit Dt_size_16(DataType dt);
1309 };
1310 
Dt_size_16(DataType dt)1311 Dt_size_16::Dt_size_16(DataType dt) {
1312   switch (dt.GetValue()) {
1313     case F32:
1314       SetEncodingValue(0x2);
1315       break;
1316     default:
1317       break;
1318   }
1319 }
1320 
1321 class Dt_size_17 : public EncodingValue {
1322  public:
1323   explicit Dt_size_17(DataType dt);
1324 };
1325 
Dt_size_17(DataType dt)1326 Dt_size_17::Dt_size_17(DataType dt) {
1327   switch (dt.GetValue()) {
1328     case I8:
1329       SetEncodingValue(0x0);
1330       break;
1331     case I16:
1332       SetEncodingValue(0x1);
1333       break;
1334     case I32:
1335       SetEncodingValue(0x2);
1336       break;
1337     default:
1338       break;
1339   }
1340 }
1341 
1342 class Index_1 : public EncodingValue {
1343  public:
1344   Index_1(const NeonRegisterList& nreglist, DataType dt);
1345 };
1346 
Index_1(const NeonRegisterList & nreglist,DataType dt)1347 Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1348   switch (dt.GetValue()) {
1349     case Untyped8: {
1350       if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1351         return;
1352       }
1353       uint32_t value = nreglist.GetTransferLane() << 1;
1354       if (!nreglist.IsSingleSpaced()) return;
1355       SetEncodingValue(value);
1356       break;
1357     }
1358     case Untyped16: {
1359       if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1360         return;
1361       }
1362       uint32_t value = nreglist.GetTransferLane() << 2;
1363       if (nreglist.IsDoubleSpaced()) value |= 2;
1364       SetEncodingValue(value);
1365       break;
1366     }
1367     case Untyped32: {
1368       if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1369         return;
1370       }
1371       uint32_t value = nreglist.GetTransferLane() << 3;
1372       if (nreglist.IsDoubleSpaced()) value |= 4;
1373       SetEncodingValue(value);
1374       break;
1375     }
1376     default:
1377       break;
1378   }
1379 }
1380 
1381 class Align_index_align_1 : public EncodingValue {
1382  public:
1383   Align_index_align_1(Alignment align,
1384                       const NeonRegisterList& nreglist,
1385                       DataType dt);
1386 };
1387 
Align_index_align_1(Alignment align,const NeonRegisterList & nreglist,DataType dt)1388 Align_index_align_1::Align_index_align_1(Alignment align,
1389                                          const NeonRegisterList& nreglist,
1390                                          DataType dt) {
1391   switch (dt.GetValue()) {
1392     case Untyped8: {
1393       uint32_t value;
1394       if (align.GetType() == kNoAlignment) {
1395         value = 0;
1396       } else {
1397         return;
1398       }
1399       if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1400         return;
1401       }
1402       value |= nreglist.GetTransferLane() << 1;
1403       SetEncodingValue(value);
1404       break;
1405     }
1406     case Untyped16: {
1407       uint32_t value;
1408       if (align.GetType() == k16BitAlign) {
1409         value = 1;
1410       } else if (align.GetType() == kNoAlignment) {
1411         value = 0;
1412       } else {
1413         return;
1414       }
1415       if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1416         return;
1417       }
1418       value |= nreglist.GetTransferLane() << 2;
1419       SetEncodingValue(value);
1420       break;
1421     }
1422     case Untyped32: {
1423       uint32_t value;
1424       if (align.GetType() == k32BitAlign) {
1425         value = 3;
1426       } else if (align.GetType() == kNoAlignment) {
1427         value = 0;
1428       } else {
1429         return;
1430       }
1431       if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1432         return;
1433       }
1434       value |= nreglist.GetTransferLane() << 3;
1435       SetEncodingValue(value);
1436       break;
1437     }
1438     default:
1439       break;
1440   }
1441 }
1442 
1443 class Align_index_align_2 : public EncodingValue {
1444  public:
1445   Align_index_align_2(Alignment align,
1446                       const NeonRegisterList& nreglist,
1447                       DataType dt);
1448 };
1449 
Align_index_align_2(Alignment align,const NeonRegisterList & nreglist,DataType dt)1450 Align_index_align_2::Align_index_align_2(Alignment align,
1451                                          const NeonRegisterList& nreglist,
1452                                          DataType dt) {
1453   switch (dt.GetValue()) {
1454     case Untyped8: {
1455       uint32_t value;
1456       if (align.GetType() == k16BitAlign) {
1457         value = 1;
1458       } else if (align.GetType() == kNoAlignment) {
1459         value = 0;
1460       } else {
1461         return;
1462       }
1463       if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1464         return;
1465       }
1466       value |= nreglist.GetTransferLane() << 1;
1467       if (!nreglist.IsSingleSpaced()) return;
1468       SetEncodingValue(value);
1469       break;
1470     }
1471     case Untyped16: {
1472       uint32_t value;
1473       if (align.GetType() == k32BitAlign) {
1474         value = 1;
1475       } else if (align.GetType() == kNoAlignment) {
1476         value = 0;
1477       } else {
1478         return;
1479       }
1480       if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1481         return;
1482       }
1483       value |= nreglist.GetTransferLane() << 2;
1484       if (nreglist.IsDoubleSpaced()) value |= 2;
1485       SetEncodingValue(value);
1486       break;
1487     }
1488     case Untyped32: {
1489       uint32_t value;
1490       if (align.GetType() == k64BitAlign) {
1491         value = 1;
1492       } else if (align.GetType() == kNoAlignment) {
1493         value = 0;
1494       } else {
1495         return;
1496       }
1497       if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1498         return;
1499       }
1500       value |= nreglist.GetTransferLane() << 3;
1501       if (nreglist.IsDoubleSpaced()) value |= 4;
1502       SetEncodingValue(value);
1503       break;
1504     }
1505     default:
1506       break;
1507   }
1508 }
1509 
1510 class Align_index_align_3 : public EncodingValue {
1511  public:
1512   Align_index_align_3(Alignment align,
1513                       const NeonRegisterList& nreglist,
1514                       DataType dt);
1515 };
1516 
Align_index_align_3(Alignment align,const NeonRegisterList & nreglist,DataType dt)1517 Align_index_align_3::Align_index_align_3(Alignment align,
1518                                          const NeonRegisterList& nreglist,
1519                                          DataType dt) {
1520   switch (dt.GetValue()) {
1521     case Untyped8: {
1522       uint32_t value;
1523       if (align.GetType() == k32BitAlign) {
1524         value = 1;
1525       } else if (align.GetType() == kNoAlignment) {
1526         value = 0;
1527       } else {
1528         return;
1529       }
1530       if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1531         return;
1532       }
1533       value |= nreglist.GetTransferLane() << 1;
1534       if (!nreglist.IsSingleSpaced()) return;
1535       SetEncodingValue(value);
1536       break;
1537     }
1538     case Untyped16: {
1539       uint32_t value;
1540       if (align.GetType() == k64BitAlign) {
1541         value = 1;
1542       } else if (align.GetType() == kNoAlignment) {
1543         value = 0;
1544       } else {
1545         return;
1546       }
1547       if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1548         return;
1549       }
1550       value |= nreglist.GetTransferLane() << 2;
1551       if (nreglist.IsDoubleSpaced()) value |= 2;
1552       SetEncodingValue(value);
1553       break;
1554     }
1555     case Untyped32: {
1556       uint32_t value;
1557       if (align.GetType() == k64BitAlign) {
1558         value = 1;
1559       } else if (align.GetType() == k128BitAlign) {
1560         value = 2;
1561       } else if (align.GetType() == kNoAlignment) {
1562         value = 0;
1563       } else {
1564         return;
1565       }
1566       if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1567         return;
1568       }
1569       value |= nreglist.GetTransferLane() << 3;
1570       if (nreglist.IsDoubleSpaced()) value |= 4;
1571       SetEncodingValue(value);
1572       break;
1573     }
1574     default:
1575       break;
1576   }
1577 }
1578 
1579 class Align_a_1 : public EncodingValue {
1580  public:
1581   Align_a_1(Alignment align, DataType dt);
1582 };
1583 
Align_a_1(Alignment align,DataType dt)1584 Align_a_1::Align_a_1(Alignment align, DataType dt) {
1585   switch (align.GetType()) {
1586     case k16BitAlign:
1587       if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1588       break;
1589     case k32BitAlign:
1590       if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1591       break;
1592     case kNoAlignment:
1593       SetEncodingValue(0x0);
1594       break;
1595     default:
1596       break;
1597   }
1598 }
1599 
1600 class Align_a_2 : public EncodingValue {
1601  public:
1602   Align_a_2(Alignment align, DataType dt);
1603 };
1604 
Align_a_2(Alignment align,DataType dt)1605 Align_a_2::Align_a_2(Alignment align, DataType dt) {
1606   switch (align.GetType()) {
1607     case k16BitAlign:
1608       if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1609       break;
1610     case k32BitAlign:
1611       if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1612       break;
1613     case k64BitAlign:
1614       if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1615       break;
1616     case kNoAlignment:
1617       SetEncodingValue(0x0);
1618       break;
1619     default:
1620       break;
1621   }
1622 }
1623 
1624 class Align_a_3 : public EncodingValue {
1625  public:
1626   Align_a_3(Alignment align, DataType dt);
1627 };
1628 
Align_a_3(Alignment align,DataType dt)1629 Align_a_3::Align_a_3(Alignment align, DataType dt) {
1630   switch (align.GetType()) {
1631     case k32BitAlign:
1632       if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1633       break;
1634     case k64BitAlign:
1635       if (dt.Is(Untyped16))
1636         SetEncodingValue(0x1);
1637       else if (dt.Is(Untyped32))
1638         SetEncodingValue(0x1);
1639       break;
1640     case k128BitAlign:
1641       if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1642       break;
1643     case kNoAlignment:
1644       SetEncodingValue(0x0);
1645       break;
1646     default:
1647       break;
1648   }
1649 }
1650 
1651 class Align_align_1 : public EncodingValue {
1652  public:
1653   Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1654 };
1655 
Align_align_1(Alignment align,const NeonRegisterList & nreglist)1656 Align_align_1::Align_align_1(Alignment align,
1657                              const NeonRegisterList& nreglist) {
1658   switch (align.GetType()) {
1659     case k64BitAlign:
1660       SetEncodingValue(0x1);
1661       break;
1662     case k128BitAlign:
1663       if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1664         SetEncodingValue(0x2);
1665       break;
1666     case k256BitAlign:
1667       if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1668         SetEncodingValue(0x3);
1669       break;
1670     case kNoAlignment:
1671       SetEncodingValue(0x0);
1672       break;
1673     default:
1674       break;
1675   }
1676 }
1677 
1678 class Align_align_2 : public EncodingValue {
1679  public:
1680   Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1681 };
1682 
Align_align_2(Alignment align,const NeonRegisterList & nreglist)1683 Align_align_2::Align_align_2(Alignment align,
1684                              const NeonRegisterList& nreglist) {
1685   switch (align.GetType()) {
1686     case k64BitAlign:
1687       SetEncodingValue(0x1);
1688       break;
1689     case k128BitAlign:
1690       SetEncodingValue(0x2);
1691       break;
1692     case k256BitAlign:
1693       if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1694       break;
1695     case kNoAlignment:
1696       SetEncodingValue(0x0);
1697       break;
1698     default:
1699       break;
1700   }
1701 }
1702 
1703 class Align_align_3 : public EncodingValue {
1704  public:
1705   explicit Align_align_3(Alignment align);
1706 };
1707 
Align_align_3(Alignment align)1708 Align_align_3::Align_align_3(Alignment align) {
1709   switch (align.GetType()) {
1710     case k64BitAlign:
1711       SetEncodingValue(0x1);
1712       break;
1713     case kNoAlignment:
1714       SetEncodingValue(0x0);
1715       break;
1716     default:
1717       break;
1718   }
1719 }
1720 
1721 class Align_align_4 : public EncodingValue {
1722  public:
1723   explicit Align_align_4(Alignment align);
1724 };
1725 
Align_align_4(Alignment align)1726 Align_align_4::Align_align_4(Alignment align) {
1727   switch (align.GetType()) {
1728     case k64BitAlign:
1729       SetEncodingValue(0x1);
1730       break;
1731     case k128BitAlign:
1732       SetEncodingValue(0x2);
1733       break;
1734     case k256BitAlign:
1735       SetEncodingValue(0x3);
1736       break;
1737     case kNoAlignment:
1738       SetEncodingValue(0x0);
1739       break;
1740     default:
1741       break;
1742   }
1743 }
1744 
1745 class Align_align_5 : public EncodingValue {
1746  public:
1747   Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1748 };
1749 
Align_align_5(Alignment align,const NeonRegisterList & nreglist)1750 Align_align_5::Align_align_5(Alignment align,
1751                              const NeonRegisterList& nreglist) {
1752   switch (align.GetType()) {
1753     case k64BitAlign:
1754       SetEncodingValue(0x1);
1755       break;
1756     case k128BitAlign:
1757       if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1758         SetEncodingValue(0x2);
1759       break;
1760     case k256BitAlign:
1761       if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1762       break;
1763     case kNoAlignment:
1764       SetEncodingValue(0x0);
1765       break;
1766     default:
1767       break;
1768   }
1769 }
1770 
1771 
1772 // CBNZ{<q>} <Rn>, <label> ; T1
1773 // CBZ{<q>} <Rn>, <label> ; T1
1774 static const struct ReferenceInfo kT16CbzInfo =
1775     {k16BitT32InstructionSizeInBytes,
1776      0,    // Min offset.
1777      126,  // Max offset.
1778      2,    // Alignment.
1779      ReferenceInfo::kDontAlignPc};
1780 
1781 
1782 // B<c>{<q>} <label> ; T1
1783 static const struct ReferenceInfo kT16ConditionalBranchInfo =
1784     {k16BitT32InstructionSizeInBytes,
1785      -256,  // Min offset.
1786      254,   // Max offset.
1787      2,     // Alignment.
1788      ReferenceInfo::kDontAlignPc};
1789 
1790 
1791 // ADR{<c>}{<q>} <Rd>, <label> ; T1
1792 // LDR{<c>}{<q>} <Rt>, <label> ; T1
1793 static const struct ReferenceInfo kT16DataInfo =
1794     {k16BitT32InstructionSizeInBytes,
1795      0,     // Min offset.
1796      1020,  // Max offset.
1797      4,     // Alignment.
1798      ReferenceInfo::kAlignPc};
1799 
1800 
1801 // B{<c>}{<q>} <label> ; T2
1802 static const struct ReferenceInfo kT16BranchInfo =
1803     {k16BitT32InstructionSizeInBytes,
1804      -2048,  // Min offset.
1805      2046,   // Max offset.
1806      2,      // Alignment.
1807      ReferenceInfo::kDontAlignPc};
1808 
1809 
1810 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
1811 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
1812 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
1813 static const struct ReferenceInfo kT32DataInfo =
1814     {k32BitT32InstructionSizeInBytes,
1815      -1020,  // Min offset.
1816      1020,   // Max offset.
1817      4,      // Alignment.
1818      ReferenceInfo::kAlignPc};
1819 
1820 
1821 // ADR{<c>}{<q>} <Rd>, <label> ; T3
1822 // LDR{<c>}{<q>} <Rt>, <label> ; T2
1823 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
1824 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
1825 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
1826 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
1827 // PLD{<c>}{<q>} <label> ; T1
1828 // PLI{<c>}{<q>} <label> ; T3
1829 static const struct ReferenceInfo kT32FarDataInfo =
1830     {k32BitT32InstructionSizeInBytes,
1831      -4095,  // Min offset.
1832      4095,   // Max offset.
1833      1,      // Alignment.
1834      ReferenceInfo::kAlignPc};
1835 
1836 
1837 // B<c>{<q>} <label> ; T3
1838 static const struct ReferenceInfo kT32ConditionalBranchInfo =
1839     {k32BitT32InstructionSizeInBytes,
1840      -1048576,  // Min offset.
1841      1048574,   // Max offset.
1842      2,         // Alignment.
1843      ReferenceInfo::kDontAlignPc};
1844 
1845 
1846 // B{<c>}{<q>} <label> ; T4
1847 // BL{<c>}{<q>} <label> ; T1
1848 static const struct ReferenceInfo kT32BranchInfo =
1849     {k32BitT32InstructionSizeInBytes,
1850      -16777216,  // Min offset.
1851      16777214,   // Max offset.
1852      2,          // Alignment.
1853      ReferenceInfo::kDontAlignPc};
1854 
1855 
1856 // BLX{<c>}{<q>} <label> ; T2
1857 static const struct ReferenceInfo kT32BlxInfo =
1858     {k32BitT32InstructionSizeInBytes,
1859      -16777216,  // Min offset.
1860      16777212,   // Max offset.
1861      4,          // Alignment.
1862      ReferenceInfo::kAlignPc};
1863 
1864 
1865 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
1866 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
1867 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
1868 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
1869 static const struct ReferenceInfo kA32VeryNearDataInfo =
1870     {kA32InstructionSizeInBytes,
1871      -255,  // Min offset.
1872      255,   // Max offset.
1873      1,     // Alignment.
1874      ReferenceInfo::kAlignPc};
1875 
1876 
1877 // ADR{<c>}{<q>} <Rd>, <label> ; A1
1878 static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes,
1879                                                  -256,  // Min offset.
1880                                                  256,   // Max offset.
1881                                                  1,     // Alignment.
1882                                                  ReferenceInfo::kAlignPc};
1883 
1884 
1885 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
1886 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
1887 static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes,
1888                                                   -1020,  // Min offset.
1889                                                   1020,   // Max offset.
1890                                                   4,      // Alignment.
1891                                                   ReferenceInfo::kAlignPc};
1892 
1893 
1894 // LDR{<c>}{<q>} <Rt>, <label> ; A1
1895 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
1896 // PLD{<c>}{<q>} <label> ; A1
1897 // PLI{<c>}{<q>} <label> ; A1
1898 static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes,
1899                                                      -4095,  // Min offset.
1900                                                      4095,   // Max offset.
1901                                                      1,      // Alignment.
1902                                                      ReferenceInfo::kAlignPc};
1903 
1904 
1905 // B{<c>}{<q>} <label> ; A1
1906 // BL{<c>}{<q>} <label> ; A1
1907 static const struct ReferenceInfo kA32BranchInfo =
1908     {kA32InstructionSizeInBytes,
1909      -33554432,  // Min offset.
1910      33554428,   // Max offset.
1911      4,          // Alignment.
1912      ReferenceInfo::kDontAlignPc};
1913 
1914 
1915 // BLX{<c>}{<q>} <label> ; A2
1916 static const struct ReferenceInfo kA32BlxInfo = {kA32InstructionSizeInBytes,
1917                                                  -33554432,  // Min offset.
1918                                                  33554430,   // Max offset.
1919                                                  2,          // Alignment.
1920                                                  ReferenceInfo::kAlignPc};
1921 
1922 
adc(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)1923 void Assembler::adc(Condition cond,
1924                     EncodingSize size,
1925                     Register rd,
1926                     Register rn,
1927                     const Operand& operand) {
1928   VIXL_ASSERT(AllowAssembler());
1929   CheckIT(cond);
1930   if (operand.IsImmediate()) {
1931     uint32_t imm = operand.GetImmediate();
1932     if (IsUsingT32()) {
1933       ImmediateT32 immediate_t32(imm);
1934       // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1935       if (!size.IsNarrow() && immediate_t32.IsValid() &&
1936           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
1937         EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1938                    (immediate_t32.GetEncodingValue() & 0xff) |
1939                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1940                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1941         AdvanceIT();
1942         return;
1943       }
1944     } else {
1945       ImmediateA32 immediate_a32(imm);
1946       // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1947       if (immediate_a32.IsValid() && cond.IsNotNever()) {
1948         EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1949                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1950                 immediate_a32.GetEncodingValue());
1951         return;
1952       }
1953     }
1954   }
1955   if (operand.IsImmediateShiftedRegister()) {
1956     Register rm = operand.GetBaseRegister();
1957     if (operand.IsPlainRegister()) {
1958       if (IsUsingT32()) {
1959         // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1960         if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1961             rm.IsLow()) {
1962           EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1963           AdvanceIT();
1964           return;
1965         }
1966       }
1967     }
1968     Shift shift = operand.GetShift();
1969     uint32_t amount = operand.GetShiftAmount();
1970     if (IsUsingT32()) {
1971       // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1972       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1973           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
1974         uint32_t amount_ = amount % 32;
1975         EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1976                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1977                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1978         AdvanceIT();
1979         return;
1980       }
1981     } else {
1982       // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1983       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1984         uint32_t amount_ = amount % 32;
1985         EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1986                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1987                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1988         return;
1989       }
1990     }
1991   }
1992   if (operand.IsRegisterShiftedRegister()) {
1993     Register rm = operand.GetBaseRegister();
1994     Shift shift = operand.GetShift();
1995     Register rs = operand.GetShiftRegister();
1996     if (IsUsingA32()) {
1997       // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1998       if (cond.IsNotNever() &&
1999           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2000            AllowUnpredictable())) {
2001         EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
2002                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2003                 (shift.GetType() << 5) | (rs.GetCode() << 8));
2004         return;
2005       }
2006     }
2007   }
2008   Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
2009 }
2010 
adcs(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)2011 void Assembler::adcs(Condition cond,
2012                      EncodingSize size,
2013                      Register rd,
2014                      Register rn,
2015                      const Operand& operand) {
2016   VIXL_ASSERT(AllowAssembler());
2017   CheckIT(cond);
2018   if (operand.IsImmediate()) {
2019     uint32_t imm = operand.GetImmediate();
2020     if (IsUsingT32()) {
2021       ImmediateT32 immediate_t32(imm);
2022       // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2023       if (!size.IsNarrow() && immediate_t32.IsValid() &&
2024           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2025         EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2026                    (immediate_t32.GetEncodingValue() & 0xff) |
2027                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2028                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2029         AdvanceIT();
2030         return;
2031       }
2032     } else {
2033       ImmediateA32 immediate_a32(imm);
2034       // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2035       if (immediate_a32.IsValid() && cond.IsNotNever()) {
2036         EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
2037                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2038                 immediate_a32.GetEncodingValue());
2039         return;
2040       }
2041     }
2042   }
2043   if (operand.IsImmediateShiftedRegister()) {
2044     Register rm = operand.GetBaseRegister();
2045     if (operand.IsPlainRegister()) {
2046       if (IsUsingT32()) {
2047         // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2048         if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2049             rm.IsLow()) {
2050           EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
2051           AdvanceIT();
2052           return;
2053         }
2054       }
2055     }
2056     Shift shift = operand.GetShift();
2057     uint32_t amount = operand.GetShiftAmount();
2058     if (IsUsingT32()) {
2059       // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2060       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2061           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2062         uint32_t amount_ = amount % 32;
2063         EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2064                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2065                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2066         AdvanceIT();
2067         return;
2068       }
2069     } else {
2070       // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2071       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2072         uint32_t amount_ = amount % 32;
2073         EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
2074                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2075                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2076         return;
2077       }
2078     }
2079   }
2080   if (operand.IsRegisterShiftedRegister()) {
2081     Register rm = operand.GetBaseRegister();
2082     Shift shift = operand.GetShift();
2083     Register rs = operand.GetShiftRegister();
2084     if (IsUsingA32()) {
2085       // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2086       if (cond.IsNotNever() &&
2087           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2088            AllowUnpredictable())) {
2089         EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
2090                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2091                 (shift.GetType() << 5) | (rs.GetCode() << 8));
2092         return;
2093       }
2094     }
2095   }
2096   Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
2097 }
2098 
add(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)2099 void Assembler::add(Condition cond,
2100                     EncodingSize size,
2101                     Register rd,
2102                     Register rn,
2103                     const Operand& operand) {
2104   VIXL_ASSERT(AllowAssembler());
2105   CheckIT(cond);
2106   if (operand.IsImmediate()) {
2107     uint32_t imm = operand.GetImmediate();
2108     if (IsUsingT32()) {
2109       ImmediateT32 immediate_t32(imm);
2110       // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
2111       if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
2112           ((imm % 4) == 0)) {
2113         uint32_t imm_ = imm >> 2;
2114         EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
2115         AdvanceIT();
2116         return;
2117       }
2118       // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
2119       if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2120           (imm <= 7)) {
2121         EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2122         AdvanceIT();
2123         return;
2124       }
2125       // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2126       if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2127           (imm <= 255)) {
2128         EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2129         AdvanceIT();
2130         return;
2131       }
2132       // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
2133       if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
2134           ((imm % 4) == 0)) {
2135         uint32_t imm_ = imm >> 2;
2136         EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2137         AdvanceIT();
2138         return;
2139       }
2140       // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2141       if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2142           ((imm % 4) == 0)) {
2143         uint32_t imm_ = imm >> 2;
2144         EmitT32_16(0xb000 | imm_);
2145         AdvanceIT();
2146         return;
2147       }
2148       // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2149       if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
2150           (!rd.IsPC() || AllowUnpredictable())) {
2151         EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2152                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2153         AdvanceIT();
2154         return;
2155       }
2156       // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2157       if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2158           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2159         EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2160                    (immediate_t32.GetEncodingValue() & 0xff) |
2161                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2162                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2163         AdvanceIT();
2164         return;
2165       }
2166       // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2167       if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
2168           (!rd.IsPC() || AllowUnpredictable())) {
2169         EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2170                    (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2171         AdvanceIT();
2172         return;
2173       }
2174       // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2175       if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2176           (!rd.IsPC() || AllowUnpredictable())) {
2177         EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2178                    (immediate_t32.GetEncodingValue() & 0xff) |
2179                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2180                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2181         AdvanceIT();
2182         return;
2183       }
2184       // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2185       if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
2186           (!rd.IsPC() || AllowUnpredictable())) {
2187         EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2188                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2189         AdvanceIT();
2190         return;
2191       }
2192     } else {
2193       ImmediateA32 immediate_a32(imm);
2194       // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2195       if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2196         EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2197                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2198         return;
2199       }
2200       // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2201       if (immediate_a32.IsValid() && cond.IsNotNever() &&
2202           ((rn.GetCode() & 0xd) != 0xd)) {
2203         EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2204                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2205                 immediate_a32.GetEncodingValue());
2206         return;
2207       }
2208       // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2209       if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2210         EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2211                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2212         return;
2213       }
2214     }
2215   }
2216   if (operand.IsImmediateShiftedRegister()) {
2217     Register rm = operand.GetBaseRegister();
2218     if (operand.IsPlainRegister()) {
2219       if (IsUsingT32()) {
2220         // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2221         if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2222             rm.IsLow()) {
2223           EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2224                      (rm.GetCode() << 6));
2225           AdvanceIT();
2226           return;
2227         }
2228         // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
2229         if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
2230             (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2231               (!rd.IsPC() || !rm.IsPC())) ||
2232              AllowUnpredictable())) {
2233           EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2234                      ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2235           AdvanceIT();
2236           return;
2237         }
2238         // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
2239         if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
2240             ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
2241              AllowUnpredictable())) {
2242           EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2243                      ((rd.GetCode() & 0x8) << 4));
2244           AdvanceIT();
2245           return;
2246         }
2247         // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2248         if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2249           EmitT32_16(0x4485 | (rm.GetCode() << 3));
2250           AdvanceIT();
2251           return;
2252         }
2253       }
2254     }
2255     Shift shift = operand.GetShift();
2256     uint32_t amount = operand.GetShiftAmount();
2257     if (IsUsingT32()) {
2258       // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2259       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2260           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2261         uint32_t amount_ = amount % 32;
2262         EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2263                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2264                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2265         AdvanceIT();
2266         return;
2267       }
2268       // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2269       if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2270           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2271         uint32_t amount_ = amount % 32;
2272         EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2273                    (operand.GetTypeEncodingValue() << 4) |
2274                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2275         AdvanceIT();
2276         return;
2277       }
2278     } else {
2279       // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2280       if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2281         uint32_t amount_ = amount % 32;
2282         EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2283                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2284                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2285         return;
2286       }
2287       // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2288       if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2289         uint32_t amount_ = amount % 32;
2290         EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2291                 (rd.GetCode() << 12) | rm.GetCode() |
2292                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2293         return;
2294       }
2295     }
2296   }
2297   if (operand.IsRegisterShiftedRegister()) {
2298     Register rm = operand.GetBaseRegister();
2299     Shift shift = operand.GetShift();
2300     Register rs = operand.GetShiftRegister();
2301     if (IsUsingA32()) {
2302       // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2303       if (cond.IsNotNever() &&
2304           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2305            AllowUnpredictable())) {
2306         EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2307                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2308                 (shift.GetType() << 5) | (rs.GetCode() << 8));
2309         return;
2310       }
2311     }
2312   }
2313   Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2314 }
2315 
add(Condition cond,Register rd,const Operand & operand)2316 void Assembler::add(Condition cond, Register rd, const Operand& operand) {
2317   VIXL_ASSERT(AllowAssembler());
2318   CheckIT(cond);
2319   if (operand.IsImmediate()) {
2320     uint32_t imm = operand.GetImmediate();
2321     if (IsUsingT32()) {
2322       // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2323       if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2324         EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2325         AdvanceIT();
2326         return;
2327       }
2328     }
2329   }
2330   if (operand.IsPlainRegister()) {
2331     Register rm = operand.GetBaseRegister();
2332     if (IsUsingT32()) {
2333       // ADD<c>{<q>} <Rdn>, <Rm> ; T2
2334       if (InITBlock() && !rm.Is(sp) &&
2335           (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2336             (!rd.IsPC() || !rm.IsPC())) ||
2337            AllowUnpredictable())) {
2338         EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2339                    (rm.GetCode() << 3));
2340         AdvanceIT();
2341         return;
2342       }
2343     }
2344   }
2345   Delegate(kAdd, &Assembler::add, cond, rd, operand);
2346 }
2347 
adds(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)2348 void Assembler::adds(Condition cond,
2349                      EncodingSize size,
2350                      Register rd,
2351                      Register rn,
2352                      const Operand& operand) {
2353   VIXL_ASSERT(AllowAssembler());
2354   CheckIT(cond);
2355   if (operand.IsImmediate()) {
2356     uint32_t imm = operand.GetImmediate();
2357     if (IsUsingT32()) {
2358       ImmediateT32 immediate_t32(imm);
2359       // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2360       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2361           (imm <= 7)) {
2362         EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2363         AdvanceIT();
2364         return;
2365       }
2366       // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2367       if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2368           (imm <= 255)) {
2369         EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2370         AdvanceIT();
2371         return;
2372       }
2373       // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2374       if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2375           !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
2376         EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2377                    (immediate_t32.GetEncodingValue() & 0xff) |
2378                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2379                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2380         AdvanceIT();
2381         return;
2382       }
2383       // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2384       if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2385           !rd.Is(pc)) {
2386         EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2387                    (immediate_t32.GetEncodingValue() & 0xff) |
2388                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2389                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2390         AdvanceIT();
2391         return;
2392       }
2393     } else {
2394       ImmediateA32 immediate_a32(imm);
2395       // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2396       if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2397         EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2398                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2399                 immediate_a32.GetEncodingValue());
2400         return;
2401       }
2402       // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2403       if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2404         EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2405                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2406         return;
2407       }
2408     }
2409   }
2410   if (operand.IsImmediateShiftedRegister()) {
2411     Register rm = operand.GetBaseRegister();
2412     if (operand.IsPlainRegister()) {
2413       if (IsUsingT32()) {
2414         // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2415         if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2416             rm.IsLow()) {
2417           EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2418                      (rm.GetCode() << 6));
2419           AdvanceIT();
2420           return;
2421         }
2422       }
2423     }
2424     Shift shift = operand.GetShift();
2425     uint32_t amount = operand.GetShiftAmount();
2426     if (IsUsingT32()) {
2427       // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2428       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2429           !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2430         uint32_t amount_ = amount % 32;
2431         EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2432                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2433                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2434         AdvanceIT();
2435         return;
2436       }
2437       // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2438       if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2439           !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
2440         uint32_t amount_ = amount % 32;
2441         EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2442                    (operand.GetTypeEncodingValue() << 4) |
2443                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2444         AdvanceIT();
2445         return;
2446       }
2447     } else {
2448       // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2449       if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2450         uint32_t amount_ = amount % 32;
2451         EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2452                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2453                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2454         return;
2455       }
2456       // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2457       if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2458         uint32_t amount_ = amount % 32;
2459         EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2460                 (rd.GetCode() << 12) | rm.GetCode() |
2461                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2462         return;
2463       }
2464     }
2465   }
2466   if (operand.IsRegisterShiftedRegister()) {
2467     Register rm = operand.GetBaseRegister();
2468     Shift shift = operand.GetShift();
2469     Register rs = operand.GetShiftRegister();
2470     if (IsUsingA32()) {
2471       // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2472       if (cond.IsNotNever() &&
2473           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2474            AllowUnpredictable())) {
2475         EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2476                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2477                 (shift.GetType() << 5) | (rs.GetCode() << 8));
2478         return;
2479       }
2480     }
2481   }
2482   Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2483 }
2484 
adds(Register rd,const Operand & operand)2485 void Assembler::adds(Register rd, const Operand& operand) {
2486   VIXL_ASSERT(AllowAssembler());
2487   CheckIT(al);
2488   if (operand.IsImmediate()) {
2489     uint32_t imm = operand.GetImmediate();
2490     if (IsUsingT32()) {
2491       // ADDS{<q>} <Rdn>, #<imm8> ; T2
2492       if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2493         EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2494         AdvanceIT();
2495         return;
2496       }
2497     }
2498   }
2499   Delegate(kAdds, &Assembler::adds, rd, operand);
2500 }
2501 
addw(Condition cond,Register rd,Register rn,const Operand & operand)2502 void Assembler::addw(Condition cond,
2503                      Register rd,
2504                      Register rn,
2505                      const Operand& operand) {
2506   VIXL_ASSERT(AllowAssembler());
2507   CheckIT(cond);
2508   if (operand.IsImmediate()) {
2509     uint32_t imm = operand.GetImmediate();
2510     if (IsUsingT32()) {
2511       // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2512       if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2513         EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2514                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2515         AdvanceIT();
2516         return;
2517       }
2518       // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2519       if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
2520           (!rd.IsPC() || AllowUnpredictable())) {
2521         EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2522                    (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2523         AdvanceIT();
2524         return;
2525       }
2526       // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2527       if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2528         EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2529                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2530         AdvanceIT();
2531         return;
2532       }
2533     }
2534   }
2535   Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2536 }
2537 
adr(Condition cond,EncodingSize size,Register rd,Location * location)2538 void Assembler::adr(Condition cond,
2539                     EncodingSize size,
2540                     Register rd,
2541                     Location* location) {
2542   VIXL_ASSERT(AllowAssembler());
2543   CheckIT(cond);
2544   Location::Offset offset =
2545       location->IsBound()
2546           ? location->GetLocation() -
2547                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2548           : 0;
2549   if (IsUsingT32()) {
2550     int32_t neg_offset = -offset;
2551     // ADR{<c>}{<q>} <Rd>, <label> ; T1
2552     if (!size.IsWide() && rd.IsLow() &&
2553         ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
2554           ((offset & 0x3) == 0)) ||
2555          (!location->IsBound() && size.IsNarrow()))) {
2556       static class EmitOp : public Location::EmitOperator {
2557        public:
2558         EmitOp() : Location::EmitOperator(T32) {}
2559         virtual uint32_t Encode(uint32_t instr,
2560                                 Location::Offset program_counter,
2561                                 const Location* loc) const VIXL_OVERRIDE {
2562           program_counter += kT32PcDelta;
2563           Location::Offset off =
2564               loc->GetLocation() - AlignDown(program_counter, 4);
2565           VIXL_ASSERT((off >= 0) && (off <= 1020) && ((off & 0x3) == 0));
2566           const int32_t target = off >> 2;
2567           return instr | (target & 0xff);
2568         }
2569       } immop;
2570       EmitT32_16(
2571           Link(0xa000 | (rd.GetCode() << 8), location, immop, &kT16DataInfo));
2572       AdvanceIT();
2573       return;
2574     }
2575     // ADR{<c>}{<q>} <Rd>, <label> ; T2
2576     if (!size.IsNarrow() && location->IsBound() && (neg_offset > 0) &&
2577         (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2578       EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2579                  ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2580       AdvanceIT();
2581       return;
2582     }
2583     // ADR{<c>}{<q>} <Rd>, <label> ; T3
2584     if (!size.IsNarrow() &&
2585         (!location->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
2586         (!rd.IsPC() || AllowUnpredictable())) {
2587       static class EmitOp : public Location::EmitOperator {
2588        public:
2589         EmitOp() : Location::EmitOperator(T32) {}
2590         virtual uint32_t Encode(uint32_t instr,
2591                                 Location::Offset program_counter,
2592                                 const Location* loc) const VIXL_OVERRIDE {
2593           program_counter += kT32PcDelta;
2594           Location::Offset off =
2595               loc->GetLocation() - AlignDown(program_counter, 4);
2596           int32_t target;
2597           if ((off >= 0) && (off <= 4095)) {
2598             target = off;
2599           } else {
2600             target = -off;
2601             VIXL_ASSERT((target >= 0) && (target <= 4095));
2602             // Emit the T2 encoding.
2603             instr |= 0x00a00000;
2604           }
2605           return instr | (target & 0xff) | ((target & 0x700) << 4) |
2606                  ((target & 0x800) << 15);
2607         }
2608       } immop;
2609       EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8),
2610                       location,
2611                       immop,
2612                       &kT32FarDataInfo));
2613       AdvanceIT();
2614       return;
2615     }
2616   } else {
2617     ImmediateA32 positive_immediate_a32(offset);
2618     ImmediateA32 negative_immediate_a32(-offset);
2619     // ADR{<c>}{<q>} <Rd>, <label> ; A1
2620     if ((!location->IsBound() || positive_immediate_a32.IsValid()) &&
2621         cond.IsNotNever()) {
2622       static class EmitOp : public Location::EmitOperator {
2623        public:
2624         EmitOp() : Location::EmitOperator(A32) {}
2625         virtual uint32_t Encode(uint32_t instr,
2626                                 Location::Offset program_counter,
2627                                 const Location* loc) const VIXL_OVERRIDE {
2628           program_counter += kA32PcDelta;
2629           Location::Offset off =
2630               loc->GetLocation() - AlignDown(program_counter, 4);
2631           int32_t target;
2632           ImmediateA32 pos_imm_a32(off);
2633           if (pos_imm_a32.IsValid()) {
2634             target = pos_imm_a32.GetEncodingValue();
2635           } else {
2636             ImmediateA32 neg_imm_a32(-off);
2637             VIXL_ASSERT(neg_imm_a32.IsValid());
2638             // Emit the A2 encoding.
2639             target = neg_imm_a32.GetEncodingValue();
2640             instr = (instr & ~0x00f00000) | 0x00400000;
2641           }
2642           return instr | (target & 0xfff);
2643         }
2644       } immop;
2645       EmitA32(
2646           Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
2647                location,
2648                immop,
2649                &kA32AdrInfo));
2650       return;
2651     }
2652     // ADR{<c>}{<q>} <Rd>, <label> ; A2
2653     if (location->IsBound() && negative_immediate_a32.IsValid() &&
2654         cond.IsNotNever()) {
2655       EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2656               negative_immediate_a32.GetEncodingValue());
2657       return;
2658     }
2659   }
2660   Delegate(kAdr, &Assembler::adr, cond, size, rd, location);
2661 }
2662 
adr_info(Condition cond,EncodingSize size,Register rd,Location * location,const struct ReferenceInfo ** info)2663 bool Assembler::adr_info(Condition cond,
2664                          EncodingSize size,
2665                          Register rd,
2666                          Location* location,
2667                          const struct ReferenceInfo** info) {
2668   VIXL_ASSERT(!location->IsBound());
2669   USE(location);
2670   if (IsUsingT32()) {
2671     // ADR{<c>}{<q>} <Rd>, <label> ; T1
2672     if (!size.IsWide() && rd.IsLow() && size.IsNarrow()) {
2673       *info = &kT16DataInfo;
2674       return true;
2675     }
2676     // Skipped T2, as it is a negative offset variant.
2677     // The minimum offset is included in the corresponding
2678     // positive variant.
2679     // ADR{<c>}{<q>} <Rd>, <label> ; T3
2680     if (!size.IsNarrow()) {
2681       *info = &kT32FarDataInfo;
2682       return true;
2683     }
2684   } else {
2685     // ADR{<c>}{<q>} <Rd>, <label> ; A1
2686     if (cond.IsNotNever()) {
2687       *info = &kA32AdrInfo;
2688       return true;
2689     }
2690     // Skipped A2, as it is a negative offset variant.
2691     // The minimum offset is included in the corresponding
2692     // positive variant.
2693   }
2694   return false;
2695 }
2696 
and_(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)2697 void Assembler::and_(Condition cond,
2698                      EncodingSize size,
2699                      Register rd,
2700                      Register rn,
2701                      const Operand& operand) {
2702   VIXL_ASSERT(AllowAssembler());
2703   CheckIT(cond);
2704   if (operand.IsImmediate()) {
2705     uint32_t imm = operand.GetImmediate();
2706     if (IsUsingT32()) {
2707       ImmediateT32 immediate_t32(imm);
2708       // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2709       if (!size.IsNarrow() && immediate_t32.IsValid() &&
2710           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2711         EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2712                    (immediate_t32.GetEncodingValue() & 0xff) |
2713                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2714                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2715         AdvanceIT();
2716         return;
2717       }
2718     } else {
2719       ImmediateA32 immediate_a32(imm);
2720       // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2721       if (immediate_a32.IsValid() && cond.IsNotNever()) {
2722         EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2723                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2724                 immediate_a32.GetEncodingValue());
2725         return;
2726       }
2727     }
2728   }
2729   if (operand.IsImmediateShiftedRegister()) {
2730     Register rm = operand.GetBaseRegister();
2731     if (operand.IsPlainRegister()) {
2732       if (IsUsingT32()) {
2733         // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2734         if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2735             rm.IsLow()) {
2736           EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2737           AdvanceIT();
2738           return;
2739         }
2740       }
2741     }
2742     Shift shift = operand.GetShift();
2743     uint32_t amount = operand.GetShiftAmount();
2744     if (IsUsingT32()) {
2745       // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2746       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2747           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2748         uint32_t amount_ = amount % 32;
2749         EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2750                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2751                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2752         AdvanceIT();
2753         return;
2754       }
2755     } else {
2756       // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2757       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2758         uint32_t amount_ = amount % 32;
2759         EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2760                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2761                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2762         return;
2763       }
2764     }
2765   }
2766   if (operand.IsRegisterShiftedRegister()) {
2767     Register rm = operand.GetBaseRegister();
2768     Shift shift = operand.GetShift();
2769     Register rs = operand.GetShiftRegister();
2770     if (IsUsingA32()) {
2771       // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2772       if (cond.IsNotNever() &&
2773           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2774            AllowUnpredictable())) {
2775         EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2776                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2777                 (shift.GetType() << 5) | (rs.GetCode() << 8));
2778         return;
2779       }
2780     }
2781   }
2782   Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2783 }
2784 
ands(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)2785 void Assembler::ands(Condition cond,
2786                      EncodingSize size,
2787                      Register rd,
2788                      Register rn,
2789                      const Operand& operand) {
2790   VIXL_ASSERT(AllowAssembler());
2791   CheckIT(cond);
2792   if (operand.IsImmediate()) {
2793     uint32_t imm = operand.GetImmediate();
2794     if (IsUsingT32()) {
2795       ImmediateT32 immediate_t32(imm);
2796       // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2797       if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
2798           (!rn.IsPC() || AllowUnpredictable())) {
2799         EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2800                    (immediate_t32.GetEncodingValue() & 0xff) |
2801                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2802                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2803         AdvanceIT();
2804         return;
2805       }
2806     } else {
2807       ImmediateA32 immediate_a32(imm);
2808       // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2809       if (immediate_a32.IsValid() && cond.IsNotNever()) {
2810         EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2811                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2812                 immediate_a32.GetEncodingValue());
2813         return;
2814       }
2815     }
2816   }
2817   if (operand.IsImmediateShiftedRegister()) {
2818     Register rm = operand.GetBaseRegister();
2819     if (operand.IsPlainRegister()) {
2820       if (IsUsingT32()) {
2821         // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2822         if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2823             rm.IsLow()) {
2824           EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2825           AdvanceIT();
2826           return;
2827         }
2828       }
2829     }
2830     Shift shift = operand.GetShift();
2831     uint32_t amount = operand.GetShiftAmount();
2832     if (IsUsingT32()) {
2833       // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2834       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
2835           ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2836         uint32_t amount_ = amount % 32;
2837         EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2838                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2839                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2840         AdvanceIT();
2841         return;
2842       }
2843     } else {
2844       // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2845       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2846         uint32_t amount_ = amount % 32;
2847         EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2848                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2849                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2850         return;
2851       }
2852     }
2853   }
2854   if (operand.IsRegisterShiftedRegister()) {
2855     Register rm = operand.GetBaseRegister();
2856     Shift shift = operand.GetShift();
2857     Register rs = operand.GetShiftRegister();
2858     if (IsUsingA32()) {
2859       // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2860       if (cond.IsNotNever() &&
2861           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2862            AllowUnpredictable())) {
2863         EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2864                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2865                 (shift.GetType() << 5) | (rs.GetCode() << 8));
2866         return;
2867       }
2868     }
2869   }
2870   Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2871 }
2872 
asr(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)2873 void Assembler::asr(Condition cond,
2874                     EncodingSize size,
2875                     Register rd,
2876                     Register rm,
2877                     const Operand& operand) {
2878   VIXL_ASSERT(AllowAssembler());
2879   CheckIT(cond);
2880   if (operand.IsImmediate()) {
2881     uint32_t imm = operand.GetImmediate();
2882     if (IsUsingT32()) {
2883       // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2884       if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2885           (imm >= 1) && (imm <= 32)) {
2886         uint32_t amount_ = imm % 32;
2887         EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2888                    (amount_ << 6));
2889         AdvanceIT();
2890         return;
2891       }
2892       // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2893       if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2894           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2895         uint32_t amount_ = imm % 32;
2896         EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2897                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2898         AdvanceIT();
2899         return;
2900       }
2901     } else {
2902       // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2903       if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2904         uint32_t amount_ = imm % 32;
2905         EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2906                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2907         return;
2908       }
2909     }
2910   }
2911   if (operand.IsPlainRegister()) {
2912     Register rs = operand.GetBaseRegister();
2913     if (IsUsingT32()) {
2914       // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2915       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2916           rs.IsLow()) {
2917         EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2918         AdvanceIT();
2919         return;
2920       }
2921       // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2922       if (!size.IsNarrow() &&
2923           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2924         EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2925                    rs.GetCode());
2926         AdvanceIT();
2927         return;
2928       }
2929     } else {
2930       // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2931       if (cond.IsNotNever() &&
2932           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2933         EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2934                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2935         return;
2936       }
2937     }
2938   }
2939   Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2940 }
2941 
asrs(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)2942 void Assembler::asrs(Condition cond,
2943                      EncodingSize size,
2944                      Register rd,
2945                      Register rm,
2946                      const Operand& operand) {
2947   VIXL_ASSERT(AllowAssembler());
2948   CheckIT(cond);
2949   if (operand.IsImmediate()) {
2950     uint32_t imm = operand.GetImmediate();
2951     if (IsUsingT32()) {
2952       // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2953       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2954           (imm >= 1) && (imm <= 32)) {
2955         uint32_t amount_ = imm % 32;
2956         EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2957                    (amount_ << 6));
2958         AdvanceIT();
2959         return;
2960       }
2961       // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2962       if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2963           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2964         uint32_t amount_ = imm % 32;
2965         EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2966                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2967         AdvanceIT();
2968         return;
2969       }
2970     } else {
2971       // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2972       if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2973         uint32_t amount_ = imm % 32;
2974         EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2975                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2976         return;
2977       }
2978     }
2979   }
2980   if (operand.IsPlainRegister()) {
2981     Register rs = operand.GetBaseRegister();
2982     if (IsUsingT32()) {
2983       // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2984       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2985           rs.IsLow()) {
2986         EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2987         AdvanceIT();
2988         return;
2989       }
2990       // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2991       if (!size.IsNarrow() &&
2992           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2993         EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2994                    rs.GetCode());
2995         AdvanceIT();
2996         return;
2997       }
2998     } else {
2999       // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
3000       if (cond.IsNotNever() &&
3001           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
3002         EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
3003                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
3004         return;
3005       }
3006     }
3007   }
3008   Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
3009 }
3010 
b(Condition cond,EncodingSize size,Location * location)3011 void Assembler::b(Condition cond, EncodingSize size, Location* location) {
3012   VIXL_ASSERT(AllowAssembler());
3013   Location::Offset offset =
3014       location->IsBound()
3015           ? location->GetLocation() -
3016                 (GetCursorOffset() + GetArchitectureStatePCOffset())
3017           : 0;
3018   if (IsUsingT32()) {
3019     // B<c>{<q>} <label> ; T1
3020     if (OutsideITBlock() && !size.IsWide() &&
3021         ((location->IsBound() && (offset >= -256) && (offset <= 254) &&
3022           ((offset & 0x1) == 0)) ||
3023          (!location->IsBound() && size.IsNarrow())) &&
3024         !cond.Is(al) && cond.IsNotNever()) {
3025       static class EmitOp : public Location::EmitOperator {
3026        public:
3027         EmitOp() : Location::EmitOperator(T32) {}
3028         virtual uint32_t Encode(uint32_t instr,
3029                                 Location::Offset program_counter,
3030                                 const Location* loc) const VIXL_OVERRIDE {
3031           program_counter += kT32PcDelta;
3032           Location::Offset off = loc->GetLocation() - program_counter;
3033           VIXL_ASSERT((off >= -256) && (off <= 254) && ((off & 0x1) == 0));
3034           const int32_t target = off >> 1;
3035           return instr | (target & 0xff);
3036         }
3037       } immop;
3038       EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8),
3039                       location,
3040                       immop,
3041                       &kT16ConditionalBranchInfo));
3042       AdvanceIT();
3043       return;
3044     }
3045     // B{<c>}{<q>} <label> ; T2
3046     if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
3047         ((location->IsBound() && (offset >= -2048) && (offset <= 2046) &&
3048           ((offset & 0x1) == 0)) ||
3049          (!location->IsBound() && size.IsNarrow()))) {
3050       CheckIT(cond);
3051       static class EmitOp : public Location::EmitOperator {
3052        public:
3053         EmitOp() : Location::EmitOperator(T32) {}
3054         virtual uint32_t Encode(uint32_t instr,
3055                                 Location::Offset program_counter,
3056                                 const Location* loc) const VIXL_OVERRIDE {
3057           program_counter += kT32PcDelta;
3058           Location::Offset off = loc->GetLocation() - program_counter;
3059           VIXL_ASSERT((off >= -2048) && (off <= 2046) && ((off & 0x1) == 0));
3060           const int32_t target = off >> 1;
3061           return instr | (target & 0x7ff);
3062         }
3063       } immop;
3064       EmitT32_16(Link(0xe000, location, immop, &kT16BranchInfo));
3065       AdvanceIT();
3066       return;
3067     }
3068     // B<c>{<q>} <label> ; T3
3069     if (OutsideITBlock() && !size.IsNarrow() &&
3070         ((location->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
3071           ((offset & 0x1) == 0)) ||
3072          !location->IsBound()) &&
3073         !cond.Is(al) && cond.IsNotNever()) {
3074       static class EmitOp : public Location::EmitOperator {
3075        public:
3076         EmitOp() : Location::EmitOperator(T32) {}
3077         virtual uint32_t Encode(uint32_t instr,
3078                                 Location::Offset program_counter,
3079                                 const Location* loc) const VIXL_OVERRIDE {
3080           program_counter += kT32PcDelta;
3081           Location::Offset off = loc->GetLocation() - program_counter;
3082           VIXL_ASSERT((off >= -1048576) && (off <= 1048574) &&
3083                       ((off & 0x1) == 0));
3084           const int32_t target = off >> 1;
3085           return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
3086                  ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
3087                  ((target & 0x80000) << 7);
3088         }
3089       } immop;
3090       EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22),
3091                       location,
3092                       immop,
3093                       &kT32ConditionalBranchInfo));
3094       AdvanceIT();
3095       return;
3096     }
3097     // B{<c>}{<q>} <label> ; T4
3098     if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
3099         ((location->IsBound() && (offset >= -16777216) &&
3100           (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3101          !location->IsBound())) {
3102       CheckIT(cond);
3103       static class EmitOp : public Location::EmitOperator {
3104        public:
3105         EmitOp() : Location::EmitOperator(T32) {}
3106         virtual uint32_t Encode(uint32_t instr,
3107                                 Location::Offset program_counter,
3108                                 const Location* loc) const VIXL_OVERRIDE {
3109           program_counter += kT32PcDelta;
3110           Location::Offset off = loc->GetLocation() - program_counter;
3111           VIXL_ASSERT((off >= -16777216) && (off <= 16777214) &&
3112                       ((off & 0x1) == 0));
3113           int32_t target = off >> 1;
3114           uint32_t S = target & (1 << 23);
3115           target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3116           return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3117                  ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3118                  ((target & 0x800000) << 3);
3119         }
3120       } immop;
3121       EmitT32_32(Link(0xf0009000U, location, immop, &kT32BranchInfo));
3122       AdvanceIT();
3123       return;
3124     }
3125   } else {
3126     // B{<c>}{<q>} <label> ; A1
3127     if (((location->IsBound() && (offset >= -33554432) &&
3128           (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3129          !location->IsBound()) &&
3130         cond.IsNotNever()) {
3131       static class EmitOp : public Location::EmitOperator {
3132        public:
3133         EmitOp() : Location::EmitOperator(A32) {}
3134         virtual uint32_t Encode(uint32_t instr,
3135                                 Location::Offset program_counter,
3136                                 const Location* loc) const VIXL_OVERRIDE {
3137           program_counter += kA32PcDelta;
3138           Location::Offset off = loc->GetLocation() - program_counter;
3139           VIXL_ASSERT((off >= -33554432) && (off <= 33554428) &&
3140                       ((off & 0x3) == 0));
3141           const int32_t target = off >> 2;
3142           return instr | (target & 0xffffff);
3143         }
3144       } immop;
3145       EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28),
3146                    location,
3147                    immop,
3148                    &kA32BranchInfo));
3149       return;
3150     }
3151   }
3152   Delegate(kB, &Assembler::b, cond, size, location);
3153 }
3154 
b_info(Condition cond,EncodingSize size,Location * location,const struct ReferenceInfo ** info)3155 bool Assembler::b_info(Condition cond,
3156                        EncodingSize size,
3157                        Location* location,
3158                        const struct ReferenceInfo** info) {
3159   VIXL_ASSERT(!location->IsBound());
3160   USE(location);
3161   if (IsUsingT32()) {
3162     // B<c>{<q>} <label> ; T1
3163     if (OutsideITBlock() && !size.IsWide() && size.IsNarrow() && !cond.Is(al) &&
3164         cond.IsNotNever()) {
3165       *info = &kT16ConditionalBranchInfo;
3166       return true;
3167     }
3168     // B{<c>}{<q>} <label> ; T2
3169     if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() && size.IsNarrow()) {
3170       *info = &kT16BranchInfo;
3171       return true;
3172     }
3173     // B<c>{<q>} <label> ; T3
3174     if (OutsideITBlock() && !size.IsNarrow() && !cond.Is(al) &&
3175         cond.IsNotNever()) {
3176       *info = &kT32ConditionalBranchInfo;
3177       return true;
3178     }
3179     // B{<c>}{<q>} <label> ; T4
3180     if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow()) {
3181       *info = &kT32BranchInfo;
3182       return true;
3183     }
3184   } else {
3185     // B{<c>}{<q>} <label> ; A1
3186     if (cond.IsNotNever()) {
3187       *info = &kA32BranchInfo;
3188       return true;
3189     }
3190   }
3191   return false;
3192 }
3193 
bfc(Condition cond,Register rd,uint32_t lsb,uint32_t width)3194 void Assembler::bfc(Condition cond, Register rd, uint32_t lsb, uint32_t width) {
3195   VIXL_ASSERT(AllowAssembler());
3196   CheckIT(cond);
3197   if (IsUsingT32()) {
3198     // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
3199     if ((lsb <= 31) && (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3200                         AllowUnpredictable())) {
3201       uint32_t msb = lsb + width - 1;
3202       EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
3203                  ((lsb & 0x1c) << 10) | msb);
3204       AdvanceIT();
3205       return;
3206     }
3207   } else {
3208     // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
3209     if ((lsb <= 31) && cond.IsNotNever() &&
3210         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3211          AllowUnpredictable())) {
3212       uint32_t msb = lsb + width - 1;
3213       EmitA32(0x07c0001fU | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3214               (lsb << 7) | (msb << 16));
3215       return;
3216     }
3217   }
3218   Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, width);
3219 }
3220 
bfi(Condition cond,Register rd,Register rn,uint32_t lsb,uint32_t width)3221 void Assembler::bfi(
3222     Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
3223   VIXL_ASSERT(AllowAssembler());
3224   CheckIT(cond);
3225   if (IsUsingT32()) {
3226     // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
3227     if ((lsb <= 31) && !rn.Is(pc) &&
3228         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3229          AllowUnpredictable())) {
3230       uint32_t msb = lsb + width - 1;
3231       EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3232                  ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
3233       AdvanceIT();
3234       return;
3235     }
3236   } else {
3237     // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
3238     if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
3239         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3240          AllowUnpredictable())) {
3241       uint32_t msb = lsb + width - 1;
3242       EmitA32(0x07c00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3243               rn.GetCode() | (lsb << 7) | (msb << 16));
3244       return;
3245     }
3246   }
3247   Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, width);
3248 }
3249 
bic(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)3250 void Assembler::bic(Condition cond,
3251                     EncodingSize size,
3252                     Register rd,
3253                     Register rn,
3254                     const Operand& operand) {
3255   VIXL_ASSERT(AllowAssembler());
3256   CheckIT(cond);
3257   if (operand.IsImmediate()) {
3258     uint32_t imm = operand.GetImmediate();
3259     if (IsUsingT32()) {
3260       ImmediateT32 immediate_t32(imm);
3261       // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3262       if (!size.IsNarrow() && immediate_t32.IsValid() &&
3263           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
3264         EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3265                    (immediate_t32.GetEncodingValue() & 0xff) |
3266                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3267                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3268         AdvanceIT();
3269         return;
3270       }
3271     } else {
3272       ImmediateA32 immediate_a32(imm);
3273       // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3274       if (immediate_a32.IsValid() && cond.IsNotNever()) {
3275         EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3276                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3277                 immediate_a32.GetEncodingValue());
3278         return;
3279       }
3280     }
3281   }
3282   if (operand.IsImmediateShiftedRegister()) {
3283     Register rm = operand.GetBaseRegister();
3284     if (operand.IsPlainRegister()) {
3285       if (IsUsingT32()) {
3286         // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3287         if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3288             rm.IsLow()) {
3289           EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3290           AdvanceIT();
3291           return;
3292         }
3293       }
3294     }
3295     Shift shift = operand.GetShift();
3296     uint32_t amount = operand.GetShiftAmount();
3297     if (IsUsingT32()) {
3298       // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3299       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3300           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3301         uint32_t amount_ = amount % 32;
3302         EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3303                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3304                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3305         AdvanceIT();
3306         return;
3307       }
3308     } else {
3309       // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3310       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3311         uint32_t amount_ = amount % 32;
3312         EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3313                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3314                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3315         return;
3316       }
3317     }
3318   }
3319   if (operand.IsRegisterShiftedRegister()) {
3320     Register rm = operand.GetBaseRegister();
3321     Shift shift = operand.GetShift();
3322     Register rs = operand.GetShiftRegister();
3323     if (IsUsingA32()) {
3324       // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3325       if (cond.IsNotNever() &&
3326           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3327            AllowUnpredictable())) {
3328         EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3329                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3330                 (shift.GetType() << 5) | (rs.GetCode() << 8));
3331         return;
3332       }
3333     }
3334   }
3335   Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3336 }
3337 
bics(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)3338 void Assembler::bics(Condition cond,
3339                      EncodingSize size,
3340                      Register rd,
3341                      Register rn,
3342                      const Operand& operand) {
3343   VIXL_ASSERT(AllowAssembler());
3344   CheckIT(cond);
3345   if (operand.IsImmediate()) {
3346     uint32_t imm = operand.GetImmediate();
3347     if (IsUsingT32()) {
3348       ImmediateT32 immediate_t32(imm);
3349       // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3350       if (!size.IsNarrow() && immediate_t32.IsValid() &&
3351           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
3352         EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3353                    (immediate_t32.GetEncodingValue() & 0xff) |
3354                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3355                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3356         AdvanceIT();
3357         return;
3358       }
3359     } else {
3360       ImmediateA32 immediate_a32(imm);
3361       // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3362       if (immediate_a32.IsValid() && cond.IsNotNever()) {
3363         EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3364                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3365                 immediate_a32.GetEncodingValue());
3366         return;
3367       }
3368     }
3369   }
3370   if (operand.IsImmediateShiftedRegister()) {
3371     Register rm = operand.GetBaseRegister();
3372     if (operand.IsPlainRegister()) {
3373       if (IsUsingT32()) {
3374         // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3375         if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3376             rm.IsLow()) {
3377           EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3378           AdvanceIT();
3379           return;
3380         }
3381       }
3382     }
3383     Shift shift = operand.GetShift();
3384     uint32_t amount = operand.GetShiftAmount();
3385     if (IsUsingT32()) {
3386       // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3387       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3388           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3389         uint32_t amount_ = amount % 32;
3390         EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3391                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3392                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3393         AdvanceIT();
3394         return;
3395       }
3396     } else {
3397       // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3398       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3399         uint32_t amount_ = amount % 32;
3400         EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3401                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3402                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3403         return;
3404       }
3405     }
3406   }
3407   if (operand.IsRegisterShiftedRegister()) {
3408     Register rm = operand.GetBaseRegister();
3409     Shift shift = operand.GetShift();
3410     Register rs = operand.GetShiftRegister();
3411     if (IsUsingA32()) {
3412       // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3413       if (cond.IsNotNever() &&
3414           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3415            AllowUnpredictable())) {
3416         EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3417                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3418                 (shift.GetType() << 5) | (rs.GetCode() << 8));
3419         return;
3420       }
3421     }
3422   }
3423   Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3424 }
3425 
bkpt(Condition cond,uint32_t imm)3426 void Assembler::bkpt(Condition cond, uint32_t imm) {
3427   VIXL_ASSERT(AllowAssembler());
3428   CheckIT(cond);
3429   if (IsUsingT32()) {
3430     // BKPT{<q>} {#}<imm> ; T1
3431     if ((imm <= 255)) {
3432       EmitT32_16(0xbe00 | imm);
3433       AdvanceIT();
3434       return;
3435     }
3436   } else {
3437     // BKPT{<q>} {#}<imm> ; A1
3438     if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3439       EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3440               ((imm & 0xfff0) << 4));
3441       return;
3442     }
3443   }
3444   Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3445 }
3446 
bl(Condition cond,Location * location)3447 void Assembler::bl(Condition cond, Location* location) {
3448   VIXL_ASSERT(AllowAssembler());
3449   CheckIT(cond);
3450   Location::Offset offset =
3451       location->IsBound()
3452           ? location->GetLocation() -
3453                 (GetCursorOffset() + GetArchitectureStatePCOffset())
3454           : 0;
3455   if (IsUsingT32()) {
3456     // BL{<c>}{<q>} <label> ; T1
3457     if (((location->IsBound() && (offset >= -16777216) &&
3458           (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3459          !location->IsBound()) &&
3460         (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3461       static class EmitOp : public Location::EmitOperator {
3462        public:
3463         EmitOp() : Location::EmitOperator(T32) {}
3464         virtual uint32_t Encode(uint32_t instr,
3465                                 Location::Offset program_counter,
3466                                 const Location* loc) const VIXL_OVERRIDE {
3467           program_counter += kT32PcDelta;
3468           Location::Offset off = loc->GetLocation() - program_counter;
3469           VIXL_ASSERT((off >= -16777216) && (off <= 16777214) &&
3470                       ((off & 0x1) == 0));
3471           int32_t target = off >> 1;
3472           uint32_t S = target & (1 << 23);
3473           target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3474           return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3475                  ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3476                  ((target & 0x800000) << 3);
3477         }
3478       } immop;
3479       EmitT32_32(Link(0xf000d000U, location, immop, &kT32BranchInfo));
3480       AdvanceIT();
3481       return;
3482     }
3483   } else {
3484     // BL{<c>}{<q>} <label> ; A1
3485     if (((location->IsBound() && (offset >= -33554432) &&
3486           (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3487          !location->IsBound()) &&
3488         cond.IsNotNever()) {
3489       static class EmitOp : public Location::EmitOperator {
3490        public:
3491         EmitOp() : Location::EmitOperator(A32) {}
3492         virtual uint32_t Encode(uint32_t instr,
3493                                 Location::Offset program_counter,
3494                                 const Location* loc) const VIXL_OVERRIDE {
3495           program_counter += kA32PcDelta;
3496           Location::Offset off = loc->GetLocation() - program_counter;
3497           VIXL_ASSERT((off >= -33554432) && (off <= 33554428) &&
3498                       ((off & 0x3) == 0));
3499           const int32_t target = off >> 2;
3500           return instr | (target & 0xffffff);
3501         }
3502       } immop;
3503       EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28),
3504                    location,
3505                    immop,
3506                    &kA32BranchInfo));
3507       return;
3508     }
3509   }
3510   Delegate(kBl, &Assembler::bl, cond, location);
3511 }
3512 
bl_info(Condition cond,Location * location,const struct ReferenceInfo ** info)3513 bool Assembler::bl_info(Condition cond,
3514                         Location* location,
3515                         const struct ReferenceInfo** info) {
3516   VIXL_ASSERT(!location->IsBound());
3517   USE(location);
3518   if (IsUsingT32()) {
3519     // BL{<c>}{<q>} <label> ; T1
3520     if (true) {
3521       *info = &kT32BranchInfo;
3522       return true;
3523     }
3524   } else {
3525     // BL{<c>}{<q>} <label> ; A1
3526     if (cond.IsNotNever()) {
3527       *info = &kA32BranchInfo;
3528       return true;
3529     }
3530   }
3531   return false;
3532 }
3533 
blx(Condition cond,Location * location)3534 void Assembler::blx(Condition cond, Location* location) {
3535   VIXL_ASSERT(AllowAssembler());
3536   CheckIT(cond);
3537   Location::Offset offset =
3538       location->IsBound()
3539           ? location->GetLocation() -
3540                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3541           : 0;
3542   if (IsUsingT32()) {
3543     // BLX{<c>}{<q>} <label> ; T2
3544     if (((location->IsBound() && (offset >= -16777216) &&
3545           (offset <= 16777212) && ((offset & 0x3) == 0)) ||
3546          !location->IsBound()) &&
3547         (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3548       static class EmitOp : public Location::EmitOperator {
3549        public:
3550         EmitOp() : Location::EmitOperator(T32) {}
3551         virtual uint32_t Encode(uint32_t instr,
3552                                 Location::Offset program_counter,
3553                                 const Location* loc) const VIXL_OVERRIDE {
3554           program_counter += kT32PcDelta;
3555           Location::Offset off =
3556               loc->GetLocation() - AlignDown(program_counter, 4);
3557           VIXL_ASSERT((off >= -16777216) && (off <= 16777212) &&
3558                       ((off & 0x3) == 0));
3559           int32_t target = off >> 2;
3560           uint32_t S = target & (1 << 22);
3561           target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3562           return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3563                  ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3564                  ((target & 0x400000) << 4);
3565         }
3566       } immop;
3567       EmitT32_32(Link(0xf000c000U, location, immop, &kT32BlxInfo));
3568       AdvanceIT();
3569       return;
3570     }
3571   } else {
3572     // BLX{<c>}{<q>} <label> ; A2
3573     if (((location->IsBound() && (offset >= -33554432) &&
3574           (offset <= 33554430) && ((offset & 0x1) == 0)) ||
3575          !location->IsBound())) {
3576       if (cond.Is(al) || AllowStronglyDiscouraged()) {
3577         static class EmitOp : public Location::EmitOperator {
3578          public:
3579           EmitOp() : Location::EmitOperator(A32) {}
3580           virtual uint32_t Encode(uint32_t instr,
3581                                   Location::Offset program_counter,
3582                                   const Location* loc) const VIXL_OVERRIDE {
3583             program_counter += kA32PcDelta;
3584             Location::Offset off =
3585                 loc->GetLocation() - AlignDown(program_counter, 4);
3586             VIXL_ASSERT((off >= -33554432) && (off <= 33554430) &&
3587                         ((off & 0x1) == 0));
3588             const int32_t target = off >> 1;
3589             return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3590           }
3591         } immop;
3592         EmitA32(Link(0xfa000000U, location, immop, &kA32BlxInfo));
3593         return;
3594       }
3595     }
3596   }
3597   Delegate(kBlx, &Assembler::blx, cond, location);
3598 }
3599 
blx_info(Condition cond,Location * location,const struct ReferenceInfo ** info)3600 bool Assembler::blx_info(Condition cond,
3601                          Location* location,
3602                          const struct ReferenceInfo** info) {
3603   VIXL_ASSERT(!location->IsBound());
3604   USE(location);
3605   USE(cond);
3606   if (IsUsingT32()) {
3607     // BLX{<c>}{<q>} <label> ; T2
3608     if (true) {
3609       *info = &kT32BlxInfo;
3610       return true;
3611     }
3612   } else {
3613     // BLX{<c>}{<q>} <label> ; A2
3614     if (true) {
3615       *info = &kA32BlxInfo;
3616       return true;
3617     }
3618   }
3619   return false;
3620 }
3621 
blx(Condition cond,Register rm)3622 void Assembler::blx(Condition cond, Register rm) {
3623   VIXL_ASSERT(AllowAssembler());
3624   CheckIT(cond);
3625   if (IsUsingT32()) {
3626     // BLX{<c>}{<q>} <Rm> ; T1
3627     if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3628          AllowUnpredictable())) {
3629       EmitT32_16(0x4780 | (rm.GetCode() << 3));
3630       AdvanceIT();
3631       return;
3632     }
3633   } else {
3634     // BLX{<c>}{<q>} <Rm> ; A1
3635     if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
3636       EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3637       return;
3638     }
3639   }
3640   Delegate(kBlx, &Assembler::blx, cond, rm);
3641 }
3642 
bx(Condition cond,Register rm)3643 void Assembler::bx(Condition cond, Register rm) {
3644   VIXL_ASSERT(AllowAssembler());
3645   CheckIT(cond);
3646   if (IsUsingT32()) {
3647     // BX{<c>}{<q>} <Rm> ; T1
3648     if ((OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3649       EmitT32_16(0x4700 | (rm.GetCode() << 3));
3650       AdvanceIT();
3651       return;
3652     }
3653   } else {
3654     // BX{<c>}{<q>} <Rm> ; A1
3655     if (cond.IsNotNever()) {
3656       EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3657       return;
3658     }
3659   }
3660   Delegate(kBx, &Assembler::bx, cond, rm);
3661 }
3662 
bxj(Condition cond,Register rm)3663 void Assembler::bxj(Condition cond, Register rm) {
3664   VIXL_ASSERT(AllowAssembler());
3665   CheckIT(cond);
3666   if (IsUsingT32()) {
3667     // BXJ{<c>}{<q>} <Rm> ; T1
3668     if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3669          AllowUnpredictable())) {
3670       EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3671       AdvanceIT();
3672       return;
3673     }
3674   } else {
3675     // BXJ{<c>}{<q>} <Rm> ; A1
3676     if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
3677       EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3678       return;
3679     }
3680   }
3681   Delegate(kBxj, &Assembler::bxj, cond, rm);
3682 }
3683 
cbnz(Register rn,Location * location)3684 void Assembler::cbnz(Register rn, Location* location) {
3685   VIXL_ASSERT(AllowAssembler());
3686   CheckIT(al);
3687   Location::Offset offset =
3688       location->IsBound()
3689           ? location->GetLocation() -
3690                 (GetCursorOffset() + GetArchitectureStatePCOffset())
3691           : 0;
3692   if (IsUsingT32()) {
3693     // CBNZ{<q>} <Rn>, <label> ; T1
3694     if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3695                         (offset <= 126) && ((offset & 0x1) == 0)) ||
3696                        !location->IsBound())) {
3697       static class EmitOp : public Location::EmitOperator {
3698        public:
3699         EmitOp() : Location::EmitOperator(T32) {}
3700         virtual uint32_t Encode(uint32_t instr,
3701                                 Location::Offset program_counter,
3702                                 const Location* loc) const VIXL_OVERRIDE {
3703           program_counter += kT32PcDelta;
3704           Location::Offset off = loc->GetLocation() - program_counter;
3705           VIXL_ASSERT((off >= 0) && (off <= 126) && ((off & 0x1) == 0));
3706           const int32_t target = off >> 1;
3707           return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3708         }
3709       } immop;
3710       EmitT32_16(Link(0xb900 | rn.GetCode(), location, immop, &kT16CbzInfo));
3711       AdvanceIT();
3712       return;
3713     }
3714   }
3715   Delegate(kCbnz, &Assembler::cbnz, rn, location);
3716 }
3717 
cbnz_info(Register rn,Location * location,const struct ReferenceInfo ** info)3718 bool Assembler::cbnz_info(Register rn,
3719                           Location* location,
3720                           const struct ReferenceInfo** info) {
3721   VIXL_ASSERT(!location->IsBound());
3722   USE(location);
3723   if (IsUsingT32()) {
3724     // CBNZ{<q>} <Rn>, <label> ; T1
3725     if (rn.IsLow()) {
3726       *info = &kT16CbzInfo;
3727       return true;
3728     }
3729   }
3730   return false;
3731 }
3732 
cbz(Register rn,Location * location)3733 void Assembler::cbz(Register rn, Location* location) {
3734   VIXL_ASSERT(AllowAssembler());
3735   CheckIT(al);
3736   Location::Offset offset =
3737       location->IsBound()
3738           ? location->GetLocation() -
3739                 (GetCursorOffset() + GetArchitectureStatePCOffset())
3740           : 0;
3741   if (IsUsingT32()) {
3742     // CBZ{<q>} <Rn>, <label> ; T1
3743     if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3744                         (offset <= 126) && ((offset & 0x1) == 0)) ||
3745                        !location->IsBound())) {
3746       static class EmitOp : public Location::EmitOperator {
3747        public:
3748         EmitOp() : Location::EmitOperator(T32) {}
3749         virtual uint32_t Encode(uint32_t instr,
3750                                 Location::Offset program_counter,
3751                                 const Location* loc) const VIXL_OVERRIDE {
3752           program_counter += kT32PcDelta;
3753           Location::Offset off = loc->GetLocation() - program_counter;
3754           VIXL_ASSERT((off >= 0) && (off <= 126) && ((off & 0x1) == 0));
3755           const int32_t target = off >> 1;
3756           return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3757         }
3758       } immop;
3759       EmitT32_16(Link(0xb100 | rn.GetCode(), location, immop, &kT16CbzInfo));
3760       AdvanceIT();
3761       return;
3762     }
3763   }
3764   Delegate(kCbz, &Assembler::cbz, rn, location);
3765 }
3766 
cbz_info(Register rn,Location * location,const struct ReferenceInfo ** info)3767 bool Assembler::cbz_info(Register rn,
3768                          Location* location,
3769                          const struct ReferenceInfo** info) {
3770   VIXL_ASSERT(!location->IsBound());
3771   USE(location);
3772   if (IsUsingT32()) {
3773     // CBZ{<q>} <Rn>, <label> ; T1
3774     if (rn.IsLow()) {
3775       *info = &kT16CbzInfo;
3776       return true;
3777     }
3778   }
3779   return false;
3780 }
3781 
clrex(Condition cond)3782 void Assembler::clrex(Condition cond) {
3783   VIXL_ASSERT(AllowAssembler());
3784   CheckIT(cond);
3785   if (IsUsingT32()) {
3786     // CLREX{<c>}{<q>} ; T1
3787     EmitT32_32(0xf3bf8f2fU);
3788     AdvanceIT();
3789     return;
3790   } else {
3791     // CLREX{<c>}{<q>} ; A1
3792     if (cond.Is(al)) {
3793       EmitA32(0xf57ff01fU);
3794       return;
3795     }
3796   }
3797   Delegate(kClrex, &Assembler::clrex, cond);
3798 }
3799 
clz(Condition cond,Register rd,Register rm)3800 void Assembler::clz(Condition cond, Register rd, Register rm) {
3801   VIXL_ASSERT(AllowAssembler());
3802   CheckIT(cond);
3803   if (IsUsingT32()) {
3804     // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
3805     if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3806       EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3807                  (rm.GetCode() << 16));
3808       AdvanceIT();
3809       return;
3810     }
3811   } else {
3812     // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
3813     if (cond.IsNotNever() &&
3814         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3815       EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3816               rm.GetCode());
3817       return;
3818     }
3819   }
3820   Delegate(kClz, &Assembler::clz, cond, rd, rm);
3821 }
3822 
cmn(Condition cond,EncodingSize size,Register rn,const Operand & operand)3823 void Assembler::cmn(Condition cond,
3824                     EncodingSize size,
3825                     Register rn,
3826                     const Operand& operand) {
3827   VIXL_ASSERT(AllowAssembler());
3828   CheckIT(cond);
3829   if (operand.IsImmediate()) {
3830     uint32_t imm = operand.GetImmediate();
3831     if (IsUsingT32()) {
3832       ImmediateT32 immediate_t32(imm);
3833       // CMN{<c>}{<q>} <Rn>, #<const> ; T1
3834       if (!size.IsNarrow() && immediate_t32.IsValid() &&
3835           (!rn.IsPC() || AllowUnpredictable())) {
3836         EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3837                    (immediate_t32.GetEncodingValue() & 0xff) |
3838                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3839                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3840         AdvanceIT();
3841         return;
3842       }
3843     } else {
3844       ImmediateA32 immediate_a32(imm);
3845       // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3846       if (immediate_a32.IsValid() && cond.IsNotNever()) {
3847         EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3848                 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3849         return;
3850       }
3851     }
3852   }
3853   if (operand.IsImmediateShiftedRegister()) {
3854     Register rm = operand.GetBaseRegister();
3855     if (operand.IsPlainRegister()) {
3856       if (IsUsingT32()) {
3857         // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3858         if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3859           EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3860           AdvanceIT();
3861           return;
3862         }
3863       }
3864     }
3865     Shift shift = operand.GetShift();
3866     uint32_t amount = operand.GetShiftAmount();
3867     if (IsUsingT32()) {
3868       // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
3869       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3870           ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3871         uint32_t amount_ = amount % 32;
3872         EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3873                    (operand.GetTypeEncodingValue() << 4) |
3874                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3875         AdvanceIT();
3876         return;
3877       }
3878     } else {
3879       // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3880       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3881         uint32_t amount_ = amount % 32;
3882         EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3883                 (rn.GetCode() << 16) | rm.GetCode() |
3884                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3885         return;
3886       }
3887     }
3888   }
3889   if (operand.IsRegisterShiftedRegister()) {
3890     Register rm = operand.GetBaseRegister();
3891     Shift shift = operand.GetShift();
3892     Register rs = operand.GetShiftRegister();
3893     if (IsUsingA32()) {
3894       // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3895       if (cond.IsNotNever() &&
3896           ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
3897         EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3898                 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3899                 (rs.GetCode() << 8));
3900         return;
3901       }
3902     }
3903   }
3904   Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3905 }
3906 
cmp(Condition cond,EncodingSize size,Register rn,const Operand & operand)3907 void Assembler::cmp(Condition cond,
3908                     EncodingSize size,
3909                     Register rn,
3910                     const Operand& operand) {
3911   VIXL_ASSERT(AllowAssembler());
3912   CheckIT(cond);
3913   if (operand.IsImmediate()) {
3914     uint32_t imm = operand.GetImmediate();
3915     if (IsUsingT32()) {
3916       ImmediateT32 immediate_t32(imm);
3917       // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3918       if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3919         EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3920         AdvanceIT();
3921         return;
3922       }
3923       // CMP{<c>}{<q>} <Rn>, #<const> ; T2
3924       if (!size.IsNarrow() && immediate_t32.IsValid() &&
3925           (!rn.IsPC() || AllowUnpredictable())) {
3926         EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3927                    (immediate_t32.GetEncodingValue() & 0xff) |
3928                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3929                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3930         AdvanceIT();
3931         return;
3932       }
3933     } else {
3934       ImmediateA32 immediate_a32(imm);
3935       // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3936       if (immediate_a32.IsValid() && cond.IsNotNever()) {
3937         EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3938                 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3939         return;
3940       }
3941     }
3942   }
3943   if (operand.IsImmediateShiftedRegister()) {
3944     Register rm = operand.GetBaseRegister();
3945     if (operand.IsPlainRegister()) {
3946       if (IsUsingT32()) {
3947         // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3948         if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3949           EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3950           AdvanceIT();
3951           return;
3952         }
3953         // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
3954         if (!size.IsWide() &&
3955             ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3956           EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3957                      ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3958           AdvanceIT();
3959           return;
3960         }
3961       }
3962     }
3963     Shift shift = operand.GetShift();
3964     uint32_t amount = operand.GetShiftAmount();
3965     if (IsUsingT32()) {
3966       // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
3967       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3968           ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3969         uint32_t amount_ = amount % 32;
3970         EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3971                    (operand.GetTypeEncodingValue() << 4) |
3972                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3973         AdvanceIT();
3974         return;
3975       }
3976     } else {
3977       // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3978       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3979         uint32_t amount_ = amount % 32;
3980         EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3981                 (rn.GetCode() << 16) | rm.GetCode() |
3982                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3983         return;
3984       }
3985     }
3986   }
3987   if (operand.IsRegisterShiftedRegister()) {
3988     Register rm = operand.GetBaseRegister();
3989     Shift shift = operand.GetShift();
3990     Register rs = operand.GetShiftRegister();
3991     if (IsUsingA32()) {
3992       // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3993       if (cond.IsNotNever() &&
3994           ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
3995         EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3996                 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3997                 (rs.GetCode() << 8));
3998         return;
3999       }
4000     }
4001   }
4002   Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
4003 }
4004 
crc32b(Condition cond,Register rd,Register rn,Register rm)4005 void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
4006   VIXL_ASSERT(AllowAssembler());
4007   CheckIT(cond);
4008   if (IsUsingT32()) {
4009     // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
4010     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4011          AllowUnpredictable())) {
4012       EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4013                  rm.GetCode());
4014       AdvanceIT();
4015       return;
4016     }
4017   } else {
4018     // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
4019     if ((cond.Is(al) || AllowUnpredictable()) &&
4020         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4021       EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4022               (rn.GetCode() << 16) | rm.GetCode());
4023       return;
4024     }
4025   }
4026   Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
4027 }
4028 
crc32cb(Condition cond,Register rd,Register rn,Register rm)4029 void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
4030   VIXL_ASSERT(AllowAssembler());
4031   CheckIT(cond);
4032   if (IsUsingT32()) {
4033     // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
4034     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4035          AllowUnpredictable())) {
4036       EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4037                  rm.GetCode());
4038       AdvanceIT();
4039       return;
4040     }
4041   } else {
4042     // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
4043     if ((cond.Is(al) || AllowUnpredictable()) &&
4044         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4045       EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4046               (rn.GetCode() << 16) | rm.GetCode());
4047       return;
4048     }
4049   }
4050   Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
4051 }
4052 
crc32ch(Condition cond,Register rd,Register rn,Register rm)4053 void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
4054   VIXL_ASSERT(AllowAssembler());
4055   CheckIT(cond);
4056   if (IsUsingT32()) {
4057     // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
4058     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4059          AllowUnpredictable())) {
4060       EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4061                  rm.GetCode());
4062       AdvanceIT();
4063       return;
4064     }
4065   } else {
4066     // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
4067     if ((cond.Is(al) || AllowUnpredictable()) &&
4068         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4069       EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4070               (rn.GetCode() << 16) | rm.GetCode());
4071       return;
4072     }
4073   }
4074   Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
4075 }
4076 
crc32cw(Condition cond,Register rd,Register rn,Register rm)4077 void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
4078   VIXL_ASSERT(AllowAssembler());
4079   CheckIT(cond);
4080   if (IsUsingT32()) {
4081     // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
4082     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4083          AllowUnpredictable())) {
4084       EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4085                  rm.GetCode());
4086       AdvanceIT();
4087       return;
4088     }
4089   } else {
4090     // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
4091     if ((cond.Is(al) || AllowUnpredictable()) &&
4092         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4093       EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4094               (rn.GetCode() << 16) | rm.GetCode());
4095       return;
4096     }
4097   }
4098   Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
4099 }
4100 
crc32h(Condition cond,Register rd,Register rn,Register rm)4101 void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
4102   VIXL_ASSERT(AllowAssembler());
4103   CheckIT(cond);
4104   if (IsUsingT32()) {
4105     // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
4106     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4107          AllowUnpredictable())) {
4108       EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4109                  rm.GetCode());
4110       AdvanceIT();
4111       return;
4112     }
4113   } else {
4114     // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
4115     if ((cond.Is(al) || AllowUnpredictable()) &&
4116         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4117       EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4118               (rn.GetCode() << 16) | rm.GetCode());
4119       return;
4120     }
4121   }
4122   Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
4123 }
4124 
crc32w(Condition cond,Register rd,Register rn,Register rm)4125 void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
4126   VIXL_ASSERT(AllowAssembler());
4127   CheckIT(cond);
4128   if (IsUsingT32()) {
4129     // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
4130     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4131          AllowUnpredictable())) {
4132       EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4133                  rm.GetCode());
4134       AdvanceIT();
4135       return;
4136     }
4137   } else {
4138     // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
4139     if ((cond.Is(al) || AllowUnpredictable()) &&
4140         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4141       EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4142               (rn.GetCode() << 16) | rm.GetCode());
4143       return;
4144     }
4145   }
4146   Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
4147 }
4148 
dmb(Condition cond,MemoryBarrier option)4149 void Assembler::dmb(Condition cond, MemoryBarrier option) {
4150   VIXL_ASSERT(AllowAssembler());
4151   CheckIT(cond);
4152   if (IsUsingT32()) {
4153     // DMB{<c>}{<q>} {<option>} ; T1
4154     EmitT32_32(0xf3bf8f50U | option.GetType());
4155     AdvanceIT();
4156     return;
4157   } else {
4158     // DMB{<c>}{<q>} {<option>} ; A1
4159     if (cond.Is(al)) {
4160       EmitA32(0xf57ff050U | option.GetType());
4161       return;
4162     }
4163   }
4164   Delegate(kDmb, &Assembler::dmb, cond, option);
4165 }
4166 
dsb(Condition cond,MemoryBarrier option)4167 void Assembler::dsb(Condition cond, MemoryBarrier option) {
4168   VIXL_ASSERT(AllowAssembler());
4169   CheckIT(cond);
4170   if (IsUsingT32()) {
4171     // DSB{<c>}{<q>} {<option>} ; T1
4172     EmitT32_32(0xf3bf8f40U | option.GetType());
4173     AdvanceIT();
4174     return;
4175   } else {
4176     // DSB{<c>}{<q>} {<option>} ; A1
4177     if (cond.Is(al)) {
4178       EmitA32(0xf57ff040U | option.GetType());
4179       return;
4180     }
4181   }
4182   Delegate(kDsb, &Assembler::dsb, cond, option);
4183 }
4184 
eor(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)4185 void Assembler::eor(Condition cond,
4186                     EncodingSize size,
4187                     Register rd,
4188                     Register rn,
4189                     const Operand& operand) {
4190   VIXL_ASSERT(AllowAssembler());
4191   CheckIT(cond);
4192   if (operand.IsImmediate()) {
4193     uint32_t imm = operand.GetImmediate();
4194     if (IsUsingT32()) {
4195       ImmediateT32 immediate_t32(imm);
4196       // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
4197       if (!size.IsNarrow() && immediate_t32.IsValid() &&
4198           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4199         EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4200                    (immediate_t32.GetEncodingValue() & 0xff) |
4201                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4202                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4203         AdvanceIT();
4204         return;
4205       }
4206     } else {
4207       ImmediateA32 immediate_a32(imm);
4208       // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4209       if (immediate_a32.IsValid() && cond.IsNotNever()) {
4210         EmitA32(0x02200000U | (cond.GetCondition() << 28) |
4211                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4212                 immediate_a32.GetEncodingValue());
4213         return;
4214       }
4215     }
4216   }
4217   if (operand.IsImmediateShiftedRegister()) {
4218     Register rm = operand.GetBaseRegister();
4219     if (operand.IsPlainRegister()) {
4220       if (IsUsingT32()) {
4221         // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4222         if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4223             rm.IsLow()) {
4224           EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4225           AdvanceIT();
4226           return;
4227         }
4228       }
4229     }
4230     Shift shift = operand.GetShift();
4231     uint32_t amount = operand.GetShiftAmount();
4232     if (IsUsingT32()) {
4233       // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
4234       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
4235           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4236         uint32_t amount_ = amount % 32;
4237         EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4238                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4239                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4240         AdvanceIT();
4241         return;
4242       }
4243     } else {
4244       // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4245       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4246         uint32_t amount_ = amount % 32;
4247         EmitA32(0x00200000U | (cond.GetCondition() << 28) |
4248                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4249                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4250         return;
4251       }
4252     }
4253   }
4254   if (operand.IsRegisterShiftedRegister()) {
4255     Register rm = operand.GetBaseRegister();
4256     Shift shift = operand.GetShift();
4257     Register rs = operand.GetShiftRegister();
4258     if (IsUsingA32()) {
4259       // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
4260       if (cond.IsNotNever() &&
4261           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4262            AllowUnpredictable())) {
4263         EmitA32(0x00200010U | (cond.GetCondition() << 28) |
4264                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4265                 (shift.GetType() << 5) | (rs.GetCode() << 8));
4266         return;
4267       }
4268     }
4269   }
4270   Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
4271 }
4272 
eors(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)4273 void Assembler::eors(Condition cond,
4274                      EncodingSize size,
4275                      Register rd,
4276                      Register rn,
4277                      const Operand& operand) {
4278   VIXL_ASSERT(AllowAssembler());
4279   CheckIT(cond);
4280   if (operand.IsImmediate()) {
4281     uint32_t imm = operand.GetImmediate();
4282     if (IsUsingT32()) {
4283       ImmediateT32 immediate_t32(imm);
4284       // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
4285       if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
4286           (!rn.IsPC() || AllowUnpredictable())) {
4287         EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4288                    (immediate_t32.GetEncodingValue() & 0xff) |
4289                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4290                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4291         AdvanceIT();
4292         return;
4293       }
4294     } else {
4295       ImmediateA32 immediate_a32(imm);
4296       // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4297       if (immediate_a32.IsValid() && cond.IsNotNever()) {
4298         EmitA32(0x02300000U | (cond.GetCondition() << 28) |
4299                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4300                 immediate_a32.GetEncodingValue());
4301         return;
4302       }
4303     }
4304   }
4305   if (operand.IsImmediateShiftedRegister()) {
4306     Register rm = operand.GetBaseRegister();
4307     if (operand.IsPlainRegister()) {
4308       if (IsUsingT32()) {
4309         // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4310         if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4311             rm.IsLow()) {
4312           EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4313           AdvanceIT();
4314           return;
4315         }
4316       }
4317     }
4318     Shift shift = operand.GetShift();
4319     uint32_t amount = operand.GetShiftAmount();
4320     if (IsUsingT32()) {
4321       // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
4322       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
4323           ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4324         uint32_t amount_ = amount % 32;
4325         EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4326                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4327                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4328         AdvanceIT();
4329         return;
4330       }
4331     } else {
4332       // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4333       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4334         uint32_t amount_ = amount % 32;
4335         EmitA32(0x00300000U | (cond.GetCondition() << 28) |
4336                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4337                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4338         return;
4339       }
4340     }
4341   }
4342   if (operand.IsRegisterShiftedRegister()) {
4343     Register rm = operand.GetBaseRegister();
4344     Shift shift = operand.GetShift();
4345     Register rs = operand.GetShiftRegister();
4346     if (IsUsingA32()) {
4347       // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
4348       if (cond.IsNotNever() &&
4349           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4350            AllowUnpredictable())) {
4351         EmitA32(0x00300010U | (cond.GetCondition() << 28) |
4352                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4353                 (shift.GetType() << 5) | (rs.GetCode() << 8));
4354         return;
4355       }
4356     }
4357   }
4358   Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
4359 }
4360 
fldmdbx(Condition cond,Register rn,WriteBack write_back,DRegisterList dreglist)4361 void Assembler::fldmdbx(Condition cond,
4362                         Register rn,
4363                         WriteBack write_back,
4364                         DRegisterList dreglist) {
4365   VIXL_ASSERT(AllowAssembler());
4366   CheckIT(cond);
4367   if (IsUsingT32()) {
4368     // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4369     if (write_back.DoesWriteBack() &&
4370         (((dreglist.GetLength() <= 16) &&
4371           (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4372          AllowUnpredictable())) {
4373       const DRegister& dreg = dreglist.GetFirstDRegister();
4374       unsigned len = dreglist.GetLength() * 2;
4375       EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4376                  (len & 0xff));
4377       AdvanceIT();
4378       return;
4379     }
4380   } else {
4381     // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4382     if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4383         (((dreglist.GetLength() <= 16) &&
4384           (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4385          AllowUnpredictable())) {
4386       const DRegister& dreg = dreglist.GetFirstDRegister();
4387       unsigned len = dreglist.GetLength() * 2;
4388       EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4389               dreg.Encode(22, 12) | (len & 0xff));
4390       return;
4391     }
4392   }
4393   Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
4394 }
4395 
fldmiax(Condition cond,Register rn,WriteBack write_back,DRegisterList dreglist)4396 void Assembler::fldmiax(Condition cond,
4397                         Register rn,
4398                         WriteBack write_back,
4399                         DRegisterList dreglist) {
4400   VIXL_ASSERT(AllowAssembler());
4401   CheckIT(cond);
4402   if (IsUsingT32()) {
4403     // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4404     if ((((dreglist.GetLength() <= 16) &&
4405           (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4406          AllowUnpredictable())) {
4407       const DRegister& dreg = dreglist.GetFirstDRegister();
4408       unsigned len = dreglist.GetLength() * 2;
4409       EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4410                  (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4411                  (len & 0xff));
4412       AdvanceIT();
4413       return;
4414     }
4415   } else {
4416     // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4417     if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4418                                (dreglist.GetLastDRegister().GetCode() < 16) &&
4419                                (!rn.IsPC() || !write_back.DoesWriteBack())) ||
4420                               AllowUnpredictable())) {
4421       const DRegister& dreg = dreglist.GetFirstDRegister();
4422       unsigned len = dreglist.GetLength() * 2;
4423       EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4424               (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4425               (len & 0xff));
4426       return;
4427     }
4428   }
4429   Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4430 }
4431 
fstmdbx(Condition cond,Register rn,WriteBack write_back,DRegisterList dreglist)4432 void Assembler::fstmdbx(Condition cond,
4433                         Register rn,
4434                         WriteBack write_back,
4435                         DRegisterList dreglist) {
4436   VIXL_ASSERT(AllowAssembler());
4437   CheckIT(cond);
4438   if (IsUsingT32()) {
4439     // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4440     if (write_back.DoesWriteBack() &&
4441         (((dreglist.GetLength() <= 16) &&
4442           (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4443          AllowUnpredictable())) {
4444       const DRegister& dreg = dreglist.GetFirstDRegister();
4445       unsigned len = dreglist.GetLength() * 2;
4446       EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4447                  (len & 0xff));
4448       AdvanceIT();
4449       return;
4450     }
4451   } else {
4452     // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4453     if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4454         (((dreglist.GetLength() <= 16) &&
4455           (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4456          AllowUnpredictable())) {
4457       const DRegister& dreg = dreglist.GetFirstDRegister();
4458       unsigned len = dreglist.GetLength() * 2;
4459       EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4460               dreg.Encode(22, 12) | (len & 0xff));
4461       return;
4462     }
4463   }
4464   Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4465 }
4466 
fstmiax(Condition cond,Register rn,WriteBack write_back,DRegisterList dreglist)4467 void Assembler::fstmiax(Condition cond,
4468                         Register rn,
4469                         WriteBack write_back,
4470                         DRegisterList dreglist) {
4471   VIXL_ASSERT(AllowAssembler());
4472   CheckIT(cond);
4473   if (IsUsingT32()) {
4474     // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4475     if ((((dreglist.GetLength() <= 16) &&
4476           (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4477          AllowUnpredictable())) {
4478       const DRegister& dreg = dreglist.GetFirstDRegister();
4479       unsigned len = dreglist.GetLength() * 2;
4480       EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4481                  (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4482                  (len & 0xff));
4483       AdvanceIT();
4484       return;
4485     }
4486   } else {
4487     // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4488     if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4489                                (dreglist.GetLastDRegister().GetCode() < 16) &&
4490                                (!rn.IsPC() || !write_back.DoesWriteBack())) ||
4491                               AllowUnpredictable())) {
4492       const DRegister& dreg = dreglist.GetFirstDRegister();
4493       unsigned len = dreglist.GetLength() * 2;
4494       EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4495               (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4496               (len & 0xff));
4497       return;
4498     }
4499   }
4500   Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4501 }
4502 
hlt(Condition cond,uint32_t imm)4503 void Assembler::hlt(Condition cond, uint32_t imm) {
4504   VIXL_ASSERT(AllowAssembler());
4505   CheckIT(cond);
4506   if (IsUsingT32()) {
4507     // HLT{<q>} {#}<imm> ; T1
4508     if ((imm <= 63)) {
4509       EmitT32_16(0xba80 | imm);
4510       AdvanceIT();
4511       return;
4512     }
4513   } else {
4514     // HLT{<q>} {#}<imm> ; A1
4515     if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4516       EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4517               ((imm & 0xfff0) << 4));
4518       return;
4519     }
4520   }
4521   Delegate(kHlt, &Assembler::hlt, cond, imm);
4522 }
4523 
hvc(Condition cond,uint32_t imm)4524 void Assembler::hvc(Condition cond, uint32_t imm) {
4525   VIXL_ASSERT(AllowAssembler());
4526   CheckIT(cond);
4527   if (IsUsingT32()) {
4528     // HVC{<q>} {#}<imm16> ; T1
4529     if ((imm <= 65535) && (OutsideITBlock() || AllowUnpredictable())) {
4530       EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4531       AdvanceIT();
4532       return;
4533     }
4534   } else {
4535     // HVC{<q>} {#}<imm16> ; A1
4536     if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4537       EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4538               ((imm & 0xfff0) << 4));
4539       return;
4540     }
4541   }
4542   Delegate(kHvc, &Assembler::hvc, cond, imm);
4543 }
4544 
isb(Condition cond,MemoryBarrier option)4545 void Assembler::isb(Condition cond, MemoryBarrier option) {
4546   VIXL_ASSERT(AllowAssembler());
4547   CheckIT(cond);
4548   if (IsUsingT32()) {
4549     // ISB{<c>}{<q>} {<option>} ; T1
4550     EmitT32_32(0xf3bf8f60U | option.GetType());
4551     AdvanceIT();
4552     return;
4553   } else {
4554     // ISB{<c>}{<q>} {<option>} ; A1
4555     if (cond.Is(al)) {
4556       EmitA32(0xf57ff060U | option.GetType());
4557       return;
4558     }
4559   }
4560   Delegate(kIsb, &Assembler::isb, cond, option);
4561 }
4562 
it(Condition cond,uint16_t mask)4563 void Assembler::it(Condition cond, uint16_t mask) {
4564   VIXL_ASSERT(AllowAssembler());
4565   CheckNotIT();
4566   if (mask != 0) {
4567     if ((cond.GetCondition() & 0x1) != 0) {
4568       if ((mask & 0x1) != 0) {
4569         mask ^= 0xE;
4570       } else if ((mask & 0x2) != 0) {
4571         mask ^= 0xC;
4572       } else if ((mask & 0x4) != 0) {
4573         mask ^= 0x8;
4574       }
4575     }
4576     if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
4577     SetIT(cond, mask);
4578     return;
4579   }
4580   DelegateIt(cond, mask);
4581 }
4582 
lda(Condition cond,Register rt,const MemOperand & operand)4583 void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
4584   VIXL_ASSERT(AllowAssembler());
4585   CheckIT(cond);
4586   if (operand.IsImmediateZero()) {
4587     Register rn = operand.GetBaseRegister();
4588     if (IsUsingT32()) {
4589       // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
4590       if (operand.IsOffset() &&
4591           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4592         EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4593         AdvanceIT();
4594         return;
4595       }
4596     } else {
4597       // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
4598       if (operand.IsOffset() && cond.IsNotNever() &&
4599           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4600         EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4601                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4602         return;
4603       }
4604     }
4605   }
4606   Delegate(kLda, &Assembler::lda, cond, rt, operand);
4607 }
4608 
ldab(Condition cond,Register rt,const MemOperand & operand)4609 void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
4610   VIXL_ASSERT(AllowAssembler());
4611   CheckIT(cond);
4612   if (operand.IsImmediateZero()) {
4613     Register rn = operand.GetBaseRegister();
4614     if (IsUsingT32()) {
4615       // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4616       if (operand.IsOffset() &&
4617           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4618         EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4619         AdvanceIT();
4620         return;
4621       }
4622     } else {
4623       // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4624       if (operand.IsOffset() && cond.IsNotNever() &&
4625           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4626         EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4627                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4628         return;
4629       }
4630     }
4631   }
4632   Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4633 }
4634 
ldaex(Condition cond,Register rt,const MemOperand & operand)4635 void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
4636   VIXL_ASSERT(AllowAssembler());
4637   CheckIT(cond);
4638   if (operand.IsImmediateZero()) {
4639     Register rn = operand.GetBaseRegister();
4640     if (IsUsingT32()) {
4641       // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
4642       if (operand.IsOffset() &&
4643           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4644         EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4645         AdvanceIT();
4646         return;
4647       }
4648     } else {
4649       // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
4650       if (operand.IsOffset() && cond.IsNotNever() &&
4651           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4652         EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4653                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4654         return;
4655       }
4656     }
4657   }
4658   Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4659 }
4660 
ldaexb(Condition cond,Register rt,const MemOperand & operand)4661 void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
4662   VIXL_ASSERT(AllowAssembler());
4663   CheckIT(cond);
4664   if (operand.IsImmediateZero()) {
4665     Register rn = operand.GetBaseRegister();
4666     if (IsUsingT32()) {
4667       // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4668       if (operand.IsOffset() &&
4669           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4670         EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4671         AdvanceIT();
4672         return;
4673       }
4674     } else {
4675       // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4676       if (operand.IsOffset() && cond.IsNotNever() &&
4677           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4678         EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4679                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4680         return;
4681       }
4682     }
4683   }
4684   Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4685 }
4686 
ldaexd(Condition cond,Register rt,Register rt2,const MemOperand & operand)4687 void Assembler::ldaexd(Condition cond,
4688                        Register rt,
4689                        Register rt2,
4690                        const MemOperand& operand) {
4691   VIXL_ASSERT(AllowAssembler());
4692   CheckIT(cond);
4693   if (operand.IsImmediateZero()) {
4694     Register rn = operand.GetBaseRegister();
4695     if (IsUsingT32()) {
4696       // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
4697       if (operand.IsOffset() &&
4698           ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4699         EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4700                    (rn.GetCode() << 16));
4701         AdvanceIT();
4702         return;
4703       }
4704     } else {
4705       // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4706       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
4707           operand.IsOffset() && cond.IsNotNever() &&
4708           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
4709            AllowUnpredictable())) {
4710         EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4711                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4712         return;
4713       }
4714     }
4715   }
4716   Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4717 }
4718 
ldaexh(Condition cond,Register rt,const MemOperand & operand)4719 void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
4720   VIXL_ASSERT(AllowAssembler());
4721   CheckIT(cond);
4722   if (operand.IsImmediateZero()) {
4723     Register rn = operand.GetBaseRegister();
4724     if (IsUsingT32()) {
4725       // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4726       if (operand.IsOffset() &&
4727           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4728         EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4729         AdvanceIT();
4730         return;
4731       }
4732     } else {
4733       // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4734       if (operand.IsOffset() && cond.IsNotNever() &&
4735           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4736         EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4737                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4738         return;
4739       }
4740     }
4741   }
4742   Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4743 }
4744 
ldah(Condition cond,Register rt,const MemOperand & operand)4745 void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
4746   VIXL_ASSERT(AllowAssembler());
4747   CheckIT(cond);
4748   if (operand.IsImmediateZero()) {
4749     Register rn = operand.GetBaseRegister();
4750     if (IsUsingT32()) {
4751       // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4752       if (operand.IsOffset() &&
4753           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4754         EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4755         AdvanceIT();
4756         return;
4757       }
4758     } else {
4759       // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4760       if (operand.IsOffset() && cond.IsNotNever() &&
4761           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4762         EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4763                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4764         return;
4765       }
4766     }
4767   }
4768   Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4769 }
4770 
ldm(Condition cond,EncodingSize size,Register rn,WriteBack write_back,RegisterList registers)4771 void Assembler::ldm(Condition cond,
4772                     EncodingSize size,
4773                     Register rn,
4774                     WriteBack write_back,
4775                     RegisterList registers) {
4776   VIXL_ASSERT(AllowAssembler());
4777   CheckIT(cond);
4778   if (IsUsingT32()) {
4779     // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4780     if (!size.IsWide() && rn.IsLow() &&
4781         (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4782          write_back.DoesWriteBack()) &&
4783         ((registers.GetList() & ~0xff) == 0)) {
4784       EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4785                  GetRegisterListEncoding(registers, 0, 8));
4786       AdvanceIT();
4787       return;
4788     }
4789     // LDM{<c>}{<q>} SP!, <registers> ; T1
4790     if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4791         registers.IsR0toR7orPC()) {
4792       EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4793                  GetRegisterListEncoding(registers, 0, 8));
4794       AdvanceIT();
4795       return;
4796     }
4797     // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
4798     if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4799         (!rn.IsPC() || AllowUnpredictable())) {
4800       EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4801                  (write_back.GetWriteBackUint32() << 21) |
4802                  (GetRegisterListEncoding(registers, 15, 1) << 15) |
4803                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
4804                  GetRegisterListEncoding(registers, 0, 13));
4805       AdvanceIT();
4806       return;
4807     }
4808   } else {
4809     // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
4810     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4811       EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4812               (write_back.GetWriteBackUint32() << 21) |
4813               GetRegisterListEncoding(registers, 0, 16));
4814       return;
4815     }
4816   }
4817   Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4818 }
4819 
ldmda(Condition cond,Register rn,WriteBack write_back,RegisterList registers)4820 void Assembler::ldmda(Condition cond,
4821                       Register rn,
4822                       WriteBack write_back,
4823                       RegisterList registers) {
4824   VIXL_ASSERT(AllowAssembler());
4825   CheckIT(cond);
4826   if (IsUsingA32()) {
4827     // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4828     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4829       EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4830               (write_back.GetWriteBackUint32() << 21) |
4831               GetRegisterListEncoding(registers, 0, 16));
4832       return;
4833     }
4834   }
4835   Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4836 }
4837 
ldmdb(Condition cond,Register rn,WriteBack write_back,RegisterList registers)4838 void Assembler::ldmdb(Condition cond,
4839                       Register rn,
4840                       WriteBack write_back,
4841                       RegisterList registers) {
4842   VIXL_ASSERT(AllowAssembler());
4843   CheckIT(cond);
4844   if (IsUsingT32()) {
4845     // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
4846     if (((registers.GetList() & ~0xdfff) == 0) &&
4847         (!rn.IsPC() || AllowUnpredictable())) {
4848       EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4849                  (write_back.GetWriteBackUint32() << 21) |
4850                  (GetRegisterListEncoding(registers, 15, 1) << 15) |
4851                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
4852                  GetRegisterListEncoding(registers, 0, 13));
4853       AdvanceIT();
4854       return;
4855     }
4856   } else {
4857     // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4858     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4859       EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4860               (write_back.GetWriteBackUint32() << 21) |
4861               GetRegisterListEncoding(registers, 0, 16));
4862       return;
4863     }
4864   }
4865   Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4866 }
4867 
ldmea(Condition cond,Register rn,WriteBack write_back,RegisterList registers)4868 void Assembler::ldmea(Condition cond,
4869                       Register rn,
4870                       WriteBack write_back,
4871                       RegisterList registers) {
4872   VIXL_ASSERT(AllowAssembler());
4873   CheckIT(cond);
4874   if (IsUsingT32()) {
4875     // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
4876     if (((registers.GetList() & ~0xdfff) == 0) &&
4877         (!rn.IsPC() || AllowUnpredictable())) {
4878       EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4879                  (write_back.GetWriteBackUint32() << 21) |
4880                  (GetRegisterListEncoding(registers, 15, 1) << 15) |
4881                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
4882                  GetRegisterListEncoding(registers, 0, 13));
4883       AdvanceIT();
4884       return;
4885     }
4886   } else {
4887     // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4888     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4889       EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4890               (write_back.GetWriteBackUint32() << 21) |
4891               GetRegisterListEncoding(registers, 0, 16));
4892       return;
4893     }
4894   }
4895   Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4896 }
4897 
ldmed(Condition cond,Register rn,WriteBack write_back,RegisterList registers)4898 void Assembler::ldmed(Condition cond,
4899                       Register rn,
4900                       WriteBack write_back,
4901                       RegisterList registers) {
4902   VIXL_ASSERT(AllowAssembler());
4903   CheckIT(cond);
4904   if (IsUsingA32()) {
4905     // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
4906     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4907       EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4908               (write_back.GetWriteBackUint32() << 21) |
4909               GetRegisterListEncoding(registers, 0, 16));
4910       return;
4911     }
4912   }
4913   Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4914 }
4915 
ldmfa(Condition cond,Register rn,WriteBack write_back,RegisterList registers)4916 void Assembler::ldmfa(Condition cond,
4917                       Register rn,
4918                       WriteBack write_back,
4919                       RegisterList registers) {
4920   VIXL_ASSERT(AllowAssembler());
4921   CheckIT(cond);
4922   if (IsUsingA32()) {
4923     // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4924     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4925       EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4926               (write_back.GetWriteBackUint32() << 21) |
4927               GetRegisterListEncoding(registers, 0, 16));
4928       return;
4929     }
4930   }
4931   Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4932 }
4933 
ldmfd(Condition cond,EncodingSize size,Register rn,WriteBack write_back,RegisterList registers)4934 void Assembler::ldmfd(Condition cond,
4935                       EncodingSize size,
4936                       Register rn,
4937                       WriteBack write_back,
4938                       RegisterList registers) {
4939   VIXL_ASSERT(AllowAssembler());
4940   CheckIT(cond);
4941   if (IsUsingT32()) {
4942     // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4943     if (!size.IsWide() && rn.IsLow() &&
4944         (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4945          write_back.DoesWriteBack()) &&
4946         ((registers.GetList() & ~0xff) == 0)) {
4947       EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4948                  GetRegisterListEncoding(registers, 0, 8));
4949       AdvanceIT();
4950       return;
4951     }
4952     // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
4953     if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4954         (!rn.IsPC() || AllowUnpredictable())) {
4955       EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4956                  (write_back.GetWriteBackUint32() << 21) |
4957                  (GetRegisterListEncoding(registers, 15, 1) << 15) |
4958                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
4959                  GetRegisterListEncoding(registers, 0, 13));
4960       AdvanceIT();
4961       return;
4962     }
4963   } else {
4964     // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
4965     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4966       EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4967               (write_back.GetWriteBackUint32() << 21) |
4968               GetRegisterListEncoding(registers, 0, 16));
4969       return;
4970     }
4971   }
4972   Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4973 }
4974 
ldmib(Condition cond,Register rn,WriteBack write_back,RegisterList registers)4975 void Assembler::ldmib(Condition cond,
4976                       Register rn,
4977                       WriteBack write_back,
4978                       RegisterList registers) {
4979   VIXL_ASSERT(AllowAssembler());
4980   CheckIT(cond);
4981   if (IsUsingA32()) {
4982     // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4983     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4984       EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4985               (write_back.GetWriteBackUint32() << 21) |
4986               GetRegisterListEncoding(registers, 0, 16));
4987       return;
4988     }
4989   }
4990   Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4991 }
4992 
ldr(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)4993 void Assembler::ldr(Condition cond,
4994                     EncodingSize size,
4995                     Register rt,
4996                     const MemOperand& operand) {
4997   VIXL_ASSERT(AllowAssembler());
4998   CheckIT(cond);
4999   if (operand.IsImmediate()) {
5000     Register rn = operand.GetBaseRegister();
5001     int32_t offset = operand.GetOffsetImmediate();
5002     if (IsUsingT32()) {
5003       // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5004       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5005           (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
5006         int32_t offset_ = offset >> 2;
5007         EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
5008                    ((offset_ & 0x1f) << 6));
5009         AdvanceIT();
5010         return;
5011       }
5012       // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
5013       if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
5014           ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
5015         int32_t offset_ = offset >> 2;
5016         EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
5017         AdvanceIT();
5018         return;
5019       }
5020       // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
5021       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5022           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5023           ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5024            AllowUnpredictable())) {
5025         EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5026                    (offset & 0xfff));
5027         AdvanceIT();
5028         return;
5029       }
5030       // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
5031       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5032           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5033           ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5034            AllowUnpredictable())) {
5035         EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5036                    (-offset & 0xff));
5037         AdvanceIT();
5038         return;
5039       }
5040       // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
5041       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5042           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5043           ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5044            AllowUnpredictable())) {
5045         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5046         uint32_t offset_ = abs(offset);
5047         EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5048                    offset_ | (sign << 9));
5049         AdvanceIT();
5050         return;
5051       }
5052       // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
5053       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5054           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5055           ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5056            AllowUnpredictable())) {
5057         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5058         uint32_t offset_ = abs(offset);
5059         EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5060                    offset_ | (sign << 9));
5061         AdvanceIT();
5062         return;
5063       }
5064       // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
5065       if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5066           rn.Is(pc) && operand.IsOffset() &&
5067           ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5068            AllowUnpredictable())) {
5069         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5070         uint32_t offset_ = abs(offset);
5071         EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5072         AdvanceIT();
5073         return;
5074       }
5075     } else {
5076       // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5077       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5078           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5079         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5080         uint32_t offset_ = abs(offset);
5081         EmitA32(0x05100000U | (cond.GetCondition() << 28) |
5082                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5083                 (sign << 23));
5084         return;
5085       }
5086       // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5087       if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5088           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5089         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5090         uint32_t offset_ = abs(offset);
5091         EmitA32(0x04100000U | (cond.GetCondition() << 28) |
5092                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5093                 (sign << 23));
5094         return;
5095       }
5096       // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5097       if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5098           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5099         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5100         uint32_t offset_ = abs(offset);
5101         EmitA32(0x05300000U | (cond.GetCondition() << 28) |
5102                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5103                 (sign << 23));
5104         return;
5105       }
5106       // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5107       if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
5108           operand.IsOffset() && cond.IsNotNever()) {
5109         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5110         uint32_t offset_ = abs(offset);
5111         EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
5112                 (rt.GetCode() << 12) | offset_ | (sign << 23));
5113         return;
5114       }
5115     }
5116   }
5117   if (operand.IsPlainRegister()) {
5118     Register rn = operand.GetBaseRegister();
5119     Sign sign = operand.GetSign();
5120     Register rm = operand.GetOffsetRegister();
5121     if (IsUsingT32()) {
5122       // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5123       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5124           sign.IsPlus() && operand.IsOffset()) {
5125         EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
5126                    (rm.GetCode() << 6));
5127         AdvanceIT();
5128         return;
5129       }
5130     }
5131   }
5132   if (operand.IsShiftedRegister()) {
5133     Register rn = operand.GetBaseRegister();
5134     Sign sign = operand.GetSign();
5135     Register rm = operand.GetOffsetRegister();
5136     Shift shift = operand.GetShift();
5137     uint32_t amount = operand.GetShiftAmount();
5138     if (IsUsingT32()) {
5139       // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5140       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5141           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5142           ((!rm.IsPC() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
5143            AllowUnpredictable())) {
5144         EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5145                    rm.GetCode() | (amount << 4));
5146         AdvanceIT();
5147         return;
5148       }
5149     } else {
5150       // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5151       if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5152           (!rm.IsPC() || AllowUnpredictable())) {
5153         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5154         uint32_t shift_ = TypeEncodingValue(shift);
5155         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5156         EmitA32(0x07100000U | (cond.GetCondition() << 28) |
5157                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5158                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5159         return;
5160       }
5161       // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
5162       if (operand.IsShiftValid() && operand.IsPostIndex() &&
5163           cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
5164         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5165         uint32_t shift_ = TypeEncodingValue(shift);
5166         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5167         EmitA32(0x06100000U | (cond.GetCondition() << 28) |
5168                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5169                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5170         return;
5171       }
5172       // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5173       if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5174           (!rm.IsPC() || AllowUnpredictable())) {
5175         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5176         uint32_t shift_ = TypeEncodingValue(shift);
5177         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5178         EmitA32(0x07300000U | (cond.GetCondition() << 28) |
5179                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5180                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5181         return;
5182       }
5183     }
5184   }
5185   Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
5186 }
5187 
ldr(Condition cond,EncodingSize size,Register rt,Location * location)5188 void Assembler::ldr(Condition cond,
5189                     EncodingSize size,
5190                     Register rt,
5191                     Location* location) {
5192   VIXL_ASSERT(AllowAssembler());
5193   CheckIT(cond);
5194   Location::Offset offset =
5195       location->IsBound()
5196           ? location->GetLocation() -
5197                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5198           : 0;
5199   if (IsUsingT32()) {
5200     // LDR{<c>}{<q>} <Rt>, <label> ; T1
5201     if (!size.IsWide() && rt.IsLow() &&
5202         ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
5203           ((offset & 0x3) == 0)) ||
5204          (!location->IsBound() && size.IsNarrow()))) {
5205       static class EmitOp : public Location::EmitOperator {
5206        public:
5207         EmitOp() : Location::EmitOperator(T32) {}
5208         virtual uint32_t Encode(uint32_t instr,
5209                                 Location::Offset program_counter,
5210                                 const Location* loc) const VIXL_OVERRIDE {
5211           program_counter += kT32PcDelta;
5212           Location::Offset off =
5213               loc->GetLocation() - AlignDown(program_counter, 4);
5214           VIXL_ASSERT((off >= 0) && (off <= 1020) && ((off & 0x3) == 0));
5215           const int32_t target = off >> 2;
5216           return instr | (target & 0xff);
5217         }
5218       } immop;
5219       EmitT32_16(
5220           Link(0x4800 | (rt.GetCode() << 8), location, immop, &kT16DataInfo));
5221       AdvanceIT();
5222       return;
5223     }
5224     // LDR{<c>}{<q>} <Rt>, <label> ; T2
5225     if (!size.IsNarrow() &&
5226         ((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5227          !location->IsBound()) &&
5228         ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5229          AllowUnpredictable())) {
5230       static class EmitOp : public Location::EmitOperator {
5231        public:
5232         EmitOp() : Location::EmitOperator(T32) {}
5233         virtual uint32_t Encode(uint32_t instr,
5234                                 Location::Offset program_counter,
5235                                 const Location* loc) const VIXL_OVERRIDE {
5236           program_counter += kT32PcDelta;
5237           Location::Offset off =
5238               loc->GetLocation() - AlignDown(program_counter, 4);
5239           VIXL_ASSERT((off >= -4095) && (off <= 4095));
5240           uint32_t U = (off >= 0);
5241           int32_t target = abs(off) | (U << 12);
5242           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5243         }
5244       } immop;
5245       EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12),
5246                       location,
5247                       immop,
5248                       &kT32FarDataInfo));
5249       AdvanceIT();
5250       return;
5251     }
5252   } else {
5253     // LDR{<c>}{<q>} <Rt>, <label> ; A1
5254     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5255          !location->IsBound()) &&
5256         cond.IsNotNever()) {
5257       static class EmitOp : public Location::EmitOperator {
5258        public:
5259         EmitOp() : Location::EmitOperator(A32) {}
5260         virtual uint32_t Encode(uint32_t instr,
5261                                 Location::Offset program_counter,
5262                                 const Location* loc) const VIXL_OVERRIDE {
5263           program_counter += kA32PcDelta;
5264           Location::Offset off =
5265               loc->GetLocation() - AlignDown(program_counter, 4);
5266           VIXL_ASSERT((off >= -4095) && (off <= 4095));
5267           uint32_t U = (off >= 0);
5268           int32_t target = abs(off) | (U << 12);
5269           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5270         }
5271       } immop;
5272       EmitA32(
5273           Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5274                location,
5275                immop,
5276                &kA32FarDataInfo));
5277       return;
5278     }
5279   }
5280   Delegate(kLdr, &Assembler::ldr, cond, size, rt, location);
5281 }
5282 
ldr_info(Condition cond,EncodingSize size,Register rt,Location * location,const struct ReferenceInfo ** info)5283 bool Assembler::ldr_info(Condition cond,
5284                          EncodingSize size,
5285                          Register rt,
5286                          Location* location,
5287                          const struct ReferenceInfo** info) {
5288   VIXL_ASSERT(!location->IsBound());
5289   USE(location);
5290   if (IsUsingT32()) {
5291     // LDR{<c>}{<q>} <Rt>, <label> ; T1
5292     if (!size.IsWide() && rt.IsLow() && size.IsNarrow()) {
5293       *info = &kT16DataInfo;
5294       return true;
5295     }
5296     // LDR{<c>}{<q>} <Rt>, <label> ; T2
5297     if (!size.IsNarrow()) {
5298       *info = &kT32FarDataInfo;
5299       return true;
5300     }
5301   } else {
5302     // LDR{<c>}{<q>} <Rt>, <label> ; A1
5303     if (cond.IsNotNever()) {
5304       *info = &kA32FarDataInfo;
5305       return true;
5306     }
5307   }
5308   return false;
5309 }
5310 
ldrb(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)5311 void Assembler::ldrb(Condition cond,
5312                      EncodingSize size,
5313                      Register rt,
5314                      const MemOperand& operand) {
5315   VIXL_ASSERT(AllowAssembler());
5316   CheckIT(cond);
5317   if (operand.IsImmediate()) {
5318     Register rn = operand.GetBaseRegister();
5319     int32_t offset = operand.GetOffsetImmediate();
5320     if (IsUsingT32()) {
5321       // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5322       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5323           (offset <= 31) && operand.IsOffset()) {
5324         EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
5325                    ((offset & 0x1f) << 6));
5326         AdvanceIT();
5327         return;
5328       }
5329       // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5330       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5331           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5332         EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5333                    (offset & 0xfff));
5334         AdvanceIT();
5335         return;
5336       }
5337       // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5338       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5339           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5340         EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5341                    (-offset & 0xff));
5342         AdvanceIT();
5343         return;
5344       }
5345       // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5346       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5347           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5348         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5349         uint32_t offset_ = abs(offset);
5350         EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5351                    offset_ | (sign << 9));
5352         AdvanceIT();
5353         return;
5354       }
5355       // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5356       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5357           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5358         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5359         uint32_t offset_ = abs(offset);
5360         EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5361                    offset_ | (sign << 9));
5362         AdvanceIT();
5363         return;
5364       }
5365       // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5366       if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5367           rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
5368         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5369         uint32_t offset_ = abs(offset);
5370         EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5371         AdvanceIT();
5372         return;
5373       }
5374     } else {
5375       // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5376       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5377           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5378           (!rt.IsPC() || AllowUnpredictable())) {
5379         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5380         uint32_t offset_ = abs(offset);
5381         EmitA32(0x05500000U | (cond.GetCondition() << 28) |
5382                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5383                 (sign << 23));
5384         return;
5385       }
5386       // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5387       if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5388           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5389           (!rt.IsPC() || AllowUnpredictable())) {
5390         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5391         uint32_t offset_ = abs(offset);
5392         EmitA32(0x04500000U | (cond.GetCondition() << 28) |
5393                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5394                 (sign << 23));
5395         return;
5396       }
5397       // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5398       if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5399           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5400           (!rt.IsPC() || AllowUnpredictable())) {
5401         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5402         uint32_t offset_ = abs(offset);
5403         EmitA32(0x05700000U | (cond.GetCondition() << 28) |
5404                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5405                 (sign << 23));
5406         return;
5407       }
5408       // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5409       if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
5410           operand.IsOffset() && cond.IsNotNever() &&
5411           (!rt.IsPC() || AllowUnpredictable())) {
5412         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5413         uint32_t offset_ = abs(offset);
5414         EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
5415                 (rt.GetCode() << 12) | offset_ | (sign << 23));
5416         return;
5417       }
5418     }
5419   }
5420   if (operand.IsPlainRegister()) {
5421     Register rn = operand.GetBaseRegister();
5422     Sign sign = operand.GetSign();
5423     Register rm = operand.GetOffsetRegister();
5424     if (IsUsingT32()) {
5425       // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5426       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5427           sign.IsPlus() && operand.IsOffset()) {
5428         EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
5429                    (rm.GetCode() << 6));
5430         AdvanceIT();
5431         return;
5432       }
5433     }
5434   }
5435   if (operand.IsShiftedRegister()) {
5436     Register rn = operand.GetBaseRegister();
5437     Sign sign = operand.GetSign();
5438     Register rm = operand.GetOffsetRegister();
5439     Shift shift = operand.GetShift();
5440     uint32_t amount = operand.GetShiftAmount();
5441     if (IsUsingT32()) {
5442       // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5443       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5444           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
5445           (!rm.IsPC() || AllowUnpredictable())) {
5446         EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5447                    rm.GetCode() | (amount << 4));
5448         AdvanceIT();
5449         return;
5450       }
5451     } else {
5452       // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5453       if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5454           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
5455         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5456         uint32_t shift_ = TypeEncodingValue(shift);
5457         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5458         EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5459                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5460                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5461         return;
5462       }
5463       // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
5464       if (operand.IsShiftValid() && operand.IsPostIndex() &&
5465           cond.IsNotNever() &&
5466           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
5467         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5468         uint32_t shift_ = TypeEncodingValue(shift);
5469         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5470         EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5471                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5472                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5473         return;
5474       }
5475       // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5476       if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5477           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
5478         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5479         uint32_t shift_ = TypeEncodingValue(shift);
5480         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5481         EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5482                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5483                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5484         return;
5485       }
5486     }
5487   }
5488   Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5489 }
5490 
ldrb(Condition cond,Register rt,Location * location)5491 void Assembler::ldrb(Condition cond, Register rt, Location* location) {
5492   VIXL_ASSERT(AllowAssembler());
5493   CheckIT(cond);
5494   Location::Offset offset =
5495       location->IsBound()
5496           ? location->GetLocation() -
5497                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5498           : 0;
5499   if (IsUsingT32()) {
5500     // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5501     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5502          !location->IsBound()) &&
5503         !rt.Is(pc)) {
5504       static class EmitOp : public Location::EmitOperator {
5505        public:
5506         EmitOp() : Location::EmitOperator(T32) {}
5507         virtual uint32_t Encode(uint32_t instr,
5508                                 Location::Offset program_counter,
5509                                 const Location* loc) const VIXL_OVERRIDE {
5510           program_counter += kT32PcDelta;
5511           Location::Offset off =
5512               loc->GetLocation() - AlignDown(program_counter, 4);
5513           VIXL_ASSERT((off >= -4095) && (off <= 4095));
5514           uint32_t U = (off >= 0);
5515           int32_t target = abs(off) | (U << 12);
5516           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5517         }
5518       } immop;
5519       EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12),
5520                       location,
5521                       immop,
5522                       &kT32FarDataInfo));
5523       AdvanceIT();
5524       return;
5525     }
5526   } else {
5527     // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5528     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5529          !location->IsBound()) &&
5530         cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
5531       static class EmitOp : public Location::EmitOperator {
5532        public:
5533         EmitOp() : Location::EmitOperator(A32) {}
5534         virtual uint32_t Encode(uint32_t instr,
5535                                 Location::Offset program_counter,
5536                                 const Location* loc) const VIXL_OVERRIDE {
5537           program_counter += kA32PcDelta;
5538           Location::Offset off =
5539               loc->GetLocation() - AlignDown(program_counter, 4);
5540           VIXL_ASSERT((off >= -4095) && (off <= 4095));
5541           uint32_t U = (off >= 0);
5542           int32_t target = abs(off) | (U << 12);
5543           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5544         }
5545       } immop;
5546       EmitA32(
5547           Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5548                location,
5549                immop,
5550                &kA32FarDataInfo));
5551       return;
5552     }
5553   }
5554   Delegate(kLdrb, &Assembler::ldrb, cond, rt, location);
5555 }
5556 
ldrb_info(Condition cond,Register rt,Location * location,const struct ReferenceInfo ** info)5557 bool Assembler::ldrb_info(Condition cond,
5558                           Register rt,
5559                           Location* location,
5560                           const struct ReferenceInfo** info) {
5561   VIXL_ASSERT(!location->IsBound());
5562   USE(location);
5563   if (IsUsingT32()) {
5564     // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5565     if (!rt.Is(pc)) {
5566       *info = &kT32FarDataInfo;
5567       return true;
5568     }
5569   } else {
5570     // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5571     if (cond.IsNotNever()) {
5572       *info = &kA32FarDataInfo;
5573       return true;
5574     }
5575   }
5576   return false;
5577 }
5578 
ldrd(Condition cond,Register rt,Register rt2,const MemOperand & operand)5579 void Assembler::ldrd(Condition cond,
5580                      Register rt,
5581                      Register rt2,
5582                      const MemOperand& operand) {
5583   VIXL_ASSERT(AllowAssembler());
5584   CheckIT(cond);
5585   if (operand.IsImmediate()) {
5586     Register rn = operand.GetBaseRegister();
5587     int32_t offset = operand.GetOffsetImmediate();
5588     if (IsUsingT32()) {
5589       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5590       if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5591           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5592           ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5593         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5594         uint32_t offset_ = abs(offset) >> 2;
5595         EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5596                    (rn.GetCode() << 16) | offset_ | (sign << 23));
5597         AdvanceIT();
5598         return;
5599       }
5600       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5601       if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5602           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5603           ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5604         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5605         uint32_t offset_ = abs(offset) >> 2;
5606         EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5607                    (rn.GetCode() << 16) | offset_ | (sign << 23));
5608         AdvanceIT();
5609         return;
5610       }
5611       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5612       if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5613           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5614           ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5615         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5616         uint32_t offset_ = abs(offset) >> 2;
5617         EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5618                    (rn.GetCode() << 16) | offset_ | (sign << 23));
5619         AdvanceIT();
5620         return;
5621       }
5622       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5623       if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5624           operand.IsOffset() &&
5625           ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5626         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5627         uint32_t offset_ = abs(offset);
5628         EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5629                    offset_ | (sign << 23));
5630         AdvanceIT();
5631         return;
5632       }
5633     } else {
5634       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5635       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5636           (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5637           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5638           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5639            AllowUnpredictable())) {
5640         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5641         uint32_t offset_ = abs(offset);
5642         EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5643                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5644                 ((offset_ & 0xf0) << 4) | (sign << 23));
5645         return;
5646       }
5647       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5648       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5649           (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5650           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5651           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5652            AllowUnpredictable())) {
5653         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5654         uint32_t offset_ = abs(offset);
5655         EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5656                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5657                 ((offset_ & 0xf0) << 4) | (sign << 23));
5658         return;
5659       }
5660       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5661       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5662           (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5663           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5664           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5665            AllowUnpredictable())) {
5666         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5667         uint32_t offset_ = abs(offset);
5668         EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5669                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5670                 ((offset_ & 0xf0) << 4) | (sign << 23));
5671         return;
5672       }
5673       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5674       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5675           (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5676           operand.IsOffset() && cond.IsNotNever() &&
5677           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5678            AllowUnpredictable())) {
5679         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5680         uint32_t offset_ = abs(offset);
5681         EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5682                 (rt.GetCode() << 12) | (offset_ & 0xf) |
5683                 ((offset_ & 0xf0) << 4) | (sign << 23));
5684         return;
5685       }
5686     }
5687   }
5688   if (operand.IsPlainRegister()) {
5689     Register rn = operand.GetBaseRegister();
5690     Sign sign = operand.GetSign();
5691     Register rm = operand.GetOffsetRegister();
5692     if (IsUsingA32()) {
5693       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5694       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5695           operand.IsOffset() && cond.IsNotNever() &&
5696           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
5697            AllowUnpredictable())) {
5698         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5699         EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5700                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5701                 (sign_ << 23));
5702         return;
5703       }
5704       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5705       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5706           operand.IsPostIndex() && cond.IsNotNever() &&
5707           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
5708            AllowUnpredictable())) {
5709         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5710         EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5711                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5712                 (sign_ << 23));
5713         return;
5714       }
5715       // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5716       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5717           operand.IsPreIndex() && cond.IsNotNever() &&
5718           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
5719            AllowUnpredictable())) {
5720         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5721         EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5722                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5723                 (sign_ << 23));
5724         return;
5725       }
5726     }
5727   }
5728   Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5729 }
5730 
ldrd(Condition cond,Register rt,Register rt2,Location * location)5731 void Assembler::ldrd(Condition cond,
5732                      Register rt,
5733                      Register rt2,
5734                      Location* location) {
5735   VIXL_ASSERT(AllowAssembler());
5736   CheckIT(cond);
5737   Location::Offset offset =
5738       location->IsBound()
5739           ? location->GetLocation() -
5740                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5741           : 0;
5742   if (IsUsingT32()) {
5743     // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5744     if (((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
5745           ((offset & 0x3) == 0)) ||
5746          !location->IsBound()) &&
5747         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5748       static class EmitOp : public Location::EmitOperator {
5749        public:
5750         EmitOp() : Location::EmitOperator(T32) {}
5751         virtual uint32_t Encode(uint32_t instr,
5752                                 Location::Offset program_counter,
5753                                 const Location* loc) const VIXL_OVERRIDE {
5754           program_counter += kT32PcDelta;
5755           Location::Offset off =
5756               loc->GetLocation() - AlignDown(program_counter, 4);
5757           VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
5758           int32_t target = off >> 2;
5759           uint32_t U = (target >= 0);
5760           target = abs(target) | (U << 8);
5761           return instr | (target & 0xff) | ((target & 0x100) << 15);
5762         }
5763       } immop;
5764       EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
5765                       location,
5766                       immop,
5767                       &kT32DataInfo));
5768       AdvanceIT();
5769       return;
5770     }
5771   } else {
5772     // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5773     if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5774         ((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
5775          !location->IsBound()) &&
5776         cond.IsNotNever() &&
5777         ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) || AllowUnpredictable())) {
5778       static class EmitOp : public Location::EmitOperator {
5779        public:
5780         EmitOp() : Location::EmitOperator(A32) {}
5781         virtual uint32_t Encode(uint32_t instr,
5782                                 Location::Offset program_counter,
5783                                 const Location* loc) const VIXL_OVERRIDE {
5784           program_counter += kA32PcDelta;
5785           Location::Offset off =
5786               loc->GetLocation() - AlignDown(program_counter, 4);
5787           VIXL_ASSERT((off >= -255) && (off <= 255));
5788           uint32_t U = (off >= 0);
5789           int32_t target = abs(off) | (U << 8);
5790           return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5791                  ((target & 0x100) << 15);
5792         }
5793       } immop;
5794       EmitA32(
5795           Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5796                location,
5797                immop,
5798                &kA32VeryNearDataInfo));
5799       return;
5800     }
5801   }
5802   Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, location);
5803 }
5804 
ldrd_info(Condition cond,Register rt,Register rt2,Location * location,const struct ReferenceInfo ** info)5805 bool Assembler::ldrd_info(Condition cond,
5806                           Register rt,
5807                           Register rt2,
5808                           Location* location,
5809                           const struct ReferenceInfo** info) {
5810   VIXL_ASSERT(!location->IsBound());
5811   USE(location);
5812   if (IsUsingT32()) {
5813     // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5814     if (true) {
5815       *info = &kT32DataInfo;
5816       return true;
5817     }
5818   } else {
5819     // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5820     if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5821         cond.IsNotNever()) {
5822       *info = &kA32VeryNearDataInfo;
5823       return true;
5824     }
5825   }
5826   return false;
5827 }
5828 
ldrex(Condition cond,Register rt,const MemOperand & operand)5829 void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
5830   VIXL_ASSERT(AllowAssembler());
5831   CheckIT(cond);
5832   if (operand.IsImmediate()) {
5833     Register rn = operand.GetBaseRegister();
5834     int32_t offset = operand.GetOffsetImmediate();
5835     if (IsUsingT32()) {
5836       // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5837       if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
5838           operand.IsOffset() &&
5839           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5840         int32_t offset_ = offset >> 2;
5841         EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5842                    (offset_ & 0xff));
5843         AdvanceIT();
5844         return;
5845       }
5846     } else {
5847       // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
5848       if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
5849           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5850         EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5851                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5852         return;
5853       }
5854     }
5855   }
5856   Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5857 }
5858 
ldrexb(Condition cond,Register rt,const MemOperand & operand)5859 void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
5860   VIXL_ASSERT(AllowAssembler());
5861   CheckIT(cond);
5862   if (operand.IsImmediateZero()) {
5863     Register rn = operand.GetBaseRegister();
5864     if (IsUsingT32()) {
5865       // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
5866       if (operand.IsOffset() &&
5867           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5868         EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5869         AdvanceIT();
5870         return;
5871       }
5872     } else {
5873       // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
5874       if (operand.IsOffset() && cond.IsNotNever() &&
5875           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5876         EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5877                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5878         return;
5879       }
5880     }
5881   }
5882   Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5883 }
5884 
ldrexd(Condition cond,Register rt,Register rt2,const MemOperand & operand)5885 void Assembler::ldrexd(Condition cond,
5886                        Register rt,
5887                        Register rt2,
5888                        const MemOperand& operand) {
5889   VIXL_ASSERT(AllowAssembler());
5890   CheckIT(cond);
5891   if (operand.IsImmediateZero()) {
5892     Register rn = operand.GetBaseRegister();
5893     if (IsUsingT32()) {
5894       // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
5895       if (operand.IsOffset() &&
5896           ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5897         EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5898                    (rn.GetCode() << 16));
5899         AdvanceIT();
5900         return;
5901       }
5902     } else {
5903       // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5904       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5905           operand.IsOffset() && cond.IsNotNever() &&
5906           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
5907            AllowUnpredictable())) {
5908         EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5909                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5910         return;
5911       }
5912     }
5913   }
5914   Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5915 }
5916 
ldrexh(Condition cond,Register rt,const MemOperand & operand)5917 void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
5918   VIXL_ASSERT(AllowAssembler());
5919   CheckIT(cond);
5920   if (operand.IsImmediateZero()) {
5921     Register rn = operand.GetBaseRegister();
5922     if (IsUsingT32()) {
5923       // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
5924       if (operand.IsOffset() &&
5925           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5926         EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5927         AdvanceIT();
5928         return;
5929       }
5930     } else {
5931       // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
5932       if (operand.IsOffset() && cond.IsNotNever() &&
5933           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5934         EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5935                 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5936         return;
5937       }
5938     }
5939   }
5940   Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5941 }
5942 
ldrh(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)5943 void Assembler::ldrh(Condition cond,
5944                      EncodingSize size,
5945                      Register rt,
5946                      const MemOperand& operand) {
5947   VIXL_ASSERT(AllowAssembler());
5948   CheckIT(cond);
5949   if (operand.IsImmediate()) {
5950     Register rn = operand.GetBaseRegister();
5951     int32_t offset = operand.GetOffsetImmediate();
5952     if (IsUsingT32()) {
5953       // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5954       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5955           (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
5956         int32_t offset_ = offset >> 1;
5957         EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5958                    ((offset_ & 0x1f) << 6));
5959         AdvanceIT();
5960         return;
5961       }
5962       // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5963       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5964           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5965         EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5966                    (offset & 0xfff));
5967         AdvanceIT();
5968         return;
5969       }
5970       // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5971       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5972           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5973         EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5974                    (-offset & 0xff));
5975         AdvanceIT();
5976         return;
5977       }
5978       // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5979       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5980           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5981         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5982         uint32_t offset_ = abs(offset);
5983         EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5984                    offset_ | (sign << 9));
5985         AdvanceIT();
5986         return;
5987       }
5988       // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5989       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5990           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5991         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5992         uint32_t offset_ = abs(offset);
5993         EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5994                    offset_ | (sign << 9));
5995         AdvanceIT();
5996         return;
5997       }
5998       // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5999       if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
6000           rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
6001         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6002         uint32_t offset_ = abs(offset);
6003         EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6004         AdvanceIT();
6005         return;
6006       }
6007     } else {
6008       // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
6009       if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
6010           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6011           (!rt.IsPC() || AllowUnpredictable())) {
6012         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6013         uint32_t offset_ = abs(offset);
6014         EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
6015                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6016                 ((offset_ & 0xf0) << 4) | (sign << 23));
6017         return;
6018       }
6019       // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
6020       if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
6021           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6022           (!rt.IsPC() || AllowUnpredictable())) {
6023         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6024         uint32_t offset_ = abs(offset);
6025         EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
6026                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6027                 ((offset_ & 0xf0) << 4) | (sign << 23));
6028         return;
6029       }
6030       // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
6031       if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
6032           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6033           (!rt.IsPC() || AllowUnpredictable())) {
6034         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6035         uint32_t offset_ = abs(offset);
6036         EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
6037                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6038                 ((offset_ & 0xf0) << 4) | (sign << 23));
6039         return;
6040       }
6041       // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6042       if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
6043           operand.IsOffset() && cond.IsNotNever() &&
6044           (!rt.IsPC() || AllowUnpredictable())) {
6045         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6046         uint32_t offset_ = abs(offset);
6047         EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
6048                 (rt.GetCode() << 12) | (offset_ & 0xf) |
6049                 ((offset_ & 0xf0) << 4) | (sign << 23));
6050         return;
6051       }
6052     }
6053   }
6054   if (operand.IsPlainRegister()) {
6055     Register rn = operand.GetBaseRegister();
6056     Sign sign = operand.GetSign();
6057     Register rm = operand.GetOffsetRegister();
6058     if (IsUsingT32()) {
6059       // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6060       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
6061           sign.IsPlus() && operand.IsOffset()) {
6062         EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
6063                    (rm.GetCode() << 6));
6064         AdvanceIT();
6065         return;
6066       }
6067     } else {
6068       // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6069       if (operand.IsOffset() && cond.IsNotNever() &&
6070           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6071         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6072         EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
6073                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6074                 (sign_ << 23));
6075         return;
6076       }
6077       // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6078       if (operand.IsPostIndex() && cond.IsNotNever() &&
6079           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6080         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6081         EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
6082                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6083                 (sign_ << 23));
6084         return;
6085       }
6086       // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6087       if (operand.IsPreIndex() && cond.IsNotNever() &&
6088           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6089         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6090         EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
6091                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6092                 (sign_ << 23));
6093         return;
6094       }
6095     }
6096   }
6097   if (operand.IsShiftedRegister()) {
6098     Register rn = operand.GetBaseRegister();
6099     Sign sign = operand.GetSign();
6100     Register rm = operand.GetOffsetRegister();
6101     Shift shift = operand.GetShift();
6102     uint32_t amount = operand.GetShiftAmount();
6103     if (IsUsingT32()) {
6104       // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6105       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6106           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6107           (!rm.IsPC() || AllowUnpredictable())) {
6108         EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6109                    rm.GetCode() | (amount << 4));
6110         AdvanceIT();
6111         return;
6112       }
6113     }
6114   }
6115   Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
6116 }
6117 
ldrh(Condition cond,Register rt,Location * location)6118 void Assembler::ldrh(Condition cond, Register rt, Location* location) {
6119   VIXL_ASSERT(AllowAssembler());
6120   CheckIT(cond);
6121   Location::Offset offset =
6122       location->IsBound()
6123           ? location->GetLocation() -
6124                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6125           : 0;
6126   if (IsUsingT32()) {
6127     // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6128     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6129          !location->IsBound()) &&
6130         !rt.Is(pc)) {
6131       static class EmitOp : public Location::EmitOperator {
6132        public:
6133         EmitOp() : Location::EmitOperator(T32) {}
6134         virtual uint32_t Encode(uint32_t instr,
6135                                 Location::Offset program_counter,
6136                                 const Location* loc) const VIXL_OVERRIDE {
6137           program_counter += kT32PcDelta;
6138           Location::Offset off =
6139               loc->GetLocation() - AlignDown(program_counter, 4);
6140           VIXL_ASSERT((off >= -4095) && (off <= 4095));
6141           uint32_t U = (off >= 0);
6142           int32_t target = abs(off) | (U << 12);
6143           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6144         }
6145       } immop;
6146       EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12),
6147                       location,
6148                       immop,
6149                       &kT32FarDataInfo));
6150       AdvanceIT();
6151       return;
6152     }
6153   } else {
6154     // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6155     if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6156          !location->IsBound()) &&
6157         cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
6158       static class EmitOp : public Location::EmitOperator {
6159        public:
6160         EmitOp() : Location::EmitOperator(A32) {}
6161         virtual uint32_t Encode(uint32_t instr,
6162                                 Location::Offset program_counter,
6163                                 const Location* loc) const VIXL_OVERRIDE {
6164           program_counter += kA32PcDelta;
6165           Location::Offset off =
6166               loc->GetLocation() - AlignDown(program_counter, 4);
6167           VIXL_ASSERT((off >= -255) && (off <= 255));
6168           uint32_t U = (off >= 0);
6169           int32_t target = abs(off) | (U << 8);
6170           return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6171                  ((target & 0x100) << 15);
6172         }
6173       } immop;
6174       EmitA32(
6175           Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6176                location,
6177                immop,
6178                &kA32VeryNearDataInfo));
6179       return;
6180     }
6181   }
6182   Delegate(kLdrh, &Assembler::ldrh, cond, rt, location);
6183 }
6184 
ldrh_info(Condition cond,Register rt,Location * location,const struct ReferenceInfo ** info)6185 bool Assembler::ldrh_info(Condition cond,
6186                           Register rt,
6187                           Location* location,
6188                           const struct ReferenceInfo** info) {
6189   VIXL_ASSERT(!location->IsBound());
6190   USE(location);
6191   if (IsUsingT32()) {
6192     // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6193     if (!rt.Is(pc)) {
6194       *info = &kT32FarDataInfo;
6195       return true;
6196     }
6197   } else {
6198     // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6199     if (cond.IsNotNever()) {
6200       *info = &kA32VeryNearDataInfo;
6201       return true;
6202     }
6203   }
6204   return false;
6205 }
6206 
ldrsb(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)6207 void Assembler::ldrsb(Condition cond,
6208                       EncodingSize size,
6209                       Register rt,
6210                       const MemOperand& operand) {
6211   VIXL_ASSERT(AllowAssembler());
6212   CheckIT(cond);
6213   if (operand.IsImmediate()) {
6214     Register rn = operand.GetBaseRegister();
6215     int32_t offset = operand.GetOffsetImmediate();
6216     if (IsUsingT32()) {
6217       // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6218       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
6219           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6220         EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6221                    (offset & 0xfff));
6222         AdvanceIT();
6223         return;
6224       }
6225       // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6226       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
6227           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6228         EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6229                    (-offset & 0xff));
6230         AdvanceIT();
6231         return;
6232       }
6233       // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6234       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6235           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6236         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6237         uint32_t offset_ = abs(offset);
6238         EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6239                    offset_ | (sign << 9));
6240         AdvanceIT();
6241         return;
6242       }
6243       // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6244       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6245           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6246         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6247         uint32_t offset_ = abs(offset);
6248         EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6249                    offset_ | (sign << 9));
6250         AdvanceIT();
6251         return;
6252       }
6253       // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6254       if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
6255           rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
6256         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6257         uint32_t offset_ = abs(offset);
6258         EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6259         AdvanceIT();
6260         return;
6261       }
6262     } else {
6263       // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
6264       if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
6265           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6266           (!rt.IsPC() || AllowUnpredictable())) {
6267         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6268         uint32_t offset_ = abs(offset);
6269         EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
6270                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6271                 ((offset_ & 0xf0) << 4) | (sign << 23));
6272         return;
6273       }
6274       // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
6275       if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
6276           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6277           (!rt.IsPC() || AllowUnpredictable())) {
6278         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6279         uint32_t offset_ = abs(offset);
6280         EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
6281                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6282                 ((offset_ & 0xf0) << 4) | (sign << 23));
6283         return;
6284       }
6285       // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
6286       if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
6287           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6288           (!rt.IsPC() || AllowUnpredictable())) {
6289         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6290         uint32_t offset_ = abs(offset);
6291         EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
6292                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6293                 ((offset_ & 0xf0) << 4) | (sign << 23));
6294         return;
6295       }
6296       // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6297       if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
6298           operand.IsOffset() && cond.IsNotNever() &&
6299           (!rt.IsPC() || AllowUnpredictable())) {
6300         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6301         uint32_t offset_ = abs(offset);
6302         EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
6303                 (rt.GetCode() << 12) | (offset_ & 0xf) |
6304                 ((offset_ & 0xf0) << 4) | (sign << 23));
6305         return;
6306       }
6307     }
6308   }
6309   if (operand.IsPlainRegister()) {
6310     Register rn = operand.GetBaseRegister();
6311     Sign sign = operand.GetSign();
6312     Register rm = operand.GetOffsetRegister();
6313     if (IsUsingT32()) {
6314       // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6315       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
6316           sign.IsPlus() && operand.IsOffset()) {
6317         EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
6318                    (rm.GetCode() << 6));
6319         AdvanceIT();
6320         return;
6321       }
6322     } else {
6323       // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6324       if (operand.IsOffset() && cond.IsNotNever() &&
6325           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6326         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6327         EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
6328                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6329                 (sign_ << 23));
6330         return;
6331       }
6332       // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6333       if (operand.IsPostIndex() && cond.IsNotNever() &&
6334           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6335         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6336         EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
6337                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6338                 (sign_ << 23));
6339         return;
6340       }
6341       // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6342       if (operand.IsPreIndex() && cond.IsNotNever() &&
6343           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6344         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6345         EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
6346                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6347                 (sign_ << 23));
6348         return;
6349       }
6350     }
6351   }
6352   if (operand.IsShiftedRegister()) {
6353     Register rn = operand.GetBaseRegister();
6354     Sign sign = operand.GetSign();
6355     Register rm = operand.GetOffsetRegister();
6356     Shift shift = operand.GetShift();
6357     uint32_t amount = operand.GetShiftAmount();
6358     if (IsUsingT32()) {
6359       // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6360       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6361           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6362           (!rm.IsPC() || AllowUnpredictable())) {
6363         EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6364                    rm.GetCode() | (amount << 4));
6365         AdvanceIT();
6366         return;
6367       }
6368     }
6369   }
6370   Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
6371 }
6372 
ldrsb(Condition cond,Register rt,Location * location)6373 void Assembler::ldrsb(Condition cond, Register rt, Location* location) {
6374   VIXL_ASSERT(AllowAssembler());
6375   CheckIT(cond);
6376   Location::Offset offset =
6377       location->IsBound()
6378           ? location->GetLocation() -
6379                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6380           : 0;
6381   if (IsUsingT32()) {
6382     // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6383     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6384          !location->IsBound()) &&
6385         !rt.Is(pc)) {
6386       static class EmitOp : public Location::EmitOperator {
6387        public:
6388         EmitOp() : Location::EmitOperator(T32) {}
6389         virtual uint32_t Encode(uint32_t instr,
6390                                 Location::Offset program_counter,
6391                                 const Location* loc) const VIXL_OVERRIDE {
6392           program_counter += kT32PcDelta;
6393           Location::Offset off =
6394               loc->GetLocation() - AlignDown(program_counter, 4);
6395           VIXL_ASSERT((off >= -4095) && (off <= 4095));
6396           uint32_t U = (off >= 0);
6397           int32_t target = abs(off) | (U << 12);
6398           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6399         }
6400       } immop;
6401       EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12),
6402                       location,
6403                       immop,
6404                       &kT32FarDataInfo));
6405       AdvanceIT();
6406       return;
6407     }
6408   } else {
6409     // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6410     if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6411          !location->IsBound()) &&
6412         cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
6413       static class EmitOp : public Location::EmitOperator {
6414        public:
6415         EmitOp() : Location::EmitOperator(A32) {}
6416         virtual uint32_t Encode(uint32_t instr,
6417                                 Location::Offset program_counter,
6418                                 const Location* loc) const VIXL_OVERRIDE {
6419           program_counter += kA32PcDelta;
6420           Location::Offset off =
6421               loc->GetLocation() - AlignDown(program_counter, 4);
6422           VIXL_ASSERT((off >= -255) && (off <= 255));
6423           uint32_t U = (off >= 0);
6424           int32_t target = abs(off) | (U << 8);
6425           return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6426                  ((target & 0x100) << 15);
6427         }
6428       } immop;
6429       EmitA32(
6430           Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6431                location,
6432                immop,
6433                &kA32VeryNearDataInfo));
6434       return;
6435     }
6436   }
6437   Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, location);
6438 }
6439 
ldrsb_info(Condition cond,Register rt,Location * location,const struct ReferenceInfo ** info)6440 bool Assembler::ldrsb_info(Condition cond,
6441                            Register rt,
6442                            Location* location,
6443                            const struct ReferenceInfo** info) {
6444   VIXL_ASSERT(!location->IsBound());
6445   USE(location);
6446   if (IsUsingT32()) {
6447     // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6448     if (!rt.Is(pc)) {
6449       *info = &kT32FarDataInfo;
6450       return true;
6451     }
6452   } else {
6453     // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6454     if (cond.IsNotNever()) {
6455       *info = &kA32VeryNearDataInfo;
6456       return true;
6457     }
6458   }
6459   return false;
6460 }
6461 
ldrsh(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)6462 void Assembler::ldrsh(Condition cond,
6463                       EncodingSize size,
6464                       Register rt,
6465                       const MemOperand& operand) {
6466   VIXL_ASSERT(AllowAssembler());
6467   CheckIT(cond);
6468   if (operand.IsImmediate()) {
6469     Register rn = operand.GetBaseRegister();
6470     int32_t offset = operand.GetOffsetImmediate();
6471     if (IsUsingT32()) {
6472       // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6473       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
6474           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6475         EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6476                    (offset & 0xfff));
6477         AdvanceIT();
6478         return;
6479       }
6480       // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6481       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
6482           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6483         EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6484                    (-offset & 0xff));
6485         AdvanceIT();
6486         return;
6487       }
6488       // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6489       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6490           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6491         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6492         uint32_t offset_ = abs(offset);
6493         EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6494                    offset_ | (sign << 9));
6495         AdvanceIT();
6496         return;
6497       }
6498       // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6499       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6500           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6501         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6502         uint32_t offset_ = abs(offset);
6503         EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6504                    offset_ | (sign << 9));
6505         AdvanceIT();
6506         return;
6507       }
6508       // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6509       if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
6510           rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
6511         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6512         uint32_t offset_ = abs(offset);
6513         EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6514         AdvanceIT();
6515         return;
6516       }
6517     } else {
6518       // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
6519       if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
6520           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6521           (!rt.IsPC() || AllowUnpredictable())) {
6522         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6523         uint32_t offset_ = abs(offset);
6524         EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
6525                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6526                 ((offset_ & 0xf0) << 4) | (sign << 23));
6527         return;
6528       }
6529       // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
6530       if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
6531           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6532           (!rt.IsPC() || AllowUnpredictable())) {
6533         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6534         uint32_t offset_ = abs(offset);
6535         EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
6536                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6537                 ((offset_ & 0xf0) << 4) | (sign << 23));
6538         return;
6539       }
6540       // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
6541       if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
6542           cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6543           (!rt.IsPC() || AllowUnpredictable())) {
6544         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6545         uint32_t offset_ = abs(offset);
6546         EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
6547                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6548                 ((offset_ & 0xf0) << 4) | (sign << 23));
6549         return;
6550       }
6551       // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6552       if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
6553           operand.IsOffset() && cond.IsNotNever() &&
6554           (!rt.IsPC() || AllowUnpredictable())) {
6555         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6556         uint32_t offset_ = abs(offset);
6557         EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
6558                 (rt.GetCode() << 12) | (offset_ & 0xf) |
6559                 ((offset_ & 0xf0) << 4) | (sign << 23));
6560         return;
6561       }
6562     }
6563   }
6564   if (operand.IsPlainRegister()) {
6565     Register rn = operand.GetBaseRegister();
6566     Sign sign = operand.GetSign();
6567     Register rm = operand.GetOffsetRegister();
6568     if (IsUsingT32()) {
6569       // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6570       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
6571           sign.IsPlus() && operand.IsOffset()) {
6572         EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
6573                    (rm.GetCode() << 6));
6574         AdvanceIT();
6575         return;
6576       }
6577     } else {
6578       // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6579       if (operand.IsOffset() && cond.IsNotNever() &&
6580           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6581         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6582         EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6583                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6584                 (sign_ << 23));
6585         return;
6586       }
6587       // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6588       if (operand.IsPostIndex() && cond.IsNotNever() &&
6589           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6590         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6591         EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6592                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6593                 (sign_ << 23));
6594         return;
6595       }
6596       // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6597       if (operand.IsPreIndex() && cond.IsNotNever() &&
6598           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6599         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6600         EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6601                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6602                 (sign_ << 23));
6603         return;
6604       }
6605     }
6606   }
6607   if (operand.IsShiftedRegister()) {
6608     Register rn = operand.GetBaseRegister();
6609     Sign sign = operand.GetSign();
6610     Register rm = operand.GetOffsetRegister();
6611     Shift shift = operand.GetShift();
6612     uint32_t amount = operand.GetShiftAmount();
6613     if (IsUsingT32()) {
6614       // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6615       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6616           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6617           (!rm.IsPC() || AllowUnpredictable())) {
6618         EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6619                    rm.GetCode() | (amount << 4));
6620         AdvanceIT();
6621         return;
6622       }
6623     }
6624   }
6625   Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6626 }
6627 
ldrsh(Condition cond,Register rt,Location * location)6628 void Assembler::ldrsh(Condition cond, Register rt, Location* location) {
6629   VIXL_ASSERT(AllowAssembler());
6630   CheckIT(cond);
6631   Location::Offset offset =
6632       location->IsBound()
6633           ? location->GetLocation() -
6634                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6635           : 0;
6636   if (IsUsingT32()) {
6637     // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6638     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6639          !location->IsBound()) &&
6640         !rt.Is(pc)) {
6641       static class EmitOp : public Location::EmitOperator {
6642        public:
6643         EmitOp() : Location::EmitOperator(T32) {}
6644         virtual uint32_t Encode(uint32_t instr,
6645                                 Location::Offset program_counter,
6646                                 const Location* loc) const VIXL_OVERRIDE {
6647           program_counter += kT32PcDelta;
6648           Location::Offset off =
6649               loc->GetLocation() - AlignDown(program_counter, 4);
6650           VIXL_ASSERT((off >= -4095) && (off <= 4095));
6651           uint32_t U = (off >= 0);
6652           int32_t target = abs(off) | (U << 12);
6653           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6654         }
6655       } immop;
6656       EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12),
6657                       location,
6658                       immop,
6659                       &kT32FarDataInfo));
6660       AdvanceIT();
6661       return;
6662     }
6663   } else {
6664     // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6665     if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6666          !location->IsBound()) &&
6667         cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
6668       static class EmitOp : public Location::EmitOperator {
6669        public:
6670         EmitOp() : Location::EmitOperator(A32) {}
6671         virtual uint32_t Encode(uint32_t instr,
6672                                 Location::Offset program_counter,
6673                                 const Location* loc) const VIXL_OVERRIDE {
6674           program_counter += kA32PcDelta;
6675           Location::Offset off =
6676               loc->GetLocation() - AlignDown(program_counter, 4);
6677           VIXL_ASSERT((off >= -255) && (off <= 255));
6678           uint32_t U = (off >= 0);
6679           int32_t target = abs(off) | (U << 8);
6680           return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6681                  ((target & 0x100) << 15);
6682         }
6683       } immop;
6684       EmitA32(
6685           Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6686                location,
6687                immop,
6688                &kA32VeryNearDataInfo));
6689       return;
6690     }
6691   }
6692   Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, location);
6693 }
6694 
ldrsh_info(Condition cond,Register rt,Location * location,const struct ReferenceInfo ** info)6695 bool Assembler::ldrsh_info(Condition cond,
6696                            Register rt,
6697                            Location* location,
6698                            const struct ReferenceInfo** info) {
6699   VIXL_ASSERT(!location->IsBound());
6700   USE(location);
6701   if (IsUsingT32()) {
6702     // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6703     if (!rt.Is(pc)) {
6704       *info = &kT32FarDataInfo;
6705       return true;
6706     }
6707   } else {
6708     // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6709     if (cond.IsNotNever()) {
6710       *info = &kA32VeryNearDataInfo;
6711       return true;
6712     }
6713   }
6714   return false;
6715 }
6716 
lsl(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)6717 void Assembler::lsl(Condition cond,
6718                     EncodingSize size,
6719                     Register rd,
6720                     Register rm,
6721                     const Operand& operand) {
6722   VIXL_ASSERT(AllowAssembler());
6723   CheckIT(cond);
6724   if (operand.IsImmediate()) {
6725     uint32_t imm = operand.GetImmediate();
6726     if (IsUsingT32()) {
6727       // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6728       if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6729           (imm >= 1) && (imm <= 31)) {
6730         EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6731         AdvanceIT();
6732         return;
6733       }
6734       // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6735       if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6736           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6737         EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6738                    ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6739         AdvanceIT();
6740         return;
6741       }
6742     } else {
6743       // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6744       if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6745         EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6746                 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6747         return;
6748       }
6749     }
6750   }
6751   if (operand.IsPlainRegister()) {
6752     Register rs = operand.GetBaseRegister();
6753     if (IsUsingT32()) {
6754       // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6755       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6756           rs.IsLow()) {
6757         EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6758         AdvanceIT();
6759         return;
6760       }
6761       // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6762       if (!size.IsNarrow() &&
6763           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6764         EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6765                    rs.GetCode());
6766         AdvanceIT();
6767         return;
6768       }
6769     } else {
6770       // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6771       if (cond.IsNotNever() &&
6772           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6773         EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6774                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6775         return;
6776       }
6777     }
6778   }
6779   Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6780 }
6781 
lsls(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)6782 void Assembler::lsls(Condition cond,
6783                      EncodingSize size,
6784                      Register rd,
6785                      Register rm,
6786                      const Operand& operand) {
6787   VIXL_ASSERT(AllowAssembler());
6788   CheckIT(cond);
6789   if (operand.IsImmediate()) {
6790     uint32_t imm = operand.GetImmediate();
6791     if (IsUsingT32()) {
6792       // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6793       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6794           (imm >= 1) && (imm <= 31)) {
6795         EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6796         AdvanceIT();
6797         return;
6798       }
6799       // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6800       if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6801           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6802         EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6803                    ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6804         AdvanceIT();
6805         return;
6806       }
6807     } else {
6808       // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6809       if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6810         EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6811                 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6812         return;
6813       }
6814     }
6815   }
6816   if (operand.IsPlainRegister()) {
6817     Register rs = operand.GetBaseRegister();
6818     if (IsUsingT32()) {
6819       // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6820       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6821           rs.IsLow()) {
6822         EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6823         AdvanceIT();
6824         return;
6825       }
6826       // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6827       if (!size.IsNarrow() &&
6828           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6829         EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6830                    rs.GetCode());
6831         AdvanceIT();
6832         return;
6833       }
6834     } else {
6835       // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6836       if (cond.IsNotNever() &&
6837           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6838         EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6839                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6840         return;
6841       }
6842     }
6843   }
6844   Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6845 }
6846 
lsr(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)6847 void Assembler::lsr(Condition cond,
6848                     EncodingSize size,
6849                     Register rd,
6850                     Register rm,
6851                     const Operand& operand) {
6852   VIXL_ASSERT(AllowAssembler());
6853   CheckIT(cond);
6854   if (operand.IsImmediate()) {
6855     uint32_t imm = operand.GetImmediate();
6856     if (IsUsingT32()) {
6857       // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6858       if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6859           (imm >= 1) && (imm <= 32)) {
6860         uint32_t amount_ = imm % 32;
6861         EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6862                    (amount_ << 6));
6863         AdvanceIT();
6864         return;
6865       }
6866       // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6867       if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6868           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6869         uint32_t amount_ = imm % 32;
6870         EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6871                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6872         AdvanceIT();
6873         return;
6874       }
6875     } else {
6876       // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6877       if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6878         uint32_t amount_ = imm % 32;
6879         EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6880                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6881         return;
6882       }
6883     }
6884   }
6885   if (operand.IsPlainRegister()) {
6886     Register rs = operand.GetBaseRegister();
6887     if (IsUsingT32()) {
6888       // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6889       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6890           rs.IsLow()) {
6891         EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6892         AdvanceIT();
6893         return;
6894       }
6895       // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6896       if (!size.IsNarrow() &&
6897           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6898         EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6899                    rs.GetCode());
6900         AdvanceIT();
6901         return;
6902       }
6903     } else {
6904       // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6905       if (cond.IsNotNever() &&
6906           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6907         EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6908                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6909         return;
6910       }
6911     }
6912   }
6913   Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6914 }
6915 
lsrs(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)6916 void Assembler::lsrs(Condition cond,
6917                      EncodingSize size,
6918                      Register rd,
6919                      Register rm,
6920                      const Operand& operand) {
6921   VIXL_ASSERT(AllowAssembler());
6922   CheckIT(cond);
6923   if (operand.IsImmediate()) {
6924     uint32_t imm = operand.GetImmediate();
6925     if (IsUsingT32()) {
6926       // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6927       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6928           (imm >= 1) && (imm <= 32)) {
6929         uint32_t amount_ = imm % 32;
6930         EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6931                    (amount_ << 6));
6932         AdvanceIT();
6933         return;
6934       }
6935       // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6936       if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6937           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6938         uint32_t amount_ = imm % 32;
6939         EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6940                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6941         AdvanceIT();
6942         return;
6943       }
6944     } else {
6945       // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6946       if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6947         uint32_t amount_ = imm % 32;
6948         EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6949                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6950         return;
6951       }
6952     }
6953   }
6954   if (operand.IsPlainRegister()) {
6955     Register rs = operand.GetBaseRegister();
6956     if (IsUsingT32()) {
6957       // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6958       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6959           rs.IsLow()) {
6960         EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6961         AdvanceIT();
6962         return;
6963       }
6964       // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6965       if (!size.IsNarrow() &&
6966           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6967         EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6968                    rs.GetCode());
6969         AdvanceIT();
6970         return;
6971       }
6972     } else {
6973       // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6974       if (cond.IsNotNever() &&
6975           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6976         EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6977                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6978         return;
6979       }
6980     }
6981   }
6982   Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6983 }
6984 
mla(Condition cond,Register rd,Register rn,Register rm,Register ra)6985 void Assembler::mla(
6986     Condition cond, Register rd, Register rn, Register rm, Register ra) {
6987   VIXL_ASSERT(AllowAssembler());
6988   CheckIT(cond);
6989   if (IsUsingT32()) {
6990     // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6991     if (!ra.Is(pc) &&
6992         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6993       EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6994                  rm.GetCode() | (ra.GetCode() << 12));
6995       AdvanceIT();
6996       return;
6997     }
6998   } else {
6999     // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
7000     if (cond.IsNotNever() &&
7001         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7002          AllowUnpredictable())) {
7003       EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7004               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7005       return;
7006     }
7007   }
7008   Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
7009 }
7010 
mlas(Condition cond,Register rd,Register rn,Register rm,Register ra)7011 void Assembler::mlas(
7012     Condition cond, Register rd, Register rn, Register rm, Register ra) {
7013   VIXL_ASSERT(AllowAssembler());
7014   CheckIT(cond);
7015   if (IsUsingA32()) {
7016     // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
7017     if (cond.IsNotNever() &&
7018         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7019          AllowUnpredictable())) {
7020       EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7021               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7022       return;
7023     }
7024   }
7025   Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
7026 }
7027 
mls(Condition cond,Register rd,Register rn,Register rm,Register ra)7028 void Assembler::mls(
7029     Condition cond, Register rd, Register rn, Register rm, Register ra) {
7030   VIXL_ASSERT(AllowAssembler());
7031   CheckIT(cond);
7032   if (IsUsingT32()) {
7033     // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
7034     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7035          AllowUnpredictable())) {
7036       EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7037                  rm.GetCode() | (ra.GetCode() << 12));
7038       AdvanceIT();
7039       return;
7040     }
7041   } else {
7042     // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
7043     if (cond.IsNotNever() &&
7044         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7045          AllowUnpredictable())) {
7046       EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7047               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7048       return;
7049     }
7050   }
7051   Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
7052 }
7053 
mov(Condition cond,EncodingSize size,Register rd,const Operand & operand)7054 void Assembler::mov(Condition cond,
7055                     EncodingSize size,
7056                     Register rd,
7057                     const Operand& operand) {
7058   VIXL_ASSERT(AllowAssembler());
7059   CheckIT(cond);
7060   if (operand.IsImmediateShiftedRegister()) {
7061     Register rm = operand.GetBaseRegister();
7062     if (operand.IsPlainRegister()) {
7063       if (IsUsingT32()) {
7064         // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
7065         if (!size.IsWide() &&
7066             ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
7067              AllowUnpredictable())) {
7068           EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
7069                      ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
7070           AdvanceIT();
7071           return;
7072         }
7073       }
7074     }
7075     Shift shift = operand.GetShift();
7076     uint32_t amount = operand.GetShiftAmount();
7077     if (IsUsingT32()) {
7078       // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7079       if (InITBlock() && !size.IsWide() && rd.IsLow() &&
7080           shift.IsValidAmount(amount) && rm.IsLow() &&
7081           (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
7082           ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
7083         uint32_t amount_ = amount % 32;
7084         EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7085                    (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7086         AdvanceIT();
7087         return;
7088       }
7089       // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
7090       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7091           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7092         uint32_t amount_ = amount % 32;
7093         EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7094                    (operand.GetTypeEncodingValue() << 4) |
7095                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7096         AdvanceIT();
7097         return;
7098       }
7099     } else {
7100       // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7101       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7102         uint32_t amount_ = amount % 32;
7103         EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
7104                 (rd.GetCode() << 12) | rm.GetCode() |
7105                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7106         return;
7107       }
7108     }
7109   }
7110   if (operand.IsRegisterShiftedRegister()) {
7111     Register rm = operand.GetBaseRegister();
7112     Shift shift = operand.GetShift();
7113     Register rs = operand.GetShiftRegister();
7114     if (IsUsingT32()) {
7115       // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7116       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7117           shift.IsASR() && rs.IsLow()) {
7118         EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
7119         AdvanceIT();
7120         return;
7121       }
7122       // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7123       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7124           shift.IsLSL() && rs.IsLow()) {
7125         EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
7126         AdvanceIT();
7127         return;
7128       }
7129       // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7130       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7131           shift.IsLSR() && rs.IsLow()) {
7132         EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
7133         AdvanceIT();
7134         return;
7135       }
7136       // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7137       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7138           shift.IsROR() && rs.IsLow()) {
7139         EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
7140         AdvanceIT();
7141         return;
7142       }
7143       // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
7144       if (!size.IsNarrow() &&
7145           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7146         EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
7147                    (shift.GetType() << 21) | rs.GetCode());
7148         AdvanceIT();
7149         return;
7150       }
7151     } else {
7152       // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7153       if (cond.IsNotNever() &&
7154           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7155         EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
7156                 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7157                 (rs.GetCode() << 8));
7158         return;
7159       }
7160     }
7161   }
7162   if (operand.IsImmediate()) {
7163     uint32_t imm = operand.GetImmediate();
7164     if (IsUsingT32()) {
7165       ImmediateT32 immediate_t32(imm);
7166       // MOV<c>{<q>} <Rd>, #<imm8> ; T1
7167       if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7168         EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7169         AdvanceIT();
7170         return;
7171       }
7172       // MOV{<c>}{<q>} <Rd>, #<const> ; T2
7173       if (!size.IsNarrow() && immediate_t32.IsValid() &&
7174           (!rd.IsPC() || AllowUnpredictable())) {
7175         EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
7176                    (immediate_t32.GetEncodingValue() & 0xff) |
7177                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7178                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7179         AdvanceIT();
7180         return;
7181       }
7182       // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
7183       if (!size.IsNarrow() && (imm <= 65535) &&
7184           (!rd.IsPC() || AllowUnpredictable())) {
7185         EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7186                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7187                    ((imm & 0xf000) << 4));
7188         AdvanceIT();
7189         return;
7190       }
7191     } else {
7192       ImmediateA32 immediate_a32(imm);
7193       // MOV{<c>}{<q>} <Rd>, #<const> ; A1
7194       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7195         EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
7196                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7197         return;
7198       }
7199       // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
7200       if ((imm <= 65535) && cond.IsNotNever() &&
7201           (!rd.IsPC() || AllowUnpredictable())) {
7202         EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7203                 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7204         return;
7205       }
7206     }
7207   }
7208   Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
7209 }
7210 
movs(Condition cond,EncodingSize size,Register rd,const Operand & operand)7211 void Assembler::movs(Condition cond,
7212                      EncodingSize size,
7213                      Register rd,
7214                      const Operand& operand) {
7215   VIXL_ASSERT(AllowAssembler());
7216   CheckIT(cond);
7217   if (operand.IsImmediateShiftedRegister()) {
7218     Register rm = operand.GetBaseRegister();
7219     Shift shift = operand.GetShift();
7220     uint32_t amount = operand.GetShiftAmount();
7221     if (IsUsingT32()) {
7222       // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7223       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
7224           shift.IsValidAmount(amount) && rm.IsLow() &&
7225           (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
7226         uint32_t amount_ = amount % 32;
7227         EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7228                    (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7229         AdvanceIT();
7230         return;
7231       }
7232       // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
7233       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7234           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7235         uint32_t amount_ = amount % 32;
7236         EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7237                    (operand.GetTypeEncodingValue() << 4) |
7238                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7239         AdvanceIT();
7240         return;
7241       }
7242     } else {
7243       // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7244       if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
7245           (!rd.IsPC() || AllowUnpredictable())) {
7246         uint32_t amount_ = amount % 32;
7247         EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
7248                 (rd.GetCode() << 12) | rm.GetCode() |
7249                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7250         return;
7251       }
7252     }
7253   }
7254   if (operand.IsRegisterShiftedRegister()) {
7255     Register rm = operand.GetBaseRegister();
7256     Shift shift = operand.GetShift();
7257     Register rs = operand.GetShiftRegister();
7258     if (IsUsingT32()) {
7259       // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7260       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7261           shift.IsASR() && rs.IsLow()) {
7262         EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
7263         AdvanceIT();
7264         return;
7265       }
7266       // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7267       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7268           shift.IsLSL() && rs.IsLow()) {
7269         EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
7270         AdvanceIT();
7271         return;
7272       }
7273       // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7274       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7275           shift.IsLSR() && rs.IsLow()) {
7276         EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
7277         AdvanceIT();
7278         return;
7279       }
7280       // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7281       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7282           shift.IsROR() && rs.IsLow()) {
7283         EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
7284         AdvanceIT();
7285         return;
7286       }
7287       // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
7288       if (!size.IsNarrow() &&
7289           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7290         EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
7291                    (shift.GetType() << 21) | rs.GetCode());
7292         AdvanceIT();
7293         return;
7294       }
7295     } else {
7296       // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7297       if (cond.IsNotNever() &&
7298           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7299         EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
7300                 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7301                 (rs.GetCode() << 8));
7302         return;
7303       }
7304     }
7305   }
7306   if (operand.IsImmediate()) {
7307     uint32_t imm = operand.GetImmediate();
7308     if (IsUsingT32()) {
7309       ImmediateT32 immediate_t32(imm);
7310       // MOVS{<q>} <Rd>, #<imm8> ; T1
7311       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7312         EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7313         AdvanceIT();
7314         return;
7315       }
7316       // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
7317       if (!size.IsNarrow() && immediate_t32.IsValid() &&
7318           (!rd.IsPC() || AllowUnpredictable())) {
7319         EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
7320                    (immediate_t32.GetEncodingValue() & 0xff) |
7321                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7322                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7323         AdvanceIT();
7324         return;
7325       }
7326     } else {
7327       ImmediateA32 immediate_a32(imm);
7328       // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
7329       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7330         EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
7331                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7332         return;
7333       }
7334     }
7335   }
7336   Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
7337 }
7338 
movt(Condition cond,Register rd,const Operand & operand)7339 void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
7340   VIXL_ASSERT(AllowAssembler());
7341   CheckIT(cond);
7342   if (operand.IsImmediate()) {
7343     uint32_t imm = operand.GetImmediate();
7344     if (IsUsingT32()) {
7345       // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
7346       if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
7347         EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
7348                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7349                    ((imm & 0xf000) << 4));
7350         AdvanceIT();
7351         return;
7352       }
7353     } else {
7354       // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
7355       if ((imm <= 65535) && cond.IsNotNever() &&
7356           (!rd.IsPC() || AllowUnpredictable())) {
7357         EmitA32(0x03400000U | (cond.GetCondition() << 28) |
7358                 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7359         return;
7360       }
7361     }
7362   }
7363   Delegate(kMovt, &Assembler::movt, cond, rd, operand);
7364 }
7365 
movw(Condition cond,Register rd,const Operand & operand)7366 void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
7367   VIXL_ASSERT(AllowAssembler());
7368   CheckIT(cond);
7369   if (operand.IsImmediate()) {
7370     uint32_t imm = operand.GetImmediate();
7371     if (IsUsingT32()) {
7372       // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
7373       if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
7374         EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7375                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7376                    ((imm & 0xf000) << 4));
7377         AdvanceIT();
7378         return;
7379       }
7380     } else {
7381       // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
7382       if ((imm <= 65535) && cond.IsNotNever() &&
7383           (!rd.IsPC() || AllowUnpredictable())) {
7384         EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7385                 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7386         return;
7387       }
7388     }
7389   }
7390   Delegate(kMovw, &Assembler::movw, cond, rd, operand);
7391 }
7392 
mrs(Condition cond,Register rd,SpecialRegister spec_reg)7393 void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
7394   VIXL_ASSERT(AllowAssembler());
7395   CheckIT(cond);
7396   if (IsUsingT32()) {
7397     // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
7398     if ((!rd.IsPC() || AllowUnpredictable())) {
7399       EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
7400       AdvanceIT();
7401       return;
7402     }
7403   } else {
7404     // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
7405     if (cond.IsNotNever() && (!rd.IsPC() || AllowUnpredictable())) {
7406       EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7407               (spec_reg.GetReg() << 22));
7408       return;
7409     }
7410   }
7411   Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
7412 }
7413 
msr(Condition cond,MaskedSpecialRegister spec_reg,const Operand & operand)7414 void Assembler::msr(Condition cond,
7415                     MaskedSpecialRegister spec_reg,
7416                     const Operand& operand) {
7417   VIXL_ASSERT(AllowAssembler());
7418   CheckIT(cond);
7419   if (operand.IsImmediate()) {
7420     uint32_t imm = operand.GetImmediate();
7421     if (IsUsingA32()) {
7422       ImmediateA32 immediate_a32(imm);
7423       // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
7424       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7425         EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
7426                 ((spec_reg.GetReg() & 0xf) << 16) |
7427                 ((spec_reg.GetReg() & 0x10) << 18) |
7428                 immediate_a32.GetEncodingValue());
7429         return;
7430       }
7431     }
7432   }
7433   if (operand.IsPlainRegister()) {
7434     Register rn = operand.GetBaseRegister();
7435     if (IsUsingT32()) {
7436       // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
7437       if ((!rn.IsPC() || AllowUnpredictable())) {
7438         EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
7439                    ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
7440         AdvanceIT();
7441         return;
7442       }
7443     } else {
7444       // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
7445       if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
7446         EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
7447                 ((spec_reg.GetReg() & 0xf) << 16) |
7448                 ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
7449         return;
7450       }
7451     }
7452   }
7453   Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
7454 }
7455 
mul(Condition cond,EncodingSize size,Register rd,Register rn,Register rm)7456 void Assembler::mul(
7457     Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
7458   VIXL_ASSERT(AllowAssembler());
7459   CheckIT(cond);
7460   if (IsUsingT32()) {
7461     // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7462     if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
7463         rm.IsLow()) {
7464       EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7465       AdvanceIT();
7466       return;
7467     }
7468     // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
7469     if (!size.IsNarrow() &&
7470         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7471       EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7472                  rm.GetCode());
7473       AdvanceIT();
7474       return;
7475     }
7476   } else {
7477     // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
7478     if (cond.IsNotNever() &&
7479         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7480       EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7481               rn.GetCode() | (rm.GetCode() << 8));
7482       return;
7483     }
7484   }
7485   Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
7486 }
7487 
muls(Condition cond,Register rd,Register rn,Register rm)7488 void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
7489   VIXL_ASSERT(AllowAssembler());
7490   CheckIT(cond);
7491   if (IsUsingT32()) {
7492     // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7493     if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
7494       EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7495       AdvanceIT();
7496       return;
7497     }
7498   } else {
7499     // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
7500     if (cond.IsNotNever() &&
7501         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7502       EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7503               rn.GetCode() | (rm.GetCode() << 8));
7504       return;
7505     }
7506   }
7507   Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
7508 }
7509 
mvn(Condition cond,EncodingSize size,Register rd,const Operand & operand)7510 void Assembler::mvn(Condition cond,
7511                     EncodingSize size,
7512                     Register rd,
7513                     const Operand& operand) {
7514   VIXL_ASSERT(AllowAssembler());
7515   CheckIT(cond);
7516   if (operand.IsImmediate()) {
7517     uint32_t imm = operand.GetImmediate();
7518     if (IsUsingT32()) {
7519       ImmediateT32 immediate_t32(imm);
7520       // MVN{<c>}{<q>} <Rd>, #<const> ; T1
7521       if (!size.IsNarrow() && immediate_t32.IsValid() &&
7522           (!rd.IsPC() || AllowUnpredictable())) {
7523         EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
7524                    (immediate_t32.GetEncodingValue() & 0xff) |
7525                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7526                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7527         AdvanceIT();
7528         return;
7529       }
7530     } else {
7531       ImmediateA32 immediate_a32(imm);
7532       // MVN{<c>}{<q>} <Rd>, #<const> ; A1
7533       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7534         EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
7535                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7536         return;
7537       }
7538     }
7539   }
7540   if (operand.IsImmediateShiftedRegister()) {
7541     Register rm = operand.GetBaseRegister();
7542     if (operand.IsPlainRegister()) {
7543       if (IsUsingT32()) {
7544         // MVN<c>{<q>} <Rd>, <Rm> ; T1
7545         if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7546           EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7547           AdvanceIT();
7548           return;
7549         }
7550       }
7551     }
7552     Shift shift = operand.GetShift();
7553     uint32_t amount = operand.GetShiftAmount();
7554     if (IsUsingT32()) {
7555       // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7556       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7557           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7558         uint32_t amount_ = amount % 32;
7559         EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7560                    (operand.GetTypeEncodingValue() << 4) |
7561                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7562         AdvanceIT();
7563         return;
7564       }
7565     } else {
7566       // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7567       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7568         uint32_t amount_ = amount % 32;
7569         EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
7570                 (rd.GetCode() << 12) | rm.GetCode() |
7571                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7572         return;
7573       }
7574     }
7575   }
7576   if (operand.IsRegisterShiftedRegister()) {
7577     Register rm = operand.GetBaseRegister();
7578     Shift shift = operand.GetShift();
7579     Register rs = operand.GetShiftRegister();
7580     if (IsUsingA32()) {
7581       // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7582       if (cond.IsNotNever() &&
7583           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7584         EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
7585                 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7586                 (rs.GetCode() << 8));
7587         return;
7588       }
7589     }
7590   }
7591   Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
7592 }
7593 
mvns(Condition cond,EncodingSize size,Register rd,const Operand & operand)7594 void Assembler::mvns(Condition cond,
7595                      EncodingSize size,
7596                      Register rd,
7597                      const Operand& operand) {
7598   VIXL_ASSERT(AllowAssembler());
7599   CheckIT(cond);
7600   if (operand.IsImmediate()) {
7601     uint32_t imm = operand.GetImmediate();
7602     if (IsUsingT32()) {
7603       ImmediateT32 immediate_t32(imm);
7604       // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
7605       if (!size.IsNarrow() && immediate_t32.IsValid() &&
7606           (!rd.IsPC() || AllowUnpredictable())) {
7607         EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
7608                    (immediate_t32.GetEncodingValue() & 0xff) |
7609                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7610                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7611         AdvanceIT();
7612         return;
7613       }
7614     } else {
7615       ImmediateA32 immediate_a32(imm);
7616       // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
7617       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7618         EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
7619                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7620         return;
7621       }
7622     }
7623   }
7624   if (operand.IsImmediateShiftedRegister()) {
7625     Register rm = operand.GetBaseRegister();
7626     if (operand.IsPlainRegister()) {
7627       if (IsUsingT32()) {
7628         // MVNS{<q>} <Rd>, <Rm> ; T1
7629         if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7630           EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7631           AdvanceIT();
7632           return;
7633         }
7634       }
7635     }
7636     Shift shift = operand.GetShift();
7637     uint32_t amount = operand.GetShiftAmount();
7638     if (IsUsingT32()) {
7639       // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7640       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7641           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7642         uint32_t amount_ = amount % 32;
7643         EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7644                    (operand.GetTypeEncodingValue() << 4) |
7645                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7646         AdvanceIT();
7647         return;
7648       }
7649     } else {
7650       // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7651       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7652         uint32_t amount_ = amount % 32;
7653         EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7654                 (rd.GetCode() << 12) | rm.GetCode() |
7655                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7656         return;
7657       }
7658     }
7659   }
7660   if (operand.IsRegisterShiftedRegister()) {
7661     Register rm = operand.GetBaseRegister();
7662     Shift shift = operand.GetShift();
7663     Register rs = operand.GetShiftRegister();
7664     if (IsUsingA32()) {
7665       // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7666       if (cond.IsNotNever() &&
7667           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7668         EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7669                 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7670                 (rs.GetCode() << 8));
7671         return;
7672       }
7673     }
7674   }
7675   Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7676 }
7677 
nop(Condition cond,EncodingSize size)7678 void Assembler::nop(Condition cond, EncodingSize size) {
7679   VIXL_ASSERT(AllowAssembler());
7680   CheckIT(cond);
7681   if (IsUsingT32()) {
7682     // NOP{<c>}{<q>} ; T1
7683     if (!size.IsWide()) {
7684       EmitT32_16(0xbf00);
7685       AdvanceIT();
7686       return;
7687     }
7688     // NOP{<c>}.W ; T2
7689     if (!size.IsNarrow()) {
7690       EmitT32_32(0xf3af8000U);
7691       AdvanceIT();
7692       return;
7693     }
7694   } else {
7695     // NOP{<c>}{<q>} ; A1
7696     if (cond.IsNotNever()) {
7697       EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7698       return;
7699     }
7700   }
7701   Delegate(kNop, &Assembler::nop, cond, size);
7702 }
7703 
orn(Condition cond,Register rd,Register rn,const Operand & operand)7704 void Assembler::orn(Condition cond,
7705                     Register rd,
7706                     Register rn,
7707                     const Operand& operand) {
7708   VIXL_ASSERT(AllowAssembler());
7709   CheckIT(cond);
7710   if (operand.IsImmediate()) {
7711     uint32_t imm = operand.GetImmediate();
7712     if (IsUsingT32()) {
7713       ImmediateT32 immediate_t32(imm);
7714       // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7715       if (immediate_t32.IsValid() && !rn.Is(pc) &&
7716           (!rd.IsPC() || AllowUnpredictable())) {
7717         EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7718                    (immediate_t32.GetEncodingValue() & 0xff) |
7719                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7720                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7721         AdvanceIT();
7722         return;
7723       }
7724     }
7725   }
7726   if (operand.IsImmediateShiftedRegister()) {
7727     Register rm = operand.GetBaseRegister();
7728     Shift shift = operand.GetShift();
7729     uint32_t amount = operand.GetShiftAmount();
7730     if (IsUsingT32()) {
7731       // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7732       if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7733           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7734         uint32_t amount_ = amount % 32;
7735         EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7736                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7737                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7738         AdvanceIT();
7739         return;
7740       }
7741     }
7742   }
7743   Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7744 }
7745 
orns(Condition cond,Register rd,Register rn,const Operand & operand)7746 void Assembler::orns(Condition cond,
7747                      Register rd,
7748                      Register rn,
7749                      const Operand& operand) {
7750   VIXL_ASSERT(AllowAssembler());
7751   CheckIT(cond);
7752   if (operand.IsImmediate()) {
7753     uint32_t imm = operand.GetImmediate();
7754     if (IsUsingT32()) {
7755       ImmediateT32 immediate_t32(imm);
7756       // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7757       if (immediate_t32.IsValid() && !rn.Is(pc) &&
7758           (!rd.IsPC() || AllowUnpredictable())) {
7759         EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7760                    (immediate_t32.GetEncodingValue() & 0xff) |
7761                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7762                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7763         AdvanceIT();
7764         return;
7765       }
7766     }
7767   }
7768   if (operand.IsImmediateShiftedRegister()) {
7769     Register rm = operand.GetBaseRegister();
7770     Shift shift = operand.GetShift();
7771     uint32_t amount = operand.GetShiftAmount();
7772     if (IsUsingT32()) {
7773       // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7774       if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7775           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7776         uint32_t amount_ = amount % 32;
7777         EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7778                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7779                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7780         AdvanceIT();
7781         return;
7782       }
7783     }
7784   }
7785   Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7786 }
7787 
orr(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)7788 void Assembler::orr(Condition cond,
7789                     EncodingSize size,
7790                     Register rd,
7791                     Register rn,
7792                     const Operand& operand) {
7793   VIXL_ASSERT(AllowAssembler());
7794   CheckIT(cond);
7795   if (operand.IsImmediate()) {
7796     uint32_t imm = operand.GetImmediate();
7797     if (IsUsingT32()) {
7798       ImmediateT32 immediate_t32(imm);
7799       // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7800       if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7801           (!rd.IsPC() || AllowUnpredictable())) {
7802         EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7803                    (immediate_t32.GetEncodingValue() & 0xff) |
7804                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7805                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7806         AdvanceIT();
7807         return;
7808       }
7809     } else {
7810       ImmediateA32 immediate_a32(imm);
7811       // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7812       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7813         EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7814                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7815                 immediate_a32.GetEncodingValue());
7816         return;
7817       }
7818     }
7819   }
7820   if (operand.IsImmediateShiftedRegister()) {
7821     Register rm = operand.GetBaseRegister();
7822     if (operand.IsPlainRegister()) {
7823       if (IsUsingT32()) {
7824         // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7825         if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7826             rm.IsLow()) {
7827           EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7828           AdvanceIT();
7829           return;
7830         }
7831       }
7832     }
7833     Shift shift = operand.GetShift();
7834     uint32_t amount = operand.GetShiftAmount();
7835     if (IsUsingT32()) {
7836       // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7837       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7838           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7839         uint32_t amount_ = amount % 32;
7840         EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7841                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7842                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7843         AdvanceIT();
7844         return;
7845       }
7846     } else {
7847       // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7848       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7849         uint32_t amount_ = amount % 32;
7850         EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7851                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7852                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7853         return;
7854       }
7855     }
7856   }
7857   if (operand.IsRegisterShiftedRegister()) {
7858     Register rm = operand.GetBaseRegister();
7859     Shift shift = operand.GetShift();
7860     Register rs = operand.GetShiftRegister();
7861     if (IsUsingA32()) {
7862       // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7863       if (cond.IsNotNever() &&
7864           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7865            AllowUnpredictable())) {
7866         EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7867                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7868                 (shift.GetType() << 5) | (rs.GetCode() << 8));
7869         return;
7870       }
7871     }
7872   }
7873   Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7874 }
7875 
orrs(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)7876 void Assembler::orrs(Condition cond,
7877                      EncodingSize size,
7878                      Register rd,
7879                      Register rn,
7880                      const Operand& operand) {
7881   VIXL_ASSERT(AllowAssembler());
7882   CheckIT(cond);
7883   if (operand.IsImmediate()) {
7884     uint32_t imm = operand.GetImmediate();
7885     if (IsUsingT32()) {
7886       ImmediateT32 immediate_t32(imm);
7887       // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7888       if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7889           (!rd.IsPC() || AllowUnpredictable())) {
7890         EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7891                    (immediate_t32.GetEncodingValue() & 0xff) |
7892                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7893                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7894         AdvanceIT();
7895         return;
7896       }
7897     } else {
7898       ImmediateA32 immediate_a32(imm);
7899       // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7900       if (immediate_a32.IsValid() && cond.IsNotNever()) {
7901         EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7902                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7903                 immediate_a32.GetEncodingValue());
7904         return;
7905       }
7906     }
7907   }
7908   if (operand.IsImmediateShiftedRegister()) {
7909     Register rm = operand.GetBaseRegister();
7910     if (operand.IsPlainRegister()) {
7911       if (IsUsingT32()) {
7912         // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7913         if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7914             rm.IsLow()) {
7915           EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7916           AdvanceIT();
7917           return;
7918         }
7919       }
7920     }
7921     Shift shift = operand.GetShift();
7922     uint32_t amount = operand.GetShiftAmount();
7923     if (IsUsingT32()) {
7924       // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7925       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7926           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7927         uint32_t amount_ = amount % 32;
7928         EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7929                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7930                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7931         AdvanceIT();
7932         return;
7933       }
7934     } else {
7935       // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7936       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7937         uint32_t amount_ = amount % 32;
7938         EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7939                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7940                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7941         return;
7942       }
7943     }
7944   }
7945   if (operand.IsRegisterShiftedRegister()) {
7946     Register rm = operand.GetBaseRegister();
7947     Shift shift = operand.GetShift();
7948     Register rs = operand.GetShiftRegister();
7949     if (IsUsingA32()) {
7950       // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7951       if (cond.IsNotNever() &&
7952           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7953            AllowUnpredictable())) {
7954         EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7955                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7956                 (shift.GetType() << 5) | (rs.GetCode() << 8));
7957         return;
7958       }
7959     }
7960   }
7961   Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7962 }
7963 
pkhbt(Condition cond,Register rd,Register rn,const Operand & operand)7964 void Assembler::pkhbt(Condition cond,
7965                       Register rd,
7966                       Register rn,
7967                       const Operand& operand) {
7968   VIXL_ASSERT(AllowAssembler());
7969   CheckIT(cond);
7970   if (operand.IsImmediateShiftedRegister()) {
7971     Register rm = operand.GetBaseRegister();
7972     Shift shift = operand.GetShift();
7973     uint32_t amount = operand.GetShiftAmount();
7974     if (IsUsingT32()) {
7975       // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
7976       if (shift.IsLSL() && shift.IsValidAmount(amount) &&
7977           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7978         EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7979                    rm.GetCode() | ((amount & 0x3) << 6) |
7980                    ((amount & 0x1c) << 10));
7981         AdvanceIT();
7982         return;
7983       }
7984     } else {
7985       // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
7986       if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever() &&
7987           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7988         EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7989                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7990                 (amount << 7));
7991         return;
7992       }
7993     }
7994   }
7995   Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7996 }
7997 
pkhtb(Condition cond,Register rd,Register rn,const Operand & operand)7998 void Assembler::pkhtb(Condition cond,
7999                       Register rd,
8000                       Register rn,
8001                       const Operand& operand) {
8002   VIXL_ASSERT(AllowAssembler());
8003   CheckIT(cond);
8004   if (operand.IsImmediateShiftedRegister()) {
8005     Register rm = operand.GetBaseRegister();
8006     Shift shift = operand.GetShift();
8007     uint32_t amount = operand.GetShiftAmount();
8008     if (IsUsingT32()) {
8009       // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
8010       if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
8011           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8012         uint32_t amount_ = amount % 32;
8013         EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8014                    rm.GetCode() | ((amount_ & 0x3) << 6) |
8015                    ((amount_ & 0x1c) << 10));
8016         AdvanceIT();
8017         return;
8018       }
8019     } else {
8020       // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
8021       if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
8022           cond.IsNotNever() &&
8023           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8024         uint32_t amount_ = amount % 32;
8025         EmitA32(0x06800050U | (cond.GetCondition() << 28) |
8026                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8027                 (amount_ << 7));
8028         return;
8029       }
8030     }
8031   }
8032   Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
8033 }
8034 
pld(Condition cond,Location * location)8035 void Assembler::pld(Condition cond, Location* location) {
8036   VIXL_ASSERT(AllowAssembler());
8037   CheckIT(cond);
8038   Location::Offset offset =
8039       location->IsBound()
8040           ? location->GetLocation() -
8041                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8042           : 0;
8043   if (IsUsingT32()) {
8044     // PLD{<c>}{<q>} <label> ; T1
8045     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8046          !location->IsBound())) {
8047       static class EmitOp : public Location::EmitOperator {
8048        public:
8049         EmitOp() : Location::EmitOperator(T32) {}
8050         virtual uint32_t Encode(uint32_t instr,
8051                                 Location::Offset program_counter,
8052                                 const Location* loc) const VIXL_OVERRIDE {
8053           program_counter += kT32PcDelta;
8054           Location::Offset off =
8055               loc->GetLocation() - AlignDown(program_counter, 4);
8056           VIXL_ASSERT((off >= -4095) && (off <= 4095));
8057           uint32_t U = (off >= 0);
8058           int32_t target = abs(off) | (U << 12);
8059           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8060         }
8061       } immop;
8062       EmitT32_32(Link(0xf81ff000U, location, immop, &kT32FarDataInfo));
8063       AdvanceIT();
8064       return;
8065     }
8066   } else {
8067     // PLD{<c>}{<q>} <label> ; A1
8068     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8069          !location->IsBound())) {
8070       if (cond.Is(al)) {
8071         static class EmitOp : public Location::EmitOperator {
8072          public:
8073           EmitOp() : Location::EmitOperator(A32) {}
8074           virtual uint32_t Encode(uint32_t instr,
8075                                   Location::Offset program_counter,
8076                                   const Location* loc) const VIXL_OVERRIDE {
8077             program_counter += kA32PcDelta;
8078             Location::Offset off =
8079                 loc->GetLocation() - AlignDown(program_counter, 4);
8080             VIXL_ASSERT((off >= -4095) && (off <= 4095));
8081             uint32_t U = (off >= 0);
8082             int32_t target = abs(off) | (U << 12);
8083             return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8084           }
8085         } immop;
8086         EmitA32(Link(0xf55ff000U, location, immop, &kA32FarDataInfo));
8087         return;
8088       }
8089     }
8090   }
8091   Delegate(kPld, &Assembler::pld, cond, location);
8092 }
8093 
pld_info(Condition cond,Location * location,const struct ReferenceInfo ** info)8094 bool Assembler::pld_info(Condition cond,
8095                          Location* location,
8096                          const struct ReferenceInfo** info) {
8097   VIXL_ASSERT(!location->IsBound());
8098   USE(location);
8099   USE(cond);
8100   if (IsUsingT32()) {
8101     // PLD{<c>}{<q>} <label> ; T1
8102     if (true) {
8103       *info = &kT32FarDataInfo;
8104       return true;
8105     }
8106   } else {
8107     // PLD{<c>}{<q>} <label> ; A1
8108     if (true) {
8109       *info = &kA32FarDataInfo;
8110       return true;
8111     }
8112   }
8113   return false;
8114 }
8115 
pld(Condition cond,const MemOperand & operand)8116 void Assembler::pld(Condition cond, const MemOperand& operand) {
8117   VIXL_ASSERT(AllowAssembler());
8118   CheckIT(cond);
8119   if (operand.IsImmediate()) {
8120     Register rn = operand.GetBaseRegister();
8121     int32_t offset = operand.GetOffsetImmediate();
8122     if (IsUsingT32()) {
8123       // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
8124       if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8125           operand.IsOffset()) {
8126         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8127         uint32_t offset_ = abs(offset);
8128         EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
8129         AdvanceIT();
8130         return;
8131       }
8132     } else {
8133       // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
8134       if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8135           operand.IsOffset()) {
8136         if (cond.Is(al)) {
8137           uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8138           uint32_t offset_ = abs(offset);
8139           EmitA32(0xf55ff000U | offset_ | (sign << 23));
8140           return;
8141         }
8142       }
8143     }
8144   }
8145   if (operand.IsImmediate()) {
8146     Register rn = operand.GetBaseRegister();
8147     int32_t offset = operand.GetOffsetImmediate();
8148     if (IsUsingT32()) {
8149       // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
8150       if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8151           ((rn.GetCode() & 0xf) != 0xf)) {
8152         EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8153         AdvanceIT();
8154         return;
8155       }
8156       // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
8157       if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8158           ((rn.GetCode() & 0xf) != 0xf)) {
8159         EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8160         AdvanceIT();
8161         return;
8162       }
8163     } else {
8164       // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
8165       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
8166           ((rn.GetCode() & 0xf) != 0xf)) {
8167         if (cond.Is(al)) {
8168           uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8169           uint32_t offset_ = abs(offset);
8170           EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8171           return;
8172         }
8173       }
8174     }
8175   }
8176   if (operand.IsShiftedRegister()) {
8177     Register rn = operand.GetBaseRegister();
8178     Sign sign = operand.GetSign();
8179     Register rm = operand.GetOffsetRegister();
8180     Shift shift = operand.GetShift();
8181     uint32_t amount = operand.GetShiftAmount();
8182     if (IsUsingT32()) {
8183       // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
8184       if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
8185           ((rn.GetCode() & 0xf) != 0xf) &&
8186           (!rm.IsPC() || AllowUnpredictable())) {
8187         EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
8188                    (amount << 4));
8189         AdvanceIT();
8190         return;
8191       }
8192     } else {
8193       // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
8194       if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8195           (!rm.IsPC() || AllowUnpredictable())) {
8196         if (cond.Is(al)) {
8197           uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8198           uint32_t amount_ = amount % 32;
8199           EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
8200                   (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8201           return;
8202         }
8203       }
8204       // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
8205       if (shift.IsRRX() && operand.IsOffset() &&
8206           (!rm.IsPC() || AllowUnpredictable())) {
8207         if (cond.Is(al)) {
8208           uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8209           EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
8210                   (sign_ << 23));
8211           return;
8212         }
8213       }
8214     }
8215   }
8216   Delegate(kPld, &Assembler::pld, cond, operand);
8217 }
8218 
pldw(Condition cond,const MemOperand & operand)8219 void Assembler::pldw(Condition cond, const MemOperand& operand) {
8220   VIXL_ASSERT(AllowAssembler());
8221   CheckIT(cond);
8222   if (operand.IsImmediate()) {
8223     Register rn = operand.GetBaseRegister();
8224     int32_t offset = operand.GetOffsetImmediate();
8225     if (IsUsingT32()) {
8226       // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
8227       if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8228           ((rn.GetCode() & 0xf) != 0xf)) {
8229         EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8230         AdvanceIT();
8231         return;
8232       }
8233       // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
8234       if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8235           ((rn.GetCode() & 0xf) != 0xf)) {
8236         EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8237         AdvanceIT();
8238         return;
8239       }
8240     } else {
8241       // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
8242       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
8243           ((rn.GetCode() & 0xf) != 0xf)) {
8244         if (cond.Is(al)) {
8245           uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8246           uint32_t offset_ = abs(offset);
8247           EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8248           return;
8249         }
8250       }
8251     }
8252   }
8253   if (operand.IsShiftedRegister()) {
8254     Register rn = operand.GetBaseRegister();
8255     Sign sign = operand.GetSign();
8256     Register rm = operand.GetOffsetRegister();
8257     Shift shift = operand.GetShift();
8258     uint32_t amount = operand.GetShiftAmount();
8259     if (IsUsingT32()) {
8260       // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
8261       if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
8262           ((rn.GetCode() & 0xf) != 0xf) &&
8263           (!rm.IsPC() || AllowUnpredictable())) {
8264         EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
8265                    (amount << 4));
8266         AdvanceIT();
8267         return;
8268       }
8269     } else {
8270       // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
8271       if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8272           (!rm.IsPC() || AllowUnpredictable())) {
8273         if (cond.Is(al)) {
8274           uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8275           uint32_t amount_ = amount % 32;
8276           EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
8277                   (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8278           return;
8279         }
8280       }
8281       // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
8282       if (shift.IsRRX() && operand.IsOffset() &&
8283           (!rm.IsPC() || AllowUnpredictable())) {
8284         if (cond.Is(al)) {
8285           uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8286           EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
8287                   (sign_ << 23));
8288           return;
8289         }
8290       }
8291     }
8292   }
8293   Delegate(kPldw, &Assembler::pldw, cond, operand);
8294 }
8295 
pli(Condition cond,const MemOperand & operand)8296 void Assembler::pli(Condition cond, const MemOperand& operand) {
8297   VIXL_ASSERT(AllowAssembler());
8298   CheckIT(cond);
8299   if (operand.IsImmediate()) {
8300     Register rn = operand.GetBaseRegister();
8301     int32_t offset = operand.GetOffsetImmediate();
8302     if (IsUsingT32()) {
8303       // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
8304       if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8305           ((rn.GetCode() & 0xf) != 0xf)) {
8306         EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8307         AdvanceIT();
8308         return;
8309       }
8310       // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
8311       if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8312           ((rn.GetCode() & 0xf) != 0xf)) {
8313         EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8314         AdvanceIT();
8315         return;
8316       }
8317     } else {
8318       // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
8319       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
8320           ((rn.GetCode() & 0xf) != 0xf)) {
8321         if (cond.Is(al)) {
8322           uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8323           uint32_t offset_ = abs(offset);
8324           EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8325           return;
8326         }
8327       }
8328     }
8329   }
8330   if (operand.IsImmediate()) {
8331     Register rn = operand.GetBaseRegister();
8332     int32_t offset = operand.GetOffsetImmediate();
8333     if (IsUsingT32()) {
8334       // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
8335       if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8336           operand.IsOffset()) {
8337         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8338         uint32_t offset_ = abs(offset);
8339         EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
8340         AdvanceIT();
8341         return;
8342       }
8343     } else {
8344       // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
8345       if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8346           operand.IsOffset()) {
8347         if (cond.Is(al)) {
8348           uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8349           uint32_t offset_ = abs(offset);
8350           EmitA32(0xf45ff000U | offset_ | (sign << 23));
8351           return;
8352         }
8353       }
8354     }
8355   }
8356   if (operand.IsShiftedRegister()) {
8357     Register rn = operand.GetBaseRegister();
8358     Sign sign = operand.GetSign();
8359     Register rm = operand.GetOffsetRegister();
8360     Shift shift = operand.GetShift();
8361     uint32_t amount = operand.GetShiftAmount();
8362     if (IsUsingT32()) {
8363       // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
8364       if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
8365           ((rn.GetCode() & 0xf) != 0xf) &&
8366           (!rm.IsPC() || AllowUnpredictable())) {
8367         EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
8368                    (amount << 4));
8369         AdvanceIT();
8370         return;
8371       }
8372     } else {
8373       // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
8374       if (shift.IsRRX() && operand.IsOffset() &&
8375           (!rm.IsPC() || AllowUnpredictable())) {
8376         if (cond.Is(al)) {
8377           uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8378           EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
8379                   (sign_ << 23));
8380           return;
8381         }
8382       }
8383       // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
8384       if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8385           (!rm.IsPC() || AllowUnpredictable())) {
8386         if (cond.Is(al)) {
8387           uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8388           uint32_t amount_ = amount % 32;
8389           EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
8390                   (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8391           return;
8392         }
8393       }
8394     }
8395   }
8396   Delegate(kPli, &Assembler::pli, cond, operand);
8397 }
8398 
pli(Condition cond,Location * location)8399 void Assembler::pli(Condition cond, Location* location) {
8400   VIXL_ASSERT(AllowAssembler());
8401   CheckIT(cond);
8402   Location::Offset offset =
8403       location->IsBound()
8404           ? location->GetLocation() -
8405                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8406           : 0;
8407   if (IsUsingT32()) {
8408     // PLI{<c>}{<q>} <label> ; T3
8409     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8410          !location->IsBound())) {
8411       static class EmitOp : public Location::EmitOperator {
8412        public:
8413         EmitOp() : Location::EmitOperator(T32) {}
8414         virtual uint32_t Encode(uint32_t instr,
8415                                 Location::Offset program_counter,
8416                                 const Location* loc) const VIXL_OVERRIDE {
8417           program_counter += kT32PcDelta;
8418           Location::Offset off =
8419               loc->GetLocation() - AlignDown(program_counter, 4);
8420           VIXL_ASSERT((off >= -4095) && (off <= 4095));
8421           uint32_t U = (off >= 0);
8422           int32_t target = abs(off) | (U << 12);
8423           return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8424         }
8425       } immop;
8426       EmitT32_32(Link(0xf91ff000U, location, immop, &kT32FarDataInfo));
8427       AdvanceIT();
8428       return;
8429     }
8430   } else {
8431     // PLI{<c>}{<q>} <label> ; A1
8432     if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8433          !location->IsBound())) {
8434       if (cond.Is(al)) {
8435         static class EmitOp : public Location::EmitOperator {
8436          public:
8437           EmitOp() : Location::EmitOperator(A32) {}
8438           virtual uint32_t Encode(uint32_t instr,
8439                                   Location::Offset program_counter,
8440                                   const Location* loc) const VIXL_OVERRIDE {
8441             program_counter += kA32PcDelta;
8442             Location::Offset off =
8443                 loc->GetLocation() - AlignDown(program_counter, 4);
8444             VIXL_ASSERT((off >= -4095) && (off <= 4095));
8445             uint32_t U = (off >= 0);
8446             int32_t target = abs(off) | (U << 12);
8447             return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8448           }
8449         } immop;
8450         EmitA32(Link(0xf45ff000U, location, immop, &kA32FarDataInfo));
8451         return;
8452       }
8453     }
8454   }
8455   Delegate(kPli, &Assembler::pli, cond, location);
8456 }
8457 
pli_info(Condition cond,Location * location,const struct ReferenceInfo ** info)8458 bool Assembler::pli_info(Condition cond,
8459                          Location* location,
8460                          const struct ReferenceInfo** info) {
8461   VIXL_ASSERT(!location->IsBound());
8462   USE(location);
8463   USE(cond);
8464   if (IsUsingT32()) {
8465     // PLI{<c>}{<q>} <label> ; T3
8466     if (true) {
8467       *info = &kT32FarDataInfo;
8468       return true;
8469     }
8470   } else {
8471     // PLI{<c>}{<q>} <label> ; A1
8472     if (true) {
8473       *info = &kA32FarDataInfo;
8474       return true;
8475     }
8476   }
8477   return false;
8478 }
8479 
pop(Condition cond,EncodingSize size,RegisterList registers)8480 void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
8481   VIXL_ASSERT(AllowAssembler());
8482   CheckIT(cond);
8483   if (!registers.IsEmpty() || AllowUnpredictable()) {
8484     if (IsUsingT32()) {
8485       // A branch out of an IT block should be the last instruction in the
8486       // block.
8487       if (!registers.Includes(pc) || OutsideITBlockAndAlOrLast(cond) ||
8488           AllowUnpredictable()) {
8489         // POP{<c>}{<q>} <registers> ; T1
8490         if (!size.IsWide() && registers.IsR0toR7orPC()) {
8491           EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
8492                      GetRegisterListEncoding(registers, 0, 8));
8493           AdvanceIT();
8494           return;
8495         }
8496         // POP{<c>}{<q>} <registers> ; T2
8497         // Alias of: LDM{<c>}{<q>} SP!, <registers> ; T2
8498         if (!size.IsNarrow() &&
8499             ((!registers.Includes(sp) && (registers.GetCount() > 1) &&
8500               !(registers.Includes(pc) && registers.Includes(lr))) ||
8501              AllowUnpredictable())) {
8502           EmitT32_32(0xe8bd0000U | GetRegisterListEncoding(registers, 0, 16));
8503           AdvanceIT();
8504           return;
8505         }
8506       }
8507     } else {
8508       // POP{<c>}{<q>} <registers> ; A1
8509       // Alias of: LDM{<c>}{<q>} SP!, <registers> ; A1
8510       if (cond.IsNotNever() &&
8511           (!registers.Includes(sp) || AllowUnpredictable())) {
8512         EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
8513                 GetRegisterListEncoding(registers, 0, 16));
8514         return;
8515       }
8516     }
8517   }
8518   Delegate(kPop, &Assembler::pop, cond, size, registers);
8519 }
8520 
pop(Condition cond,EncodingSize size,Register rt)8521 void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
8522   VIXL_ASSERT(AllowAssembler());
8523   CheckIT(cond);
8524   if (!rt.IsSP() || AllowUnpredictable()) {
8525     if (IsUsingT32()) {
8526       // POP{<c>}{<q>} <single_register_list> ; T4
8527       // Alias of: LDR{<c>}{<q>} <Rt>, [SP], #4 ; T4
8528       if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond) ||
8529                                AllowUnpredictable())) {
8530         EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
8531         AdvanceIT();
8532         return;
8533       }
8534     } else {
8535       // POP{<c>}{<q>} <single_register_list> ; A1
8536       // Alias of: LDR{<c>}{<q>} <Rt>, [SP], #4 ; T1
8537       if (cond.IsNotNever()) {
8538         EmitA32(0x049d0004U | (cond.GetCondition() << 28) |
8539                 (rt.GetCode() << 12));
8540         return;
8541       }
8542     }
8543   }
8544   Delegate(kPop, &Assembler::pop, cond, size, rt);
8545 }
8546 
push(Condition cond,EncodingSize size,RegisterList registers)8547 void Assembler::push(Condition cond,
8548                      EncodingSize size,
8549                      RegisterList registers) {
8550   VIXL_ASSERT(AllowAssembler());
8551   CheckIT(cond);
8552   if (!registers.IsEmpty() || AllowUnpredictable()) {
8553     if (IsUsingT32()) {
8554       // PUSH{<c>}{<q>} <registers> ; T1
8555       if (!size.IsWide() && registers.IsR0toR7orLR()) {
8556         EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
8557                    GetRegisterListEncoding(registers, 0, 8));
8558         AdvanceIT();
8559         return;
8560       }
8561       // PUSH{<c>}{<q>} <registers> ; T1
8562       // Alias of: STMDB SP!, <registers> ; T1
8563       if (!size.IsNarrow() && !registers.Includes(pc) &&
8564           ((!registers.Includes(sp) && (registers.GetCount() > 1)) ||
8565            AllowUnpredictable())) {
8566         EmitT32_32(0xe92d0000U | GetRegisterListEncoding(registers, 0, 15));
8567         AdvanceIT();
8568         return;
8569       }
8570     } else {
8571       // PUSH{<c>}{<q>} <registers> ; A1
8572       // Alias of: STMDB SP!, <registers> ; A1
8573       if (cond.IsNotNever() &&
8574           // For A32, sp can appear in the list, but stores an UNKNOWN value if
8575           // it is not the lowest-valued register.
8576           (!registers.Includes(sp) ||
8577            registers.GetFirstAvailableRegister().IsSP() ||
8578            AllowUnpredictable())) {
8579         EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
8580                 GetRegisterListEncoding(registers, 0, 16));
8581         return;
8582       }
8583     }
8584   }
8585   Delegate(kPush, &Assembler::push, cond, size, registers);
8586 }
8587 
push(Condition cond,EncodingSize size,Register rt)8588 void Assembler::push(Condition cond, EncodingSize size, Register rt) {
8589   VIXL_ASSERT(AllowAssembler());
8590   CheckIT(cond);
8591   if (IsUsingT32()) {
8592     // PUSH{<c>}{<q>} <single_register_list> ; T4
8593     // Alias of: STR{<c>}{<q>} <Rt>, [SP, #4]! ; T4
8594     if (!size.IsNarrow() &&
8595         ((!rt.IsPC() && !rt.IsSP()) || AllowUnpredictable())) {
8596       EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
8597       AdvanceIT();
8598       return;
8599     }
8600   } else {
8601     // PUSH{<c>}{<q>} <single_register_list> ; A1
8602     // Alias of: STR{<c>}{<q>} <Rt>, [SP, #4]! ; A1
8603     if (cond.IsNotNever() && (!rt.IsSP() || AllowUnpredictable())) {
8604       EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8605       return;
8606     }
8607   }
8608   Delegate(kPush, &Assembler::push, cond, size, rt);
8609 }
8610 
qadd(Condition cond,Register rd,Register rm,Register rn)8611 void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
8612   VIXL_ASSERT(AllowAssembler());
8613   CheckIT(cond);
8614   if (IsUsingT32()) {
8615     // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8616     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8617       EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
8618                  (rn.GetCode() << 16));
8619       AdvanceIT();
8620       return;
8621     }
8622   } else {
8623     // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8624     if (cond.IsNotNever() &&
8625         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8626       EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8627               rm.GetCode() | (rn.GetCode() << 16));
8628       return;
8629     }
8630   }
8631   Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
8632 }
8633 
qadd16(Condition cond,Register rd,Register rn,Register rm)8634 void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
8635   VIXL_ASSERT(AllowAssembler());
8636   CheckIT(cond);
8637   if (IsUsingT32()) {
8638     // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8639     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8640       EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8641                  rm.GetCode());
8642       AdvanceIT();
8643       return;
8644     }
8645   } else {
8646     // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8647     if (cond.IsNotNever() &&
8648         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8649       EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8650               (rn.GetCode() << 16) | rm.GetCode());
8651       return;
8652     }
8653   }
8654   Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
8655 }
8656 
qadd8(Condition cond,Register rd,Register rn,Register rm)8657 void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
8658   VIXL_ASSERT(AllowAssembler());
8659   CheckIT(cond);
8660   if (IsUsingT32()) {
8661     // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8662     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8663       EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8664                  rm.GetCode());
8665       AdvanceIT();
8666       return;
8667     }
8668   } else {
8669     // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8670     if (cond.IsNotNever() &&
8671         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8672       EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8673               (rn.GetCode() << 16) | rm.GetCode());
8674       return;
8675     }
8676   }
8677   Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
8678 }
8679 
qasx(Condition cond,Register rd,Register rn,Register rm)8680 void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
8681   VIXL_ASSERT(AllowAssembler());
8682   CheckIT(cond);
8683   if (IsUsingT32()) {
8684     // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8685     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8686       EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8687                  rm.GetCode());
8688       AdvanceIT();
8689       return;
8690     }
8691   } else {
8692     // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8693     if (cond.IsNotNever() &&
8694         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8695       EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8696               (rn.GetCode() << 16) | rm.GetCode());
8697       return;
8698     }
8699   }
8700   Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
8701 }
8702 
qdadd(Condition cond,Register rd,Register rm,Register rn)8703 void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
8704   VIXL_ASSERT(AllowAssembler());
8705   CheckIT(cond);
8706   if (IsUsingT32()) {
8707     // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8708     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8709       EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
8710                  (rn.GetCode() << 16));
8711       AdvanceIT();
8712       return;
8713     }
8714   } else {
8715     // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8716     if (cond.IsNotNever() &&
8717         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8718       EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8719               rm.GetCode() | (rn.GetCode() << 16));
8720       return;
8721     }
8722   }
8723   Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
8724 }
8725 
qdsub(Condition cond,Register rd,Register rm,Register rn)8726 void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
8727   VIXL_ASSERT(AllowAssembler());
8728   CheckIT(cond);
8729   if (IsUsingT32()) {
8730     // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8731     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8732       EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8733                  (rn.GetCode() << 16));
8734       AdvanceIT();
8735       return;
8736     }
8737   } else {
8738     // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8739     if (cond.IsNotNever() &&
8740         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8741       EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8742               rm.GetCode() | (rn.GetCode() << 16));
8743       return;
8744     }
8745   }
8746   Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
8747 }
8748 
qsax(Condition cond,Register rd,Register rn,Register rm)8749 void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
8750   VIXL_ASSERT(AllowAssembler());
8751   CheckIT(cond);
8752   if (IsUsingT32()) {
8753     // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8754     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8755       EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8756                  rm.GetCode());
8757       AdvanceIT();
8758       return;
8759     }
8760   } else {
8761     // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8762     if (cond.IsNotNever() &&
8763         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8764       EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8765               (rn.GetCode() << 16) | rm.GetCode());
8766       return;
8767     }
8768   }
8769   Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
8770 }
8771 
qsub(Condition cond,Register rd,Register rm,Register rn)8772 void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
8773   VIXL_ASSERT(AllowAssembler());
8774   CheckIT(cond);
8775   if (IsUsingT32()) {
8776     // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8777     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8778       EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8779                  (rn.GetCode() << 16));
8780       AdvanceIT();
8781       return;
8782     }
8783   } else {
8784     // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8785     if (cond.IsNotNever() &&
8786         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8787       EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8788               rm.GetCode() | (rn.GetCode() << 16));
8789       return;
8790     }
8791   }
8792   Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8793 }
8794 
qsub16(Condition cond,Register rd,Register rn,Register rm)8795 void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
8796   VIXL_ASSERT(AllowAssembler());
8797   CheckIT(cond);
8798   if (IsUsingT32()) {
8799     // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8800     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8801       EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8802                  rm.GetCode());
8803       AdvanceIT();
8804       return;
8805     }
8806   } else {
8807     // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8808     if (cond.IsNotNever() &&
8809         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8810       EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8811               (rn.GetCode() << 16) | rm.GetCode());
8812       return;
8813     }
8814   }
8815   Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8816 }
8817 
qsub8(Condition cond,Register rd,Register rn,Register rm)8818 void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
8819   VIXL_ASSERT(AllowAssembler());
8820   CheckIT(cond);
8821   if (IsUsingT32()) {
8822     // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8823     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8824       EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8825                  rm.GetCode());
8826       AdvanceIT();
8827       return;
8828     }
8829   } else {
8830     // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8831     if (cond.IsNotNever() &&
8832         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8833       EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8834               (rn.GetCode() << 16) | rm.GetCode());
8835       return;
8836     }
8837   }
8838   Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8839 }
8840 
rbit(Condition cond,Register rd,Register rm)8841 void Assembler::rbit(Condition cond, Register rd, Register rm) {
8842   VIXL_ASSERT(AllowAssembler());
8843   CheckIT(cond);
8844   if (IsUsingT32()) {
8845     // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
8846     if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8847       EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8848                  (rm.GetCode() << 16));
8849       AdvanceIT();
8850       return;
8851     }
8852   } else {
8853     // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
8854     if (cond.IsNotNever() &&
8855         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8856       EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8857               rm.GetCode());
8858       return;
8859     }
8860   }
8861   Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8862 }
8863 
rev(Condition cond,EncodingSize size,Register rd,Register rm)8864 void Assembler::rev(Condition cond,
8865                     EncodingSize size,
8866                     Register rd,
8867                     Register rm) {
8868   VIXL_ASSERT(AllowAssembler());
8869   CheckIT(cond);
8870   if (IsUsingT32()) {
8871     // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8872     if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8873       EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8874       AdvanceIT();
8875       return;
8876     }
8877     // REV{<c>}{<q>} <Rd>, <Rm> ; T2
8878     if (!size.IsNarrow() &&
8879         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8880       EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8881                  (rm.GetCode() << 16));
8882       AdvanceIT();
8883       return;
8884     }
8885   } else {
8886     // REV{<c>}{<q>} <Rd>, <Rm> ; A1
8887     if (cond.IsNotNever() &&
8888         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8889       EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8890               rm.GetCode());
8891       return;
8892     }
8893   }
8894   Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8895 }
8896 
rev16(Condition cond,EncodingSize size,Register rd,Register rm)8897 void Assembler::rev16(Condition cond,
8898                       EncodingSize size,
8899                       Register rd,
8900                       Register rm) {
8901   VIXL_ASSERT(AllowAssembler());
8902   CheckIT(cond);
8903   if (IsUsingT32()) {
8904     // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8905     if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8906       EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8907       AdvanceIT();
8908       return;
8909     }
8910     // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
8911     if (!size.IsNarrow() &&
8912         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8913       EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8914                  (rm.GetCode() << 16));
8915       AdvanceIT();
8916       return;
8917     }
8918   } else {
8919     // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
8920     if (cond.IsNotNever() &&
8921         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8922       EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8923               rm.GetCode());
8924       return;
8925     }
8926   }
8927   Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8928 }
8929 
revsh(Condition cond,EncodingSize size,Register rd,Register rm)8930 void Assembler::revsh(Condition cond,
8931                       EncodingSize size,
8932                       Register rd,
8933                       Register rm) {
8934   VIXL_ASSERT(AllowAssembler());
8935   CheckIT(cond);
8936   if (IsUsingT32()) {
8937     // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8938     if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8939       EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8940       AdvanceIT();
8941       return;
8942     }
8943     // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
8944     if (!size.IsNarrow() &&
8945         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8946       EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8947                  (rm.GetCode() << 16));
8948       AdvanceIT();
8949       return;
8950     }
8951   } else {
8952     // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
8953     if (cond.IsNotNever() &&
8954         ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8955       EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8956               rm.GetCode());
8957       return;
8958     }
8959   }
8960   Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8961 }
8962 
ror(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)8963 void Assembler::ror(Condition cond,
8964                     EncodingSize size,
8965                     Register rd,
8966                     Register rm,
8967                     const Operand& operand) {
8968   VIXL_ASSERT(AllowAssembler());
8969   CheckIT(cond);
8970   if (operand.IsImmediate()) {
8971     uint32_t imm = operand.GetImmediate();
8972     if (IsUsingT32()) {
8973       // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8974       if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8975           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8976         EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8977                    ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8978         AdvanceIT();
8979         return;
8980       }
8981     } else {
8982       // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8983       if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8984         EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8985                 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8986         return;
8987       }
8988     }
8989   }
8990   if (operand.IsPlainRegister()) {
8991     Register rs = operand.GetBaseRegister();
8992     if (IsUsingT32()) {
8993       // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8994       if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8995           rs.IsLow()) {
8996         EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8997         AdvanceIT();
8998         return;
8999       }
9000       // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
9001       if (!size.IsNarrow() &&
9002           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
9003         EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
9004                    rs.GetCode());
9005         AdvanceIT();
9006         return;
9007       }
9008     } else {
9009       // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
9010       if (cond.IsNotNever() &&
9011           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
9012         EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
9013                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9014         return;
9015       }
9016     }
9017   }
9018   Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
9019 }
9020 
rors(Condition cond,EncodingSize size,Register rd,Register rm,const Operand & operand)9021 void Assembler::rors(Condition cond,
9022                      EncodingSize size,
9023                      Register rd,
9024                      Register rm,
9025                      const Operand& operand) {
9026   VIXL_ASSERT(AllowAssembler());
9027   CheckIT(cond);
9028   if (operand.IsImmediate()) {
9029     uint32_t imm = operand.GetImmediate();
9030     if (IsUsingT32()) {
9031       // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
9032       if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
9033           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9034         EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
9035                    ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
9036         AdvanceIT();
9037         return;
9038       }
9039     } else {
9040       // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
9041       if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
9042         EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
9043                 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
9044         return;
9045       }
9046     }
9047   }
9048   if (operand.IsPlainRegister()) {
9049     Register rs = operand.GetBaseRegister();
9050     if (IsUsingT32()) {
9051       // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
9052       if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
9053           rs.IsLow()) {
9054         EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
9055         AdvanceIT();
9056         return;
9057       }
9058       // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
9059       if (!size.IsNarrow() &&
9060           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
9061         EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
9062                    rs.GetCode());
9063         AdvanceIT();
9064         return;
9065       }
9066     } else {
9067       // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
9068       if (cond.IsNotNever() &&
9069           ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
9070         EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
9071                 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9072         return;
9073       }
9074     }
9075   }
9076   Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
9077 }
9078 
rrx(Condition cond,Register rd,Register rm)9079 void Assembler::rrx(Condition cond, Register rd, Register rm) {
9080   VIXL_ASSERT(AllowAssembler());
9081   CheckIT(cond);
9082   if (IsUsingT32()) {
9083     // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
9084     if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9085       EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
9086       AdvanceIT();
9087       return;
9088     }
9089   } else {
9090     // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
9091     if (cond.IsNotNever()) {
9092       EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9093               rm.GetCode());
9094       return;
9095     }
9096   }
9097   Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
9098 }
9099 
rrxs(Condition cond,Register rd,Register rm)9100 void Assembler::rrxs(Condition cond, Register rd, Register rm) {
9101   VIXL_ASSERT(AllowAssembler());
9102   CheckIT(cond);
9103   if (IsUsingT32()) {
9104     // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
9105     if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9106       EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
9107       AdvanceIT();
9108       return;
9109     }
9110   } else {
9111     // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
9112     if (cond.IsNotNever()) {
9113       EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9114               rm.GetCode());
9115       return;
9116     }
9117   }
9118   Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
9119 }
9120 
rsb(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)9121 void Assembler::rsb(Condition cond,
9122                     EncodingSize size,
9123                     Register rd,
9124                     Register rn,
9125                     const Operand& operand) {
9126   VIXL_ASSERT(AllowAssembler());
9127   CheckIT(cond);
9128   if (operand.IsImmediate()) {
9129     uint32_t imm = operand.GetImmediate();
9130     if (IsUsingT32()) {
9131       ImmediateT32 immediate_t32(imm);
9132       // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
9133       if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9134           (imm == 0)) {
9135         EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9136         AdvanceIT();
9137         return;
9138       }
9139       // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
9140       if (!size.IsNarrow() && immediate_t32.IsValid() &&
9141           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9142         EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9143                    (immediate_t32.GetEncodingValue() & 0xff) |
9144                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9145                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9146         AdvanceIT();
9147         return;
9148       }
9149     } else {
9150       ImmediateA32 immediate_a32(imm);
9151       // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9152       if (immediate_a32.IsValid() && cond.IsNotNever()) {
9153         EmitA32(0x02600000U | (cond.GetCondition() << 28) |
9154                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9155                 immediate_a32.GetEncodingValue());
9156         return;
9157       }
9158     }
9159   }
9160   if (operand.IsImmediateShiftedRegister()) {
9161     Register rm = operand.GetBaseRegister();
9162     Shift shift = operand.GetShift();
9163     uint32_t amount = operand.GetShiftAmount();
9164     if (IsUsingT32()) {
9165       // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
9166       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9167           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9168         uint32_t amount_ = amount % 32;
9169         EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9170                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9171                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9172         AdvanceIT();
9173         return;
9174       }
9175     } else {
9176       // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9177       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9178         uint32_t amount_ = amount % 32;
9179         EmitA32(0x00600000U | (cond.GetCondition() << 28) |
9180                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9181                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9182         return;
9183       }
9184     }
9185   }
9186   if (operand.IsRegisterShiftedRegister()) {
9187     Register rm = operand.GetBaseRegister();
9188     Shift shift = operand.GetShift();
9189     Register rs = operand.GetShiftRegister();
9190     if (IsUsingA32()) {
9191       // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9192       if (cond.IsNotNever() &&
9193           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9194            AllowUnpredictable())) {
9195         EmitA32(0x00600010U | (cond.GetCondition() << 28) |
9196                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9197                 (shift.GetType() << 5) | (rs.GetCode() << 8));
9198         return;
9199       }
9200     }
9201   }
9202   Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
9203 }
9204 
rsbs(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)9205 void Assembler::rsbs(Condition cond,
9206                      EncodingSize size,
9207                      Register rd,
9208                      Register rn,
9209                      const Operand& operand) {
9210   VIXL_ASSERT(AllowAssembler());
9211   CheckIT(cond);
9212   if (operand.IsImmediate()) {
9213     uint32_t imm = operand.GetImmediate();
9214     if (IsUsingT32()) {
9215       ImmediateT32 immediate_t32(imm);
9216       // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
9217       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9218           (imm == 0)) {
9219         EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9220         AdvanceIT();
9221         return;
9222       }
9223       // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
9224       if (!size.IsNarrow() && immediate_t32.IsValid() &&
9225           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9226         EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9227                    (immediate_t32.GetEncodingValue() & 0xff) |
9228                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9229                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9230         AdvanceIT();
9231         return;
9232       }
9233     } else {
9234       ImmediateA32 immediate_a32(imm);
9235       // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9236       if (immediate_a32.IsValid() && cond.IsNotNever()) {
9237         EmitA32(0x02700000U | (cond.GetCondition() << 28) |
9238                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9239                 immediate_a32.GetEncodingValue());
9240         return;
9241       }
9242     }
9243   }
9244   if (operand.IsImmediateShiftedRegister()) {
9245     Register rm = operand.GetBaseRegister();
9246     Shift shift = operand.GetShift();
9247     uint32_t amount = operand.GetShiftAmount();
9248     if (IsUsingT32()) {
9249       // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
9250       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9251           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9252         uint32_t amount_ = amount % 32;
9253         EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9254                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9255                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9256         AdvanceIT();
9257         return;
9258       }
9259     } else {
9260       // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9261       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9262         uint32_t amount_ = amount % 32;
9263         EmitA32(0x00700000U | (cond.GetCondition() << 28) |
9264                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9265                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9266         return;
9267       }
9268     }
9269   }
9270   if (operand.IsRegisterShiftedRegister()) {
9271     Register rm = operand.GetBaseRegister();
9272     Shift shift = operand.GetShift();
9273     Register rs = operand.GetShiftRegister();
9274     if (IsUsingA32()) {
9275       // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9276       if (cond.IsNotNever() &&
9277           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9278            AllowUnpredictable())) {
9279         EmitA32(0x00700010U | (cond.GetCondition() << 28) |
9280                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9281                 (shift.GetType() << 5) | (rs.GetCode() << 8));
9282         return;
9283       }
9284     }
9285   }
9286   Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
9287 }
9288 
rsc(Condition cond,Register rd,Register rn,const Operand & operand)9289 void Assembler::rsc(Condition cond,
9290                     Register rd,
9291                     Register rn,
9292                     const Operand& operand) {
9293   VIXL_ASSERT(AllowAssembler());
9294   CheckIT(cond);
9295   if (operand.IsImmediate()) {
9296     uint32_t imm = operand.GetImmediate();
9297     if (IsUsingA32()) {
9298       ImmediateA32 immediate_a32(imm);
9299       // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9300       if (immediate_a32.IsValid() && cond.IsNotNever()) {
9301         EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
9302                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9303                 immediate_a32.GetEncodingValue());
9304         return;
9305       }
9306     }
9307   }
9308   if (operand.IsImmediateShiftedRegister()) {
9309     Register rm = operand.GetBaseRegister();
9310     Shift shift = operand.GetShift();
9311     uint32_t amount = operand.GetShiftAmount();
9312     if (IsUsingA32()) {
9313       // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9314       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9315         uint32_t amount_ = amount % 32;
9316         EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
9317                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9318                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9319         return;
9320       }
9321     }
9322   }
9323   if (operand.IsRegisterShiftedRegister()) {
9324     Register rm = operand.GetBaseRegister();
9325     Shift shift = operand.GetShift();
9326     Register rs = operand.GetShiftRegister();
9327     if (IsUsingA32()) {
9328       // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9329       if (cond.IsNotNever() &&
9330           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9331            AllowUnpredictable())) {
9332         EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
9333                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9334                 (shift.GetType() << 5) | (rs.GetCode() << 8));
9335         return;
9336       }
9337     }
9338   }
9339   Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
9340 }
9341 
rscs(Condition cond,Register rd,Register rn,const Operand & operand)9342 void Assembler::rscs(Condition cond,
9343                      Register rd,
9344                      Register rn,
9345                      const Operand& operand) {
9346   VIXL_ASSERT(AllowAssembler());
9347   CheckIT(cond);
9348   if (operand.IsImmediate()) {
9349     uint32_t imm = operand.GetImmediate();
9350     if (IsUsingA32()) {
9351       ImmediateA32 immediate_a32(imm);
9352       // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9353       if (immediate_a32.IsValid() && cond.IsNotNever()) {
9354         EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
9355                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9356                 immediate_a32.GetEncodingValue());
9357         return;
9358       }
9359     }
9360   }
9361   if (operand.IsImmediateShiftedRegister()) {
9362     Register rm = operand.GetBaseRegister();
9363     Shift shift = operand.GetShift();
9364     uint32_t amount = operand.GetShiftAmount();
9365     if (IsUsingA32()) {
9366       // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9367       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9368         uint32_t amount_ = amount % 32;
9369         EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
9370                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9371                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9372         return;
9373       }
9374     }
9375   }
9376   if (operand.IsRegisterShiftedRegister()) {
9377     Register rm = operand.GetBaseRegister();
9378     Shift shift = operand.GetShift();
9379     Register rs = operand.GetShiftRegister();
9380     if (IsUsingA32()) {
9381       // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9382       if (cond.IsNotNever() &&
9383           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9384            AllowUnpredictable())) {
9385         EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
9386                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9387                 (shift.GetType() << 5) | (rs.GetCode() << 8));
9388         return;
9389       }
9390     }
9391   }
9392   Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
9393 }
9394 
sadd16(Condition cond,Register rd,Register rn,Register rm)9395 void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
9396   VIXL_ASSERT(AllowAssembler());
9397   CheckIT(cond);
9398   if (IsUsingT32()) {
9399     // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9400     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9401       EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9402                  rm.GetCode());
9403       AdvanceIT();
9404       return;
9405     }
9406   } else {
9407     // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9408     if (cond.IsNotNever() &&
9409         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9410       EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9411               (rn.GetCode() << 16) | rm.GetCode());
9412       return;
9413     }
9414   }
9415   Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
9416 }
9417 
sadd8(Condition cond,Register rd,Register rn,Register rm)9418 void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
9419   VIXL_ASSERT(AllowAssembler());
9420   CheckIT(cond);
9421   if (IsUsingT32()) {
9422     // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9423     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9424       EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9425                  rm.GetCode());
9426       AdvanceIT();
9427       return;
9428     }
9429   } else {
9430     // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9431     if (cond.IsNotNever() &&
9432         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9433       EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9434               (rn.GetCode() << 16) | rm.GetCode());
9435       return;
9436     }
9437   }
9438   Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
9439 }
9440 
sasx(Condition cond,Register rd,Register rn,Register rm)9441 void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
9442   VIXL_ASSERT(AllowAssembler());
9443   CheckIT(cond);
9444   if (IsUsingT32()) {
9445     // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9446     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9447       EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9448                  rm.GetCode());
9449       AdvanceIT();
9450       return;
9451     }
9452   } else {
9453     // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9454     if (cond.IsNotNever() &&
9455         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9456       EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9457               (rn.GetCode() << 16) | rm.GetCode());
9458       return;
9459     }
9460   }
9461   Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
9462 }
9463 
sbc(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)9464 void Assembler::sbc(Condition cond,
9465                     EncodingSize size,
9466                     Register rd,
9467                     Register rn,
9468                     const Operand& operand) {
9469   VIXL_ASSERT(AllowAssembler());
9470   CheckIT(cond);
9471   if (operand.IsImmediate()) {
9472     uint32_t imm = operand.GetImmediate();
9473     if (IsUsingT32()) {
9474       ImmediateT32 immediate_t32(imm);
9475       // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
9476       if (!size.IsNarrow() && immediate_t32.IsValid() &&
9477           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9478         EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9479                    (immediate_t32.GetEncodingValue() & 0xff) |
9480                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9481                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9482         AdvanceIT();
9483         return;
9484       }
9485     } else {
9486       ImmediateA32 immediate_a32(imm);
9487       // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9488       if (immediate_a32.IsValid() && cond.IsNotNever()) {
9489         EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
9490                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9491                 immediate_a32.GetEncodingValue());
9492         return;
9493       }
9494     }
9495   }
9496   if (operand.IsImmediateShiftedRegister()) {
9497     Register rm = operand.GetBaseRegister();
9498     if (operand.IsPlainRegister()) {
9499       if (IsUsingT32()) {
9500         // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9501         if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9502             rm.IsLow()) {
9503           EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9504           AdvanceIT();
9505           return;
9506         }
9507       }
9508     }
9509     Shift shift = operand.GetShift();
9510     uint32_t amount = operand.GetShiftAmount();
9511     if (IsUsingT32()) {
9512       // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
9513       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9514           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9515         uint32_t amount_ = amount % 32;
9516         EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9517                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9518                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9519         AdvanceIT();
9520         return;
9521       }
9522     } else {
9523       // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9524       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9525         uint32_t amount_ = amount % 32;
9526         EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
9527                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9528                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9529         return;
9530       }
9531     }
9532   }
9533   if (operand.IsRegisterShiftedRegister()) {
9534     Register rm = operand.GetBaseRegister();
9535     Shift shift = operand.GetShift();
9536     Register rs = operand.GetShiftRegister();
9537     if (IsUsingA32()) {
9538       // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9539       if (cond.IsNotNever() &&
9540           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9541            AllowUnpredictable())) {
9542         EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
9543                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9544                 (shift.GetType() << 5) | (rs.GetCode() << 8));
9545         return;
9546       }
9547     }
9548   }
9549   Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
9550 }
9551 
sbcs(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)9552 void Assembler::sbcs(Condition cond,
9553                      EncodingSize size,
9554                      Register rd,
9555                      Register rn,
9556                      const Operand& operand) {
9557   VIXL_ASSERT(AllowAssembler());
9558   CheckIT(cond);
9559   if (operand.IsImmediate()) {
9560     uint32_t imm = operand.GetImmediate();
9561     if (IsUsingT32()) {
9562       ImmediateT32 immediate_t32(imm);
9563       // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
9564       if (!size.IsNarrow() && immediate_t32.IsValid() &&
9565           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9566         EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9567                    (immediate_t32.GetEncodingValue() & 0xff) |
9568                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9569                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9570         AdvanceIT();
9571         return;
9572       }
9573     } else {
9574       ImmediateA32 immediate_a32(imm);
9575       // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9576       if (immediate_a32.IsValid() && cond.IsNotNever()) {
9577         EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
9578                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9579                 immediate_a32.GetEncodingValue());
9580         return;
9581       }
9582     }
9583   }
9584   if (operand.IsImmediateShiftedRegister()) {
9585     Register rm = operand.GetBaseRegister();
9586     if (operand.IsPlainRegister()) {
9587       if (IsUsingT32()) {
9588         // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9589         if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9590             rm.IsLow()) {
9591           EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9592           AdvanceIT();
9593           return;
9594         }
9595       }
9596     }
9597     Shift shift = operand.GetShift();
9598     uint32_t amount = operand.GetShiftAmount();
9599     if (IsUsingT32()) {
9600       // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
9601       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9602           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9603         uint32_t amount_ = amount % 32;
9604         EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9605                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9606                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9607         AdvanceIT();
9608         return;
9609       }
9610     } else {
9611       // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9612       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9613         uint32_t amount_ = amount % 32;
9614         EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
9615                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9616                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9617         return;
9618       }
9619     }
9620   }
9621   if (operand.IsRegisterShiftedRegister()) {
9622     Register rm = operand.GetBaseRegister();
9623     Shift shift = operand.GetShift();
9624     Register rs = operand.GetShiftRegister();
9625     if (IsUsingA32()) {
9626       // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9627       if (cond.IsNotNever() &&
9628           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9629            AllowUnpredictable())) {
9630         EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
9631                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9632                 (shift.GetType() << 5) | (rs.GetCode() << 8));
9633         return;
9634       }
9635     }
9636   }
9637   Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
9638 }
9639 
sbfx(Condition cond,Register rd,Register rn,uint32_t lsb,uint32_t width)9640 void Assembler::sbfx(
9641     Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
9642   VIXL_ASSERT(AllowAssembler());
9643   CheckIT(cond);
9644   if (IsUsingT32()) {
9645     // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
9646     if ((lsb <= 31) &&
9647         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9648          AllowUnpredictable())) {
9649       uint32_t widthm1 = width - 1;
9650       EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9651                  ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
9652       AdvanceIT();
9653       return;
9654     }
9655   } else {
9656     // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
9657     if ((lsb <= 31) && cond.IsNotNever() &&
9658         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9659          AllowUnpredictable())) {
9660       uint32_t widthm1 = width - 1;
9661       EmitA32(0x07a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9662               rn.GetCode() | (lsb << 7) | (widthm1 << 16));
9663       return;
9664     }
9665   }
9666   Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, width);
9667 }
9668 
sdiv(Condition cond,Register rd,Register rn,Register rm)9669 void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
9670   VIXL_ASSERT(AllowAssembler());
9671   CheckIT(cond);
9672   if (IsUsingT32()) {
9673     // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9674     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9675       EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9676                  rm.GetCode());
9677       AdvanceIT();
9678       return;
9679     }
9680   } else {
9681     // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9682     if (cond.IsNotNever() &&
9683         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9684       EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9685               rn.GetCode() | (rm.GetCode() << 8));
9686       return;
9687     }
9688   }
9689   Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
9690 }
9691 
sel(Condition cond,Register rd,Register rn,Register rm)9692 void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
9693   VIXL_ASSERT(AllowAssembler());
9694   CheckIT(cond);
9695   if (IsUsingT32()) {
9696     // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9697     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9698       EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9699                  rm.GetCode());
9700       AdvanceIT();
9701       return;
9702     }
9703   } else {
9704     // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9705     if (cond.IsNotNever() &&
9706         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9707       EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9708               (rn.GetCode() << 16) | rm.GetCode());
9709       return;
9710     }
9711   }
9712   Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
9713 }
9714 
shadd16(Condition cond,Register rd,Register rn,Register rm)9715 void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
9716   VIXL_ASSERT(AllowAssembler());
9717   CheckIT(cond);
9718   if (IsUsingT32()) {
9719     // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9720     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9721       EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9722                  rm.GetCode());
9723       AdvanceIT();
9724       return;
9725     }
9726   } else {
9727     // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9728     if (cond.IsNotNever() &&
9729         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9730       EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9731               (rn.GetCode() << 16) | rm.GetCode());
9732       return;
9733     }
9734   }
9735   Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
9736 }
9737 
shadd8(Condition cond,Register rd,Register rn,Register rm)9738 void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
9739   VIXL_ASSERT(AllowAssembler());
9740   CheckIT(cond);
9741   if (IsUsingT32()) {
9742     // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9743     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9744       EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9745                  rm.GetCode());
9746       AdvanceIT();
9747       return;
9748     }
9749   } else {
9750     // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9751     if (cond.IsNotNever() &&
9752         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9753       EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9754               (rn.GetCode() << 16) | rm.GetCode());
9755       return;
9756     }
9757   }
9758   Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
9759 }
9760 
shasx(Condition cond,Register rd,Register rn,Register rm)9761 void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
9762   VIXL_ASSERT(AllowAssembler());
9763   CheckIT(cond);
9764   if (IsUsingT32()) {
9765     // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9766     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9767       EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9768                  rm.GetCode());
9769       AdvanceIT();
9770       return;
9771     }
9772   } else {
9773     // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9774     if (cond.IsNotNever() &&
9775         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9776       EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9777               (rn.GetCode() << 16) | rm.GetCode());
9778       return;
9779     }
9780   }
9781   Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
9782 }
9783 
shsax(Condition cond,Register rd,Register rn,Register rm)9784 void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
9785   VIXL_ASSERT(AllowAssembler());
9786   CheckIT(cond);
9787   if (IsUsingT32()) {
9788     // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9789     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9790       EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9791                  rm.GetCode());
9792       AdvanceIT();
9793       return;
9794     }
9795   } else {
9796     // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9797     if (cond.IsNotNever() &&
9798         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9799       EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9800               (rn.GetCode() << 16) | rm.GetCode());
9801       return;
9802     }
9803   }
9804   Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
9805 }
9806 
shsub16(Condition cond,Register rd,Register rn,Register rm)9807 void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
9808   VIXL_ASSERT(AllowAssembler());
9809   CheckIT(cond);
9810   if (IsUsingT32()) {
9811     // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9812     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9813       EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9814                  rm.GetCode());
9815       AdvanceIT();
9816       return;
9817     }
9818   } else {
9819     // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9820     if (cond.IsNotNever() &&
9821         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9822       EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9823               (rn.GetCode() << 16) | rm.GetCode());
9824       return;
9825     }
9826   }
9827   Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
9828 }
9829 
shsub8(Condition cond,Register rd,Register rn,Register rm)9830 void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
9831   VIXL_ASSERT(AllowAssembler());
9832   CheckIT(cond);
9833   if (IsUsingT32()) {
9834     // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9835     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9836       EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9837                  rm.GetCode());
9838       AdvanceIT();
9839       return;
9840     }
9841   } else {
9842     // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9843     if (cond.IsNotNever() &&
9844         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9845       EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9846               (rn.GetCode() << 16) | rm.GetCode());
9847       return;
9848     }
9849   }
9850   Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
9851 }
9852 
smlabb(Condition cond,Register rd,Register rn,Register rm,Register ra)9853 void Assembler::smlabb(
9854     Condition cond, Register rd, Register rn, Register rm, Register ra) {
9855   VIXL_ASSERT(AllowAssembler());
9856   CheckIT(cond);
9857   if (IsUsingT32()) {
9858     // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9859     if (!ra.Is(pc) &&
9860         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9861       EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9862                  rm.GetCode() | (ra.GetCode() << 12));
9863       AdvanceIT();
9864       return;
9865     }
9866   } else {
9867     // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9868     if (cond.IsNotNever() &&
9869         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9870          AllowUnpredictable())) {
9871       EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9872               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9873       return;
9874     }
9875   }
9876   Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9877 }
9878 
smlabt(Condition cond,Register rd,Register rn,Register rm,Register ra)9879 void Assembler::smlabt(
9880     Condition cond, Register rd, Register rn, Register rm, Register ra) {
9881   VIXL_ASSERT(AllowAssembler());
9882   CheckIT(cond);
9883   if (IsUsingT32()) {
9884     // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9885     if (!ra.Is(pc) &&
9886         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9887       EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9888                  rm.GetCode() | (ra.GetCode() << 12));
9889       AdvanceIT();
9890       return;
9891     }
9892   } else {
9893     // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9894     if (cond.IsNotNever() &&
9895         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9896          AllowUnpredictable())) {
9897       EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9898               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9899       return;
9900     }
9901   }
9902   Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9903 }
9904 
smlad(Condition cond,Register rd,Register rn,Register rm,Register ra)9905 void Assembler::smlad(
9906     Condition cond, Register rd, Register rn, Register rm, Register ra) {
9907   VIXL_ASSERT(AllowAssembler());
9908   CheckIT(cond);
9909   if (IsUsingT32()) {
9910     // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9911     if (!ra.Is(pc) &&
9912         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9913       EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9914                  rm.GetCode() | (ra.GetCode() << 12));
9915       AdvanceIT();
9916       return;
9917     }
9918   } else {
9919     // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9920     if (cond.IsNotNever() && !ra.Is(pc) &&
9921         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9922       EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9923               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9924       return;
9925     }
9926   }
9927   Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9928 }
9929 
smladx(Condition cond,Register rd,Register rn,Register rm,Register ra)9930 void Assembler::smladx(
9931     Condition cond, Register rd, Register rn, Register rm, Register ra) {
9932   VIXL_ASSERT(AllowAssembler());
9933   CheckIT(cond);
9934   if (IsUsingT32()) {
9935     // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9936     if (!ra.Is(pc) &&
9937         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9938       EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9939                  rm.GetCode() | (ra.GetCode() << 12));
9940       AdvanceIT();
9941       return;
9942     }
9943   } else {
9944     // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9945     if (cond.IsNotNever() && !ra.Is(pc) &&
9946         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9947       EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9948               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9949       return;
9950     }
9951   }
9952   Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9953 }
9954 
smlal(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)9955 void Assembler::smlal(
9956     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9957   VIXL_ASSERT(AllowAssembler());
9958   CheckIT(cond);
9959   if (IsUsingT32()) {
9960     // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9961     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9962          AllowUnpredictable())) {
9963       EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9964                  (rn.GetCode() << 16) | rm.GetCode());
9965       AdvanceIT();
9966       return;
9967     }
9968   } else {
9969     // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9970     if (cond.IsNotNever() &&
9971         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9972          AllowUnpredictable())) {
9973       EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9974               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9975               (rm.GetCode() << 8));
9976       return;
9977     }
9978   }
9979   Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9980 }
9981 
smlalbb(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)9982 void Assembler::smlalbb(
9983     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9984   VIXL_ASSERT(AllowAssembler());
9985   CheckIT(cond);
9986   if (IsUsingT32()) {
9987     // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9988     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9989          AllowUnpredictable())) {
9990       EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9991                  (rn.GetCode() << 16) | rm.GetCode());
9992       AdvanceIT();
9993       return;
9994     }
9995   } else {
9996     // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9997     if (cond.IsNotNever() &&
9998         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9999          AllowUnpredictable())) {
10000       EmitA32(0x01400080U | (cond.GetCondition() << 28) |
10001               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10002               (rm.GetCode() << 8));
10003       return;
10004     }
10005   }
10006   Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
10007 }
10008 
smlalbt(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10009 void Assembler::smlalbt(
10010     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10011   VIXL_ASSERT(AllowAssembler());
10012   CheckIT(cond);
10013   if (IsUsingT32()) {
10014     // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10015     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10016          AllowUnpredictable())) {
10017       EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10018                  (rn.GetCode() << 16) | rm.GetCode());
10019       AdvanceIT();
10020       return;
10021     }
10022   } else {
10023     // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10024     if (cond.IsNotNever() &&
10025         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10026          AllowUnpredictable())) {
10027       EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
10028               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10029               (rm.GetCode() << 8));
10030       return;
10031     }
10032   }
10033   Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
10034 }
10035 
smlald(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10036 void Assembler::smlald(
10037     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10038   VIXL_ASSERT(AllowAssembler());
10039   CheckIT(cond);
10040   if (IsUsingT32()) {
10041     // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10042     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10043          AllowUnpredictable())) {
10044       EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10045                  (rn.GetCode() << 16) | rm.GetCode());
10046       AdvanceIT();
10047       return;
10048     }
10049   } else {
10050     // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10051     if (cond.IsNotNever() &&
10052         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10053          AllowUnpredictable())) {
10054       EmitA32(0x07400010U | (cond.GetCondition() << 28) |
10055               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10056               (rm.GetCode() << 8));
10057       return;
10058     }
10059   }
10060   Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
10061 }
10062 
smlaldx(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10063 void Assembler::smlaldx(
10064     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10065   VIXL_ASSERT(AllowAssembler());
10066   CheckIT(cond);
10067   if (IsUsingT32()) {
10068     // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10069     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10070          AllowUnpredictable())) {
10071       EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10072                  (rn.GetCode() << 16) | rm.GetCode());
10073       AdvanceIT();
10074       return;
10075     }
10076   } else {
10077     // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10078     if (cond.IsNotNever() &&
10079         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10080          AllowUnpredictable())) {
10081       EmitA32(0x07400030U | (cond.GetCondition() << 28) |
10082               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10083               (rm.GetCode() << 8));
10084       return;
10085     }
10086   }
10087   Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
10088 }
10089 
smlals(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10090 void Assembler::smlals(
10091     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10092   VIXL_ASSERT(AllowAssembler());
10093   CheckIT(cond);
10094   if (IsUsingA32()) {
10095     // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10096     if (cond.IsNotNever() &&
10097         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10098          AllowUnpredictable())) {
10099       EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
10100               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10101               (rm.GetCode() << 8));
10102       return;
10103     }
10104   }
10105   Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
10106 }
10107 
smlaltb(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10108 void Assembler::smlaltb(
10109     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10110   VIXL_ASSERT(AllowAssembler());
10111   CheckIT(cond);
10112   if (IsUsingT32()) {
10113     // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10114     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10115          AllowUnpredictable())) {
10116       EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10117                  (rn.GetCode() << 16) | rm.GetCode());
10118       AdvanceIT();
10119       return;
10120     }
10121   } else {
10122     // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10123     if (cond.IsNotNever() &&
10124         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10125          AllowUnpredictable())) {
10126       EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
10127               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10128               (rm.GetCode() << 8));
10129       return;
10130     }
10131   }
10132   Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
10133 }
10134 
smlaltt(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10135 void Assembler::smlaltt(
10136     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10137   VIXL_ASSERT(AllowAssembler());
10138   CheckIT(cond);
10139   if (IsUsingT32()) {
10140     // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10141     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10142          AllowUnpredictable())) {
10143       EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10144                  (rn.GetCode() << 16) | rm.GetCode());
10145       AdvanceIT();
10146       return;
10147     }
10148   } else {
10149     // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10150     if (cond.IsNotNever() &&
10151         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10152          AllowUnpredictable())) {
10153       EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
10154               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10155               (rm.GetCode() << 8));
10156       return;
10157     }
10158   }
10159   Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
10160 }
10161 
smlatb(Condition cond,Register rd,Register rn,Register rm,Register ra)10162 void Assembler::smlatb(
10163     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10164   VIXL_ASSERT(AllowAssembler());
10165   CheckIT(cond);
10166   if (IsUsingT32()) {
10167     // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10168     if (!ra.Is(pc) &&
10169         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10170       EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10171                  rm.GetCode() | (ra.GetCode() << 12));
10172       AdvanceIT();
10173       return;
10174     }
10175   } else {
10176     // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10177     if (cond.IsNotNever() &&
10178         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10179          AllowUnpredictable())) {
10180       EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10181               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10182       return;
10183     }
10184   }
10185   Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
10186 }
10187 
smlatt(Condition cond,Register rd,Register rn,Register rm,Register ra)10188 void Assembler::smlatt(
10189     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10190   VIXL_ASSERT(AllowAssembler());
10191   CheckIT(cond);
10192   if (IsUsingT32()) {
10193     // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10194     if (!ra.Is(pc) &&
10195         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10196       EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10197                  rm.GetCode() | (ra.GetCode() << 12));
10198       AdvanceIT();
10199       return;
10200     }
10201   } else {
10202     // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10203     if (cond.IsNotNever() &&
10204         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10205          AllowUnpredictable())) {
10206       EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10207               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10208       return;
10209     }
10210   }
10211   Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
10212 }
10213 
smlawb(Condition cond,Register rd,Register rn,Register rm,Register ra)10214 void Assembler::smlawb(
10215     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10216   VIXL_ASSERT(AllowAssembler());
10217   CheckIT(cond);
10218   if (IsUsingT32()) {
10219     // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10220     if (!ra.Is(pc) &&
10221         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10222       EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10223                  rm.GetCode() | (ra.GetCode() << 12));
10224       AdvanceIT();
10225       return;
10226     }
10227   } else {
10228     // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10229     if (cond.IsNotNever() &&
10230         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10231          AllowUnpredictable())) {
10232       EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10233               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10234       return;
10235     }
10236   }
10237   Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
10238 }
10239 
smlawt(Condition cond,Register rd,Register rn,Register rm,Register ra)10240 void Assembler::smlawt(
10241     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10242   VIXL_ASSERT(AllowAssembler());
10243   CheckIT(cond);
10244   if (IsUsingT32()) {
10245     // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10246     if (!ra.Is(pc) &&
10247         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10248       EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10249                  rm.GetCode() | (ra.GetCode() << 12));
10250       AdvanceIT();
10251       return;
10252     }
10253   } else {
10254     // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10255     if (cond.IsNotNever() &&
10256         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10257          AllowUnpredictable())) {
10258       EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10259               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10260       return;
10261     }
10262   }
10263   Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
10264 }
10265 
smlsd(Condition cond,Register rd,Register rn,Register rm,Register ra)10266 void Assembler::smlsd(
10267     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10268   VIXL_ASSERT(AllowAssembler());
10269   CheckIT(cond);
10270   if (IsUsingT32()) {
10271     // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10272     if (!ra.Is(pc) &&
10273         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10274       EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10275                  rm.GetCode() | (ra.GetCode() << 12));
10276       AdvanceIT();
10277       return;
10278     }
10279   } else {
10280     // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10281     if (cond.IsNotNever() && !ra.Is(pc) &&
10282         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10283       EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10284               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10285       return;
10286     }
10287   }
10288   Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
10289 }
10290 
smlsdx(Condition cond,Register rd,Register rn,Register rm,Register ra)10291 void Assembler::smlsdx(
10292     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10293   VIXL_ASSERT(AllowAssembler());
10294   CheckIT(cond);
10295   if (IsUsingT32()) {
10296     // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10297     if (!ra.Is(pc) &&
10298         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10299       EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10300                  rm.GetCode() | (ra.GetCode() << 12));
10301       AdvanceIT();
10302       return;
10303     }
10304   } else {
10305     // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10306     if (cond.IsNotNever() && !ra.Is(pc) &&
10307         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10308       EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10309               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10310       return;
10311     }
10312   }
10313   Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
10314 }
10315 
smlsld(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10316 void Assembler::smlsld(
10317     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10318   VIXL_ASSERT(AllowAssembler());
10319   CheckIT(cond);
10320   if (IsUsingT32()) {
10321     // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10322     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10323          AllowUnpredictable())) {
10324       EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10325                  (rn.GetCode() << 16) | rm.GetCode());
10326       AdvanceIT();
10327       return;
10328     }
10329   } else {
10330     // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10331     if (cond.IsNotNever() &&
10332         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10333          AllowUnpredictable())) {
10334       EmitA32(0x07400050U | (cond.GetCondition() << 28) |
10335               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10336               (rm.GetCode() << 8));
10337       return;
10338     }
10339   }
10340   Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
10341 }
10342 
smlsldx(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10343 void Assembler::smlsldx(
10344     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10345   VIXL_ASSERT(AllowAssembler());
10346   CheckIT(cond);
10347   if (IsUsingT32()) {
10348     // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10349     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10350          AllowUnpredictable())) {
10351       EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10352                  (rn.GetCode() << 16) | rm.GetCode());
10353       AdvanceIT();
10354       return;
10355     }
10356   } else {
10357     // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10358     if (cond.IsNotNever() &&
10359         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10360          AllowUnpredictable())) {
10361       EmitA32(0x07400070U | (cond.GetCondition() << 28) |
10362               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10363               (rm.GetCode() << 8));
10364       return;
10365     }
10366   }
10367   Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
10368 }
10369 
smmla(Condition cond,Register rd,Register rn,Register rm,Register ra)10370 void Assembler::smmla(
10371     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10372   VIXL_ASSERT(AllowAssembler());
10373   CheckIT(cond);
10374   if (IsUsingT32()) {
10375     // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10376     if (!ra.Is(pc) &&
10377         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10378       EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10379                  rm.GetCode() | (ra.GetCode() << 12));
10380       AdvanceIT();
10381       return;
10382     }
10383   } else {
10384     // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10385     if (cond.IsNotNever() && !ra.Is(pc) &&
10386         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10387       EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10388               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10389       return;
10390     }
10391   }
10392   Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
10393 }
10394 
smmlar(Condition cond,Register rd,Register rn,Register rm,Register ra)10395 void Assembler::smmlar(
10396     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10397   VIXL_ASSERT(AllowAssembler());
10398   CheckIT(cond);
10399   if (IsUsingT32()) {
10400     // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10401     if (!ra.Is(pc) &&
10402         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10403       EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10404                  rm.GetCode() | (ra.GetCode() << 12));
10405       AdvanceIT();
10406       return;
10407     }
10408   } else {
10409     // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10410     if (cond.IsNotNever() && !ra.Is(pc) &&
10411         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10412       EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10413               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10414       return;
10415     }
10416   }
10417   Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
10418 }
10419 
smmls(Condition cond,Register rd,Register rn,Register rm,Register ra)10420 void Assembler::smmls(
10421     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10422   VIXL_ASSERT(AllowAssembler());
10423   CheckIT(cond);
10424   if (IsUsingT32()) {
10425     // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10426     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10427          AllowUnpredictable())) {
10428       EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10429                  rm.GetCode() | (ra.GetCode() << 12));
10430       AdvanceIT();
10431       return;
10432     }
10433   } else {
10434     // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10435     if (cond.IsNotNever() &&
10436         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10437          AllowUnpredictable())) {
10438       EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10439               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10440       return;
10441     }
10442   }
10443   Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
10444 }
10445 
smmlsr(Condition cond,Register rd,Register rn,Register rm,Register ra)10446 void Assembler::smmlsr(
10447     Condition cond, Register rd, Register rn, Register rm, Register ra) {
10448   VIXL_ASSERT(AllowAssembler());
10449   CheckIT(cond);
10450   if (IsUsingT32()) {
10451     // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10452     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10453          AllowUnpredictable())) {
10454       EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10455                  rm.GetCode() | (ra.GetCode() << 12));
10456       AdvanceIT();
10457       return;
10458     }
10459   } else {
10460     // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10461     if (cond.IsNotNever() &&
10462         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10463          AllowUnpredictable())) {
10464       EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10465               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10466       return;
10467     }
10468   }
10469   Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
10470 }
10471 
smmul(Condition cond,Register rd,Register rn,Register rm)10472 void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
10473   VIXL_ASSERT(AllowAssembler());
10474   CheckIT(cond);
10475   if (IsUsingT32()) {
10476     // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10477     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10478       EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10479                  rm.GetCode());
10480       AdvanceIT();
10481       return;
10482     }
10483   } else {
10484     // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10485     if (cond.IsNotNever() &&
10486         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10487       EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10488               rn.GetCode() | (rm.GetCode() << 8));
10489       return;
10490     }
10491   }
10492   Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
10493 }
10494 
smmulr(Condition cond,Register rd,Register rn,Register rm)10495 void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
10496   VIXL_ASSERT(AllowAssembler());
10497   CheckIT(cond);
10498   if (IsUsingT32()) {
10499     // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10500     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10501       EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10502                  rm.GetCode());
10503       AdvanceIT();
10504       return;
10505     }
10506   } else {
10507     // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10508     if (cond.IsNotNever() &&
10509         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10510       EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10511               rn.GetCode() | (rm.GetCode() << 8));
10512       return;
10513     }
10514   }
10515   Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
10516 }
10517 
smuad(Condition cond,Register rd,Register rn,Register rm)10518 void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
10519   VIXL_ASSERT(AllowAssembler());
10520   CheckIT(cond);
10521   if (IsUsingT32()) {
10522     // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10523     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10524       EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10525                  rm.GetCode());
10526       AdvanceIT();
10527       return;
10528     }
10529   } else {
10530     // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10531     if (cond.IsNotNever() &&
10532         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10533       EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10534               rn.GetCode() | (rm.GetCode() << 8));
10535       return;
10536     }
10537   }
10538   Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
10539 }
10540 
smuadx(Condition cond,Register rd,Register rn,Register rm)10541 void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
10542   VIXL_ASSERT(AllowAssembler());
10543   CheckIT(cond);
10544   if (IsUsingT32()) {
10545     // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10546     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10547       EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10548                  rm.GetCode());
10549       AdvanceIT();
10550       return;
10551     }
10552   } else {
10553     // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10554     if (cond.IsNotNever() &&
10555         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10556       EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10557               rn.GetCode() | (rm.GetCode() << 8));
10558       return;
10559     }
10560   }
10561   Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
10562 }
10563 
smulbb(Condition cond,Register rd,Register rn,Register rm)10564 void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
10565   VIXL_ASSERT(AllowAssembler());
10566   CheckIT(cond);
10567   if (IsUsingT32()) {
10568     // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10569     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10570       EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10571                  rm.GetCode());
10572       AdvanceIT();
10573       return;
10574     }
10575   } else {
10576     // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10577     if (cond.IsNotNever() &&
10578         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10579       EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10580               rn.GetCode() | (rm.GetCode() << 8));
10581       return;
10582     }
10583   }
10584   Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
10585 }
10586 
smulbt(Condition cond,Register rd,Register rn,Register rm)10587 void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
10588   VIXL_ASSERT(AllowAssembler());
10589   CheckIT(cond);
10590   if (IsUsingT32()) {
10591     // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10592     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10593       EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10594                  rm.GetCode());
10595       AdvanceIT();
10596       return;
10597     }
10598   } else {
10599     // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10600     if (cond.IsNotNever() &&
10601         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10602       EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10603               rn.GetCode() | (rm.GetCode() << 8));
10604       return;
10605     }
10606   }
10607   Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
10608 }
10609 
smull(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10610 void Assembler::smull(
10611     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10612   VIXL_ASSERT(AllowAssembler());
10613   CheckIT(cond);
10614   if (IsUsingT32()) {
10615     // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10616     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10617          AllowUnpredictable())) {
10618       EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10619                  (rn.GetCode() << 16) | rm.GetCode());
10620       AdvanceIT();
10621       return;
10622     }
10623   } else {
10624     // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10625     if (cond.IsNotNever() &&
10626         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10627          AllowUnpredictable())) {
10628       EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
10629               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10630               (rm.GetCode() << 8));
10631       return;
10632     }
10633   }
10634   Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
10635 }
10636 
smulls(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)10637 void Assembler::smulls(
10638     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10639   VIXL_ASSERT(AllowAssembler());
10640   CheckIT(cond);
10641   if (IsUsingA32()) {
10642     // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10643     if (cond.IsNotNever() &&
10644         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10645          AllowUnpredictable())) {
10646       EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
10647               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10648               (rm.GetCode() << 8));
10649       return;
10650     }
10651   }
10652   Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
10653 }
10654 
smultb(Condition cond,Register rd,Register rn,Register rm)10655 void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
10656   VIXL_ASSERT(AllowAssembler());
10657   CheckIT(cond);
10658   if (IsUsingT32()) {
10659     // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10660     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10661       EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10662                  rm.GetCode());
10663       AdvanceIT();
10664       return;
10665     }
10666   } else {
10667     // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10668     if (cond.IsNotNever() &&
10669         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10670       EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10671               rn.GetCode() | (rm.GetCode() << 8));
10672       return;
10673     }
10674   }
10675   Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
10676 }
10677 
smultt(Condition cond,Register rd,Register rn,Register rm)10678 void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
10679   VIXL_ASSERT(AllowAssembler());
10680   CheckIT(cond);
10681   if (IsUsingT32()) {
10682     // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10683     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10684       EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10685                  rm.GetCode());
10686       AdvanceIT();
10687       return;
10688     }
10689   } else {
10690     // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10691     if (cond.IsNotNever() &&
10692         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10693       EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10694               rn.GetCode() | (rm.GetCode() << 8));
10695       return;
10696     }
10697   }
10698   Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
10699 }
10700 
smulwb(Condition cond,Register rd,Register rn,Register rm)10701 void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
10702   VIXL_ASSERT(AllowAssembler());
10703   CheckIT(cond);
10704   if (IsUsingT32()) {
10705     // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10706     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10707       EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10708                  rm.GetCode());
10709       AdvanceIT();
10710       return;
10711     }
10712   } else {
10713     // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10714     if (cond.IsNotNever() &&
10715         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10716       EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10717               rn.GetCode() | (rm.GetCode() << 8));
10718       return;
10719     }
10720   }
10721   Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
10722 }
10723 
smulwt(Condition cond,Register rd,Register rn,Register rm)10724 void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
10725   VIXL_ASSERT(AllowAssembler());
10726   CheckIT(cond);
10727   if (IsUsingT32()) {
10728     // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10729     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10730       EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10731                  rm.GetCode());
10732       AdvanceIT();
10733       return;
10734     }
10735   } else {
10736     // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10737     if (cond.IsNotNever() &&
10738         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10739       EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10740               rn.GetCode() | (rm.GetCode() << 8));
10741       return;
10742     }
10743   }
10744   Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
10745 }
10746 
smusd(Condition cond,Register rd,Register rn,Register rm)10747 void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
10748   VIXL_ASSERT(AllowAssembler());
10749   CheckIT(cond);
10750   if (IsUsingT32()) {
10751     // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10752     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10753       EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10754                  rm.GetCode());
10755       AdvanceIT();
10756       return;
10757     }
10758   } else {
10759     // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10760     if (cond.IsNotNever() &&
10761         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10762       EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10763               rn.GetCode() | (rm.GetCode() << 8));
10764       return;
10765     }
10766   }
10767   Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
10768 }
10769 
smusdx(Condition cond,Register rd,Register rn,Register rm)10770 void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
10771   VIXL_ASSERT(AllowAssembler());
10772   CheckIT(cond);
10773   if (IsUsingT32()) {
10774     // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10775     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10776       EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10777                  rm.GetCode());
10778       AdvanceIT();
10779       return;
10780     }
10781   } else {
10782     // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10783     if (cond.IsNotNever() &&
10784         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10785       EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10786               rn.GetCode() | (rm.GetCode() << 8));
10787       return;
10788     }
10789   }
10790   Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
10791 }
10792 
ssat(Condition cond,Register rd,uint32_t imm,const Operand & operand)10793 void Assembler::ssat(Condition cond,
10794                      Register rd,
10795                      uint32_t imm,
10796                      const Operand& operand) {
10797   VIXL_ASSERT(AllowAssembler());
10798   CheckIT(cond);
10799   if (operand.IsImmediateShiftedRegister()) {
10800     Register rn = operand.GetBaseRegister();
10801     Shift shift = operand.GetShift();
10802     uint32_t amount = operand.GetShiftAmount();
10803     if (IsUsingT32()) {
10804       // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
10805       if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
10806           (amount <= 31) &&
10807           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10808         uint32_t imm_ = imm - 1;
10809         EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10810                    (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10811                    ((amount & 0x1c) << 10));
10812         AdvanceIT();
10813         return;
10814       }
10815       // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
10816       if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10817           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10818         uint32_t imm_ = imm - 1;
10819         EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
10820                    (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10821                    ((amount & 0x1c) << 10));
10822         AdvanceIT();
10823         return;
10824       }
10825     } else {
10826       // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
10827       if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
10828           (amount <= 32) && cond.IsNotNever() &&
10829           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10830         uint32_t imm_ = imm - 1;
10831         uint32_t amount_ = amount % 32;
10832         EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
10833                 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10834                 (amount_ << 7));
10835         return;
10836       }
10837       // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
10838       if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10839           cond.IsNotNever() &&
10840           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10841         uint32_t imm_ = imm - 1;
10842         EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
10843                 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10844                 (amount << 7));
10845         return;
10846       }
10847     }
10848   }
10849   Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
10850 }
10851 
ssat16(Condition cond,Register rd,uint32_t imm,Register rn)10852 void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
10853   VIXL_ASSERT(AllowAssembler());
10854   CheckIT(cond);
10855   if (IsUsingT32()) {
10856     // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
10857     if ((imm >= 1) && (imm <= 16) &&
10858         ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10859       uint32_t imm_ = imm - 1;
10860       EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10861                  (rn.GetCode() << 16));
10862       AdvanceIT();
10863       return;
10864     }
10865   } else {
10866     // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
10867     if ((imm >= 1) && (imm <= 16) && cond.IsNotNever() &&
10868         ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10869       uint32_t imm_ = imm - 1;
10870       EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10871               (imm_ << 16) | rn.GetCode());
10872       return;
10873     }
10874   }
10875   Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
10876 }
10877 
ssax(Condition cond,Register rd,Register rn,Register rm)10878 void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
10879   VIXL_ASSERT(AllowAssembler());
10880   CheckIT(cond);
10881   if (IsUsingT32()) {
10882     // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10883     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10884       EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10885                  rm.GetCode());
10886       AdvanceIT();
10887       return;
10888     }
10889   } else {
10890     // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10891     if (cond.IsNotNever() &&
10892         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10893       EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10894               (rn.GetCode() << 16) | rm.GetCode());
10895       return;
10896     }
10897   }
10898   Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
10899 }
10900 
ssub16(Condition cond,Register rd,Register rn,Register rm)10901 void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
10902   VIXL_ASSERT(AllowAssembler());
10903   CheckIT(cond);
10904   if (IsUsingT32()) {
10905     // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10906     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10907       EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10908                  rm.GetCode());
10909       AdvanceIT();
10910       return;
10911     }
10912   } else {
10913     // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10914     if (cond.IsNotNever() &&
10915         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10916       EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10917               (rn.GetCode() << 16) | rm.GetCode());
10918       return;
10919     }
10920   }
10921   Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
10922 }
10923 
ssub8(Condition cond,Register rd,Register rn,Register rm)10924 void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
10925   VIXL_ASSERT(AllowAssembler());
10926   CheckIT(cond);
10927   if (IsUsingT32()) {
10928     // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10929     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10930       EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10931                  rm.GetCode());
10932       AdvanceIT();
10933       return;
10934     }
10935   } else {
10936     // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10937     if (cond.IsNotNever() &&
10938         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10939       EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10940               (rn.GetCode() << 16) | rm.GetCode());
10941       return;
10942     }
10943   }
10944   Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
10945 }
10946 
stl(Condition cond,Register rt,const MemOperand & operand)10947 void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
10948   VIXL_ASSERT(AllowAssembler());
10949   CheckIT(cond);
10950   if (operand.IsImmediateZero()) {
10951     Register rn = operand.GetBaseRegister();
10952     if (IsUsingT32()) {
10953       // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
10954       if (operand.IsOffset() &&
10955           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10956         EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10957         AdvanceIT();
10958         return;
10959       }
10960     } else {
10961       // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
10962       if (operand.IsOffset() && cond.IsNotNever() &&
10963           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10964         EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10965                 (rn.GetCode() << 16));
10966         return;
10967       }
10968     }
10969   }
10970   Delegate(kStl, &Assembler::stl, cond, rt, operand);
10971 }
10972 
stlb(Condition cond,Register rt,const MemOperand & operand)10973 void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
10974   VIXL_ASSERT(AllowAssembler());
10975   CheckIT(cond);
10976   if (operand.IsImmediateZero()) {
10977     Register rn = operand.GetBaseRegister();
10978     if (IsUsingT32()) {
10979       // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
10980       if (operand.IsOffset() &&
10981           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10982         EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10983         AdvanceIT();
10984         return;
10985       }
10986     } else {
10987       // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
10988       if (operand.IsOffset() && cond.IsNotNever() &&
10989           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10990         EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10991                 (rn.GetCode() << 16));
10992         return;
10993       }
10994     }
10995   }
10996   Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
10997 }
10998 
stlex(Condition cond,Register rd,Register rt,const MemOperand & operand)10999 void Assembler::stlex(Condition cond,
11000                       Register rd,
11001                       Register rt,
11002                       const MemOperand& operand) {
11003   VIXL_ASSERT(AllowAssembler());
11004   CheckIT(cond);
11005   if (operand.IsImmediateZero()) {
11006     Register rn = operand.GetBaseRegister();
11007     if (IsUsingT32()) {
11008       // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11009       if (operand.IsOffset() &&
11010           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11011         EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
11012                    (rn.GetCode() << 16));
11013         AdvanceIT();
11014         return;
11015       }
11016     } else {
11017       // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11018       if (operand.IsOffset() && cond.IsNotNever() &&
11019           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11020         EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
11021                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11022         return;
11023       }
11024     }
11025   }
11026   Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
11027 }
11028 
stlexb(Condition cond,Register rd,Register rt,const MemOperand & operand)11029 void Assembler::stlexb(Condition cond,
11030                        Register rd,
11031                        Register rt,
11032                        const MemOperand& operand) {
11033   VIXL_ASSERT(AllowAssembler());
11034   CheckIT(cond);
11035   if (operand.IsImmediateZero()) {
11036     Register rn = operand.GetBaseRegister();
11037     if (IsUsingT32()) {
11038       // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11039       if (operand.IsOffset() &&
11040           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11041         EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
11042                    (rn.GetCode() << 16));
11043         AdvanceIT();
11044         return;
11045       }
11046     } else {
11047       // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11048       if (operand.IsOffset() && cond.IsNotNever() &&
11049           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11050         EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
11051                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11052         return;
11053       }
11054     }
11055   }
11056   Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
11057 }
11058 
stlexd(Condition cond,Register rd,Register rt,Register rt2,const MemOperand & operand)11059 void Assembler::stlexd(Condition cond,
11060                        Register rd,
11061                        Register rt,
11062                        Register rt2,
11063                        const MemOperand& operand) {
11064   VIXL_ASSERT(AllowAssembler());
11065   CheckIT(cond);
11066   if (operand.IsImmediateZero()) {
11067     Register rn = operand.GetBaseRegister();
11068     if (IsUsingT32()) {
11069       // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
11070       if (operand.IsOffset() &&
11071           ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11072            AllowUnpredictable())) {
11073         EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
11074                    (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11075         AdvanceIT();
11076         return;
11077       }
11078     } else {
11079       // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11080       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11081           operand.IsOffset() && cond.IsNotNever() &&
11082           ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11083             !rn.IsPC()) ||
11084            AllowUnpredictable())) {
11085         EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
11086                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11087         return;
11088       }
11089     }
11090   }
11091   Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
11092 }
11093 
stlexh(Condition cond,Register rd,Register rt,const MemOperand & operand)11094 void Assembler::stlexh(Condition cond,
11095                        Register rd,
11096                        Register rt,
11097                        const MemOperand& operand) {
11098   VIXL_ASSERT(AllowAssembler());
11099   CheckIT(cond);
11100   if (operand.IsImmediateZero()) {
11101     Register rn = operand.GetBaseRegister();
11102     if (IsUsingT32()) {
11103       // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11104       if (operand.IsOffset() &&
11105           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11106         EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
11107                    (rn.GetCode() << 16));
11108         AdvanceIT();
11109         return;
11110       }
11111     } else {
11112       // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11113       if (operand.IsOffset() && cond.IsNotNever() &&
11114           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11115         EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
11116                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11117         return;
11118       }
11119     }
11120   }
11121   Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
11122 }
11123 
stlh(Condition cond,Register rt,const MemOperand & operand)11124 void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
11125   VIXL_ASSERT(AllowAssembler());
11126   CheckIT(cond);
11127   if (operand.IsImmediateZero()) {
11128     Register rn = operand.GetBaseRegister();
11129     if (IsUsingT32()) {
11130       // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
11131       if (operand.IsOffset() &&
11132           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11133         EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
11134         AdvanceIT();
11135         return;
11136       }
11137     } else {
11138       // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
11139       if (operand.IsOffset() && cond.IsNotNever() &&
11140           ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11141         EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
11142                 (rn.GetCode() << 16));
11143         return;
11144       }
11145     }
11146   }
11147   Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
11148 }
11149 
stm(Condition cond,EncodingSize size,Register rn,WriteBack write_back,RegisterList registers)11150 void Assembler::stm(Condition cond,
11151                     EncodingSize size,
11152                     Register rn,
11153                     WriteBack write_back,
11154                     RegisterList registers) {
11155   VIXL_ASSERT(AllowAssembler());
11156   CheckIT(cond);
11157   if (IsUsingT32()) {
11158     // STM{<c>}{<q>} <Rn>!, <registers> ; T1
11159     if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11160         ((registers.GetList() & ~0xff) == 0)) {
11161       EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11162                  GetRegisterListEncoding(registers, 0, 8));
11163       AdvanceIT();
11164       return;
11165     }
11166     // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
11167     if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11168         (!rn.IsPC() || AllowUnpredictable())) {
11169       EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11170                  (write_back.GetWriteBackUint32() << 21) |
11171                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
11172                  GetRegisterListEncoding(registers, 0, 13));
11173       AdvanceIT();
11174       return;
11175     }
11176   } else {
11177     // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
11178     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11179       EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11180               (write_back.GetWriteBackUint32() << 21) |
11181               GetRegisterListEncoding(registers, 0, 16));
11182       return;
11183     }
11184   }
11185   Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
11186 }
11187 
stmda(Condition cond,Register rn,WriteBack write_back,RegisterList registers)11188 void Assembler::stmda(Condition cond,
11189                       Register rn,
11190                       WriteBack write_back,
11191                       RegisterList registers) {
11192   VIXL_ASSERT(AllowAssembler());
11193   CheckIT(cond);
11194   if (IsUsingA32()) {
11195     // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
11196     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11197       EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11198               (write_back.GetWriteBackUint32() << 21) |
11199               GetRegisterListEncoding(registers, 0, 16));
11200       return;
11201     }
11202   }
11203   Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
11204 }
11205 
stmdb(Condition cond,EncodingSize size,Register rn,WriteBack write_back,RegisterList registers)11206 void Assembler::stmdb(Condition cond,
11207                       EncodingSize size,
11208                       Register rn,
11209                       WriteBack write_back,
11210                       RegisterList registers) {
11211   VIXL_ASSERT(AllowAssembler());
11212   CheckIT(cond);
11213   if (IsUsingT32()) {
11214     // STMDB{<c>}{<q>} SP!, <registers> ; T1
11215     if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
11216         registers.IsR0toR7orLR()) {
11217       EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
11218                  GetRegisterListEncoding(registers, 0, 8));
11219       AdvanceIT();
11220       return;
11221     }
11222     // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
11223     if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11224         (!rn.IsPC() || AllowUnpredictable())) {
11225       EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11226                  (write_back.GetWriteBackUint32() << 21) |
11227                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
11228                  GetRegisterListEncoding(registers, 0, 13));
11229       AdvanceIT();
11230       return;
11231     }
11232   } else {
11233     // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
11234     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11235       EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11236               (write_back.GetWriteBackUint32() << 21) |
11237               GetRegisterListEncoding(registers, 0, 16));
11238       return;
11239     }
11240   }
11241   Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
11242 }
11243 
stmea(Condition cond,EncodingSize size,Register rn,WriteBack write_back,RegisterList registers)11244 void Assembler::stmea(Condition cond,
11245                       EncodingSize size,
11246                       Register rn,
11247                       WriteBack write_back,
11248                       RegisterList registers) {
11249   VIXL_ASSERT(AllowAssembler());
11250   CheckIT(cond);
11251   if (IsUsingT32()) {
11252     // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
11253     if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11254         ((registers.GetList() & ~0xff) == 0)) {
11255       EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11256                  GetRegisterListEncoding(registers, 0, 8));
11257       AdvanceIT();
11258       return;
11259     }
11260     // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
11261     if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11262         (!rn.IsPC() || AllowUnpredictable())) {
11263       EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11264                  (write_back.GetWriteBackUint32() << 21) |
11265                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
11266                  GetRegisterListEncoding(registers, 0, 13));
11267       AdvanceIT();
11268       return;
11269     }
11270     // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
11271     if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11272         (!rn.IsPC() || AllowUnpredictable())) {
11273       EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11274                  (write_back.GetWriteBackUint32() << 21) |
11275                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
11276                  GetRegisterListEncoding(registers, 0, 13));
11277       AdvanceIT();
11278       return;
11279     }
11280   } else {
11281     // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
11282     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11283       EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11284               (write_back.GetWriteBackUint32() << 21) |
11285               GetRegisterListEncoding(registers, 0, 16));
11286       return;
11287     }
11288   }
11289   Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
11290 }
11291 
stmed(Condition cond,Register rn,WriteBack write_back,RegisterList registers)11292 void Assembler::stmed(Condition cond,
11293                       Register rn,
11294                       WriteBack write_back,
11295                       RegisterList registers) {
11296   VIXL_ASSERT(AllowAssembler());
11297   CheckIT(cond);
11298   if (IsUsingA32()) {
11299     // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
11300     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11301       EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11302               (write_back.GetWriteBackUint32() << 21) |
11303               GetRegisterListEncoding(registers, 0, 16));
11304       return;
11305     }
11306   }
11307   Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
11308 }
11309 
stmfa(Condition cond,Register rn,WriteBack write_back,RegisterList registers)11310 void Assembler::stmfa(Condition cond,
11311                       Register rn,
11312                       WriteBack write_back,
11313                       RegisterList registers) {
11314   VIXL_ASSERT(AllowAssembler());
11315   CheckIT(cond);
11316   if (IsUsingA32()) {
11317     // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
11318     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11319       EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11320               (write_back.GetWriteBackUint32() << 21) |
11321               GetRegisterListEncoding(registers, 0, 16));
11322       return;
11323     }
11324   }
11325   Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
11326 }
11327 
stmfd(Condition cond,Register rn,WriteBack write_back,RegisterList registers)11328 void Assembler::stmfd(Condition cond,
11329                       Register rn,
11330                       WriteBack write_back,
11331                       RegisterList registers) {
11332   VIXL_ASSERT(AllowAssembler());
11333   CheckIT(cond);
11334   if (IsUsingT32()) {
11335     // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
11336     if (((registers.GetList() & ~0x5fff) == 0) &&
11337         (!rn.IsPC() || AllowUnpredictable())) {
11338       EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11339                  (write_back.GetWriteBackUint32() << 21) |
11340                  (GetRegisterListEncoding(registers, 14, 1) << 14) |
11341                  GetRegisterListEncoding(registers, 0, 13));
11342       AdvanceIT();
11343       return;
11344     }
11345   } else {
11346     // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
11347     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11348       EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11349               (write_back.GetWriteBackUint32() << 21) |
11350               GetRegisterListEncoding(registers, 0, 16));
11351       return;
11352     }
11353   }
11354   Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
11355 }
11356 
stmib(Condition cond,Register rn,WriteBack write_back,RegisterList registers)11357 void Assembler::stmib(Condition cond,
11358                       Register rn,
11359                       WriteBack write_back,
11360                       RegisterList registers) {
11361   VIXL_ASSERT(AllowAssembler());
11362   CheckIT(cond);
11363   if (IsUsingA32()) {
11364     // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
11365     if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11366       EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11367               (write_back.GetWriteBackUint32() << 21) |
11368               GetRegisterListEncoding(registers, 0, 16));
11369       return;
11370     }
11371   }
11372   Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
11373 }
11374 
str(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)11375 void Assembler::str(Condition cond,
11376                     EncodingSize size,
11377                     Register rt,
11378                     const MemOperand& operand) {
11379   VIXL_ASSERT(AllowAssembler());
11380   CheckIT(cond);
11381   if (operand.IsImmediate()) {
11382     Register rn = operand.GetBaseRegister();
11383     int32_t offset = operand.GetOffsetImmediate();
11384     if (IsUsingT32()) {
11385       // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11386       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
11387           (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
11388         int32_t offset_ = offset >> 2;
11389         EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
11390                    ((offset_ & 0x1f) << 6));
11391         AdvanceIT();
11392         return;
11393       }
11394       // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
11395       if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
11396           ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
11397         int32_t offset_ = offset >> 2;
11398         EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
11399         AdvanceIT();
11400         return;
11401       }
11402       // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
11403       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
11404           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11405           (!rt.IsPC() || AllowUnpredictable())) {
11406         EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11407                    (offset & 0xfff));
11408         AdvanceIT();
11409         return;
11410       }
11411       // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
11412       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
11413           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11414           (!rt.IsPC() || AllowUnpredictable())) {
11415         EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11416                    (-offset & 0xff));
11417         AdvanceIT();
11418         return;
11419       }
11420       // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
11421       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11422           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11423           (!rt.IsPC() || AllowUnpredictable())) {
11424         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11425         uint32_t offset_ = abs(offset);
11426         EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11427                    offset_ | (sign << 9));
11428         AdvanceIT();
11429         return;
11430       }
11431       // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
11432       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11433           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11434           (!rt.IsPC() || AllowUnpredictable())) {
11435         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11436         uint32_t offset_ = abs(offset);
11437         EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11438                    offset_ | (sign << 9));
11439         AdvanceIT();
11440         return;
11441       }
11442     } else {
11443       // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
11444       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11445           cond.IsNotNever()) {
11446         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11447         uint32_t offset_ = abs(offset);
11448         EmitA32(0x05000000U | (cond.GetCondition() << 28) |
11449                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11450                 (sign << 23));
11451         return;
11452       }
11453       // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11454       if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11455           cond.IsNotNever()) {
11456         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11457         uint32_t offset_ = abs(offset);
11458         EmitA32(0x04000000U | (cond.GetCondition() << 28) |
11459                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11460                 (sign << 23));
11461         return;
11462       }
11463       // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11464       if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11465           cond.IsNotNever()) {
11466         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11467         uint32_t offset_ = abs(offset);
11468         EmitA32(0x05200000U | (cond.GetCondition() << 28) |
11469                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11470                 (sign << 23));
11471         return;
11472       }
11473     }
11474   }
11475   if (operand.IsPlainRegister()) {
11476     Register rn = operand.GetBaseRegister();
11477     Sign sign = operand.GetSign();
11478     Register rm = operand.GetOffsetRegister();
11479     if (IsUsingT32()) {
11480       // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11481       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11482           sign.IsPlus() && operand.IsOffset()) {
11483         EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
11484                    (rm.GetCode() << 6));
11485         AdvanceIT();
11486         return;
11487       }
11488     }
11489   }
11490   if (operand.IsShiftedRegister()) {
11491     Register rn = operand.GetBaseRegister();
11492     Sign sign = operand.GetSign();
11493     Register rm = operand.GetOffsetRegister();
11494     Shift shift = operand.GetShift();
11495     uint32_t amount = operand.GetShiftAmount();
11496     if (IsUsingT32()) {
11497       // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11498       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11499           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11500           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11501         EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11502                    rm.GetCode() | (amount << 4));
11503         AdvanceIT();
11504         return;
11505       }
11506     } else {
11507       // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
11508       if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11509           (!rm.IsPC() || AllowUnpredictable())) {
11510         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11511         uint32_t shift_ = TypeEncodingValue(shift);
11512         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11513         EmitA32(0x07000000U | (cond.GetCondition() << 28) |
11514                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11515                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11516         return;
11517       }
11518       // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
11519       if (operand.IsShiftValid() && operand.IsPostIndex() &&
11520           cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
11521         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11522         uint32_t shift_ = TypeEncodingValue(shift);
11523         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11524         EmitA32(0x06000000U | (cond.GetCondition() << 28) |
11525                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11526                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11527         return;
11528       }
11529       // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
11530       if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11531           (!rm.IsPC() || AllowUnpredictable())) {
11532         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11533         uint32_t shift_ = TypeEncodingValue(shift);
11534         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11535         EmitA32(0x07200000U | (cond.GetCondition() << 28) |
11536                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11537                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11538         return;
11539       }
11540     }
11541   }
11542   Delegate(kStr, &Assembler::str, cond, size, rt, operand);
11543 }
11544 
strb(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)11545 void Assembler::strb(Condition cond,
11546                      EncodingSize size,
11547                      Register rt,
11548                      const MemOperand& operand) {
11549   VIXL_ASSERT(AllowAssembler());
11550   CheckIT(cond);
11551   if (operand.IsImmediate()) {
11552     Register rn = operand.GetBaseRegister();
11553     int32_t offset = operand.GetOffsetImmediate();
11554     if (IsUsingT32()) {
11555       // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11556       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
11557           (offset <= 31) && operand.IsOffset()) {
11558         EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
11559                    ((offset & 0x1f) << 6));
11560         AdvanceIT();
11561         return;
11562       }
11563       // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11564       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
11565           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11566           (!rt.IsPC() || AllowUnpredictable())) {
11567         EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11568                    (offset & 0xfff));
11569         AdvanceIT();
11570         return;
11571       }
11572       // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11573       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
11574           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11575           (!rt.IsPC() || AllowUnpredictable())) {
11576         EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11577                    (-offset & 0xff));
11578         AdvanceIT();
11579         return;
11580       }
11581       // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11582       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11583           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11584           (!rt.IsPC() || AllowUnpredictable())) {
11585         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11586         uint32_t offset_ = abs(offset);
11587         EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11588                    offset_ | (sign << 9));
11589         AdvanceIT();
11590         return;
11591       }
11592       // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11593       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11594           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11595           (!rt.IsPC() || AllowUnpredictable())) {
11596         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11597         uint32_t offset_ = abs(offset);
11598         EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11599                    offset_ | (sign << 9));
11600         AdvanceIT();
11601         return;
11602       }
11603     } else {
11604       // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
11605       if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11606           cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11607         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11608         uint32_t offset_ = abs(offset);
11609         EmitA32(0x05400000U | (cond.GetCondition() << 28) |
11610                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11611                 (sign << 23));
11612         return;
11613       }
11614       // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11615       if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11616           cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11617         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11618         uint32_t offset_ = abs(offset);
11619         EmitA32(0x04400000U | (cond.GetCondition() << 28) |
11620                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11621                 (sign << 23));
11622         return;
11623       }
11624       // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11625       if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11626           cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11627         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11628         uint32_t offset_ = abs(offset);
11629         EmitA32(0x05600000U | (cond.GetCondition() << 28) |
11630                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11631                 (sign << 23));
11632         return;
11633       }
11634     }
11635   }
11636   if (operand.IsPlainRegister()) {
11637     Register rn = operand.GetBaseRegister();
11638     Sign sign = operand.GetSign();
11639     Register rm = operand.GetOffsetRegister();
11640     if (IsUsingT32()) {
11641       // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11642       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11643           sign.IsPlus() && operand.IsOffset()) {
11644         EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
11645                    (rm.GetCode() << 6));
11646         AdvanceIT();
11647         return;
11648       }
11649     }
11650   }
11651   if (operand.IsShiftedRegister()) {
11652     Register rn = operand.GetBaseRegister();
11653     Sign sign = operand.GetSign();
11654     Register rm = operand.GetOffsetRegister();
11655     Shift shift = operand.GetShift();
11656     uint32_t amount = operand.GetShiftAmount();
11657     if (IsUsingT32()) {
11658       // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11659       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11660           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11661           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11662         EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11663                    rm.GetCode() | (amount << 4));
11664         AdvanceIT();
11665         return;
11666       }
11667     } else {
11668       // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
11669       if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11670           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11671         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11672         uint32_t shift_ = TypeEncodingValue(shift);
11673         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11674         EmitA32(0x07400000U | (cond.GetCondition() << 28) |
11675                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11676                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11677         return;
11678       }
11679       // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
11680       if (operand.IsShiftValid() && operand.IsPostIndex() &&
11681           cond.IsNotNever() &&
11682           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11683         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11684         uint32_t shift_ = TypeEncodingValue(shift);
11685         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11686         EmitA32(0x06400000U | (cond.GetCondition() << 28) |
11687                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11688                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11689         return;
11690       }
11691       // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
11692       if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11693           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11694         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11695         uint32_t shift_ = TypeEncodingValue(shift);
11696         uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11697         EmitA32(0x07600000U | (cond.GetCondition() << 28) |
11698                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11699                 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11700         return;
11701       }
11702     }
11703   }
11704   Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
11705 }
11706 
strd(Condition cond,Register rt,Register rt2,const MemOperand & operand)11707 void Assembler::strd(Condition cond,
11708                      Register rt,
11709                      Register rt2,
11710                      const MemOperand& operand) {
11711   VIXL_ASSERT(AllowAssembler());
11712   CheckIT(cond);
11713   if (operand.IsImmediate()) {
11714     Register rn = operand.GetBaseRegister();
11715     int32_t offset = operand.GetOffsetImmediate();
11716     if (IsUsingT32()) {
11717       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
11718       if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
11719           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11720           ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
11721         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11722         uint32_t offset_ = abs(offset) >> 2;
11723         EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11724                    (rn.GetCode() << 16) | offset_ | (sign << 23));
11725         AdvanceIT();
11726         return;
11727       }
11728       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
11729       if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
11730           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11731           ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
11732         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11733         uint32_t offset_ = abs(offset) >> 2;
11734         EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11735                    (rn.GetCode() << 16) | offset_ | (sign << 23));
11736         AdvanceIT();
11737         return;
11738       }
11739       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
11740       if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
11741           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11742           ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
11743         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11744         uint32_t offset_ = abs(offset) >> 2;
11745         EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11746                    (rn.GetCode() << 16) | offset_ | (sign << 23));
11747         AdvanceIT();
11748         return;
11749       }
11750     } else {
11751       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
11752       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11753           (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
11754           cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11755                                 AllowUnpredictable())) {
11756         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11757         uint32_t offset_ = abs(offset);
11758         EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
11759                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11760                 ((offset_ & 0xf0) << 4) | (sign << 23));
11761         return;
11762       }
11763       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
11764       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11765           (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
11766           cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11767                                 AllowUnpredictable())) {
11768         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11769         uint32_t offset_ = abs(offset);
11770         EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
11771                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11772                 ((offset_ & 0xf0) << 4) | (sign << 23));
11773         return;
11774       }
11775       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
11776       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11777           (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
11778           cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11779                                 AllowUnpredictable())) {
11780         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11781         uint32_t offset_ = abs(offset);
11782         EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
11783                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11784                 ((offset_ & 0xf0) << 4) | (sign << 23));
11785         return;
11786       }
11787     }
11788   }
11789   if (operand.IsPlainRegister()) {
11790     Register rn = operand.GetBaseRegister();
11791     Sign sign = operand.GetSign();
11792     Register rm = operand.GetOffsetRegister();
11793     if (IsUsingA32()) {
11794       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
11795       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11796           operand.IsOffset() && cond.IsNotNever() &&
11797           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
11798            AllowUnpredictable())) {
11799         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11800         EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
11801                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11802                 (sign_ << 23));
11803         return;
11804       }
11805       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
11806       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11807           operand.IsPostIndex() && cond.IsNotNever() &&
11808           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
11809            AllowUnpredictable())) {
11810         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11811         EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
11812                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11813                 (sign_ << 23));
11814         return;
11815       }
11816       // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
11817       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11818           operand.IsPreIndex() && cond.IsNotNever() &&
11819           ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
11820            AllowUnpredictable())) {
11821         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11822         EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
11823                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11824                 (sign_ << 23));
11825         return;
11826       }
11827     }
11828   }
11829   Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
11830 }
11831 
strex(Condition cond,Register rd,Register rt,const MemOperand & operand)11832 void Assembler::strex(Condition cond,
11833                       Register rd,
11834                       Register rt,
11835                       const MemOperand& operand) {
11836   VIXL_ASSERT(AllowAssembler());
11837   CheckIT(cond);
11838   if (operand.IsImmediate()) {
11839     Register rn = operand.GetBaseRegister();
11840     int32_t offset = operand.GetOffsetImmediate();
11841     if (IsUsingT32()) {
11842       // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
11843       if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
11844           operand.IsOffset() &&
11845           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11846         int32_t offset_ = offset >> 2;
11847         EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
11848                    (rn.GetCode() << 16) | (offset_ & 0xff));
11849         AdvanceIT();
11850         return;
11851       }
11852     } else {
11853       // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
11854       if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
11855           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11856         EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
11857                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11858         return;
11859       }
11860     }
11861   }
11862   Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
11863 }
11864 
strexb(Condition cond,Register rd,Register rt,const MemOperand & operand)11865 void Assembler::strexb(Condition cond,
11866                        Register rd,
11867                        Register rt,
11868                        const MemOperand& operand) {
11869   VIXL_ASSERT(AllowAssembler());
11870   CheckIT(cond);
11871   if (operand.IsImmediateZero()) {
11872     Register rn = operand.GetBaseRegister();
11873     if (IsUsingT32()) {
11874       // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11875       if (operand.IsOffset() &&
11876           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11877         EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
11878                    (rn.GetCode() << 16));
11879         AdvanceIT();
11880         return;
11881       }
11882     } else {
11883       // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11884       if (operand.IsOffset() && cond.IsNotNever() &&
11885           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11886         EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
11887                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11888         return;
11889       }
11890     }
11891   }
11892   Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
11893 }
11894 
strexd(Condition cond,Register rd,Register rt,Register rt2,const MemOperand & operand)11895 void Assembler::strexd(Condition cond,
11896                        Register rd,
11897                        Register rt,
11898                        Register rt2,
11899                        const MemOperand& operand) {
11900   VIXL_ASSERT(AllowAssembler());
11901   CheckIT(cond);
11902   if (operand.IsImmediateZero()) {
11903     Register rn = operand.GetBaseRegister();
11904     if (IsUsingT32()) {
11905       // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
11906       if (operand.IsOffset() &&
11907           ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11908            AllowUnpredictable())) {
11909         EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
11910                    (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11911         AdvanceIT();
11912         return;
11913       }
11914     } else {
11915       // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11916       if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11917           operand.IsOffset() && cond.IsNotNever() &&
11918           ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11919             !rn.IsPC()) ||
11920            AllowUnpredictable())) {
11921         EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
11922                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11923         return;
11924       }
11925     }
11926   }
11927   Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
11928 }
11929 
strexh(Condition cond,Register rd,Register rt,const MemOperand & operand)11930 void Assembler::strexh(Condition cond,
11931                        Register rd,
11932                        Register rt,
11933                        const MemOperand& operand) {
11934   VIXL_ASSERT(AllowAssembler());
11935   CheckIT(cond);
11936   if (operand.IsImmediateZero()) {
11937     Register rn = operand.GetBaseRegister();
11938     if (IsUsingT32()) {
11939       // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11940       if (operand.IsOffset() &&
11941           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11942         EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
11943                    (rn.GetCode() << 16));
11944         AdvanceIT();
11945         return;
11946       }
11947     } else {
11948       // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11949       if (operand.IsOffset() && cond.IsNotNever() &&
11950           ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11951         EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
11952                 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11953         return;
11954       }
11955     }
11956   }
11957   Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
11958 }
11959 
strh(Condition cond,EncodingSize size,Register rt,const MemOperand & operand)11960 void Assembler::strh(Condition cond,
11961                      EncodingSize size,
11962                      Register rt,
11963                      const MemOperand& operand) {
11964   VIXL_ASSERT(AllowAssembler());
11965   CheckIT(cond);
11966   if (operand.IsImmediate()) {
11967     Register rn = operand.GetBaseRegister();
11968     int32_t offset = operand.GetOffsetImmediate();
11969     if (IsUsingT32()) {
11970       // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11971       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
11972           (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
11973         int32_t offset_ = offset >> 1;
11974         EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
11975                    ((offset_ & 0x1f) << 6));
11976         AdvanceIT();
11977         return;
11978       }
11979       // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11980       if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
11981           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11982           (!rt.IsPC() || AllowUnpredictable())) {
11983         EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11984                    (offset & 0xfff));
11985         AdvanceIT();
11986         return;
11987       }
11988       // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11989       if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
11990           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11991           (!rt.IsPC() || AllowUnpredictable())) {
11992         EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11993                    (-offset & 0xff));
11994         AdvanceIT();
11995         return;
11996       }
11997       // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11998       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11999           operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
12000           (!rt.IsPC() || AllowUnpredictable())) {
12001         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12002         uint32_t offset_ = abs(offset);
12003         EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12004                    offset_ | (sign << 9));
12005         AdvanceIT();
12006         return;
12007       }
12008       // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
12009       if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
12010           operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
12011           (!rt.IsPC() || AllowUnpredictable())) {
12012         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12013         uint32_t offset_ = abs(offset);
12014         EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12015                    offset_ | (sign << 9));
12016         AdvanceIT();
12017         return;
12018       }
12019     } else {
12020       // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
12021       if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
12022           cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
12023         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12024         uint32_t offset_ = abs(offset);
12025         EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
12026                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
12027                 ((offset_ & 0xf0) << 4) | (sign << 23));
12028         return;
12029       }
12030       // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
12031       if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
12032           cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
12033         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12034         uint32_t offset_ = abs(offset);
12035         EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
12036                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
12037                 ((offset_ & 0xf0) << 4) | (sign << 23));
12038         return;
12039       }
12040       // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
12041       if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
12042           cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
12043         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12044         uint32_t offset_ = abs(offset);
12045         EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
12046                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
12047                 ((offset_ & 0xf0) << 4) | (sign << 23));
12048         return;
12049       }
12050     }
12051   }
12052   if (operand.IsPlainRegister()) {
12053     Register rn = operand.GetBaseRegister();
12054     Sign sign = operand.GetSign();
12055     Register rm = operand.GetOffsetRegister();
12056     if (IsUsingT32()) {
12057       // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
12058       if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
12059           sign.IsPlus() && operand.IsOffset()) {
12060         EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
12061                    (rm.GetCode() << 6));
12062         AdvanceIT();
12063         return;
12064       }
12065     } else {
12066       // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
12067       if (operand.IsOffset() && cond.IsNotNever() &&
12068           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12069         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12070         EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
12071                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12072                 (sign_ << 23));
12073         return;
12074       }
12075       // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
12076       if (operand.IsPostIndex() && cond.IsNotNever() &&
12077           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12078         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12079         EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
12080                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12081                 (sign_ << 23));
12082         return;
12083       }
12084       // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
12085       if (operand.IsPreIndex() && cond.IsNotNever() &&
12086           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12087         uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12088         EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
12089                 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12090                 (sign_ << 23));
12091         return;
12092       }
12093     }
12094   }
12095   if (operand.IsShiftedRegister()) {
12096     Register rn = operand.GetBaseRegister();
12097     Sign sign = operand.GetSign();
12098     Register rm = operand.GetOffsetRegister();
12099     Shift shift = operand.GetShift();
12100     uint32_t amount = operand.GetShiftAmount();
12101     if (IsUsingT32()) {
12102       // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
12103       if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
12104           operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
12105           ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12106         EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12107                    rm.GetCode() | (amount << 4));
12108         AdvanceIT();
12109         return;
12110       }
12111     }
12112   }
12113   Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
12114 }
12115 
sub(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)12116 void Assembler::sub(Condition cond,
12117                     EncodingSize size,
12118                     Register rd,
12119                     Register rn,
12120                     const Operand& operand) {
12121   VIXL_ASSERT(AllowAssembler());
12122   CheckIT(cond);
12123   if (operand.IsImmediate()) {
12124     uint32_t imm = operand.GetImmediate();
12125     if (IsUsingT32()) {
12126       ImmediateT32 immediate_t32(imm);
12127       // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
12128       if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12129           (imm <= 7)) {
12130         EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12131         AdvanceIT();
12132         return;
12133       }
12134       // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12135       if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12136           (imm <= 255)) {
12137         EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12138         AdvanceIT();
12139         return;
12140       }
12141       // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
12142       if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
12143           ((imm % 4) == 0)) {
12144         uint32_t imm_ = imm >> 2;
12145         EmitT32_16(0xb080 | imm_);
12146         AdvanceIT();
12147         return;
12148       }
12149       // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
12150       if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
12151           (!rd.IsPC() || AllowUnpredictable())) {
12152         EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12153                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12154         AdvanceIT();
12155         return;
12156       }
12157       // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12158       if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12159           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
12160         EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12161                    (immediate_t32.GetEncodingValue() & 0xff) |
12162                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12163                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12164         AdvanceIT();
12165         return;
12166       }
12167       // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
12168       if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12169           (!rd.IsPC() || AllowUnpredictable())) {
12170         EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12171                    (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12172         AdvanceIT();
12173         return;
12174       }
12175       // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12176       if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12177           (!rd.IsPC() || AllowUnpredictable())) {
12178         EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
12179                    (immediate_t32.GetEncodingValue() & 0xff) |
12180                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12181                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12182         AdvanceIT();
12183         return;
12184       }
12185       // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
12186       if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
12187           (!rd.IsPC() || AllowUnpredictable())) {
12188         EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12189                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12190         AdvanceIT();
12191         return;
12192       }
12193     } else {
12194       ImmediateA32 immediate_a32(imm);
12195       // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
12196       if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
12197         EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
12198                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12199         return;
12200       }
12201       // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12202       if (immediate_a32.IsValid() && cond.IsNotNever() &&
12203           ((rn.GetCode() & 0xd) != 0xd)) {
12204         EmitA32(0x02400000U | (cond.GetCondition() << 28) |
12205                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12206                 immediate_a32.GetEncodingValue());
12207         return;
12208       }
12209       // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12210       if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12211         EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
12212                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12213         return;
12214       }
12215     }
12216   }
12217   if (operand.IsImmediateShiftedRegister()) {
12218     Register rm = operand.GetBaseRegister();
12219     if (operand.IsPlainRegister()) {
12220       if (IsUsingT32()) {
12221         // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
12222         if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12223             rm.IsLow()) {
12224           EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12225                      (rm.GetCode() << 6));
12226           AdvanceIT();
12227           return;
12228         }
12229         // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
12230         if (rn.Is(sp) && ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12231           EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
12232           AdvanceIT();
12233           return;
12234         }
12235       }
12236     }
12237     Shift shift = operand.GetShift();
12238     uint32_t amount = operand.GetShiftAmount();
12239     if (IsUsingT32()) {
12240       // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12241       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12242           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12243         uint32_t amount_ = amount % 32;
12244         EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12245                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12246                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12247         AdvanceIT();
12248         return;
12249       }
12250       // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12251       if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12252           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12253         uint32_t amount_ = amount % 32;
12254         EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
12255                    (operand.GetTypeEncodingValue() << 4) |
12256                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12257         AdvanceIT();
12258         return;
12259       }
12260     } else {
12261       // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12262       if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12263         uint32_t amount_ = amount % 32;
12264         EmitA32(0x00400000U | (cond.GetCondition() << 28) |
12265                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12266                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12267         return;
12268       }
12269       // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12270       if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12271         uint32_t amount_ = amount % 32;
12272         EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
12273                 (rd.GetCode() << 12) | rm.GetCode() |
12274                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12275         return;
12276       }
12277     }
12278   }
12279   if (operand.IsRegisterShiftedRegister()) {
12280     Register rm = operand.GetBaseRegister();
12281     Shift shift = operand.GetShift();
12282     Register rs = operand.GetShiftRegister();
12283     if (IsUsingA32()) {
12284       // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
12285       if (cond.IsNotNever() &&
12286           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12287            AllowUnpredictable())) {
12288         EmitA32(0x00400010U | (cond.GetCondition() << 28) |
12289                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12290                 (shift.GetType() << 5) | (rs.GetCode() << 8));
12291         return;
12292       }
12293     }
12294   }
12295   Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
12296 }
12297 
sub(Condition cond,Register rd,const Operand & operand)12298 void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
12299   VIXL_ASSERT(AllowAssembler());
12300   CheckIT(cond);
12301   if (operand.IsImmediate()) {
12302     uint32_t imm = operand.GetImmediate();
12303     if (IsUsingT32()) {
12304       // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
12305       if (InITBlock() && rd.IsLow() && (imm <= 255)) {
12306         EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12307         AdvanceIT();
12308         return;
12309       }
12310     }
12311   }
12312   Delegate(kSub, &Assembler::sub, cond, rd, operand);
12313 }
12314 
subs(Condition cond,EncodingSize size,Register rd,Register rn,const Operand & operand)12315 void Assembler::subs(Condition cond,
12316                      EncodingSize size,
12317                      Register rd,
12318                      Register rn,
12319                      const Operand& operand) {
12320   VIXL_ASSERT(AllowAssembler());
12321   CheckIT(cond);
12322   if (operand.IsImmediate()) {
12323     uint32_t imm = operand.GetImmediate();
12324     if (IsUsingT32()) {
12325       ImmediateT32 immediate_t32(imm);
12326       // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
12327       if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12328           (imm <= 7)) {
12329         EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12330         AdvanceIT();
12331         return;
12332       }
12333       // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12334       if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12335           (imm <= 255)) {
12336         EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12337         AdvanceIT();
12338         return;
12339       }
12340       // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12341       if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12342           !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
12343         EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12344                    (immediate_t32.GetEncodingValue() & 0xff) |
12345                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12346                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12347         AdvanceIT();
12348         return;
12349       }
12350       // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
12351       if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255) &&
12352           (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
12353         EmitT32_32(0xf3de8f00U | imm);
12354         AdvanceIT();
12355         return;
12356       }
12357       // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12358       if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12359           !rd.Is(pc)) {
12360         EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
12361                    (immediate_t32.GetEncodingValue() & 0xff) |
12362                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12363                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12364         AdvanceIT();
12365         return;
12366       }
12367     } else {
12368       ImmediateA32 immediate_a32(imm);
12369       // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12370       if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
12371         EmitA32(0x02500000U | (cond.GetCondition() << 28) |
12372                 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12373                 immediate_a32.GetEncodingValue());
12374         return;
12375       }
12376       // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12377       if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12378         EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
12379                 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12380         return;
12381       }
12382     }
12383   }
12384   if (operand.IsImmediateShiftedRegister()) {
12385     Register rm = operand.GetBaseRegister();
12386     if (operand.IsPlainRegister()) {
12387       if (IsUsingT32()) {
12388         // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12389         if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12390             rm.IsLow()) {
12391           EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12392                      (rm.GetCode() << 6));
12393           AdvanceIT();
12394           return;
12395         }
12396       }
12397     }
12398     Shift shift = operand.GetShift();
12399     uint32_t amount = operand.GetShiftAmount();
12400     if (IsUsingT32()) {
12401       // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12402       if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12403           !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12404         uint32_t amount_ = amount % 32;
12405         EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12406                    rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12407                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12408         AdvanceIT();
12409         return;
12410       }
12411       // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12412       if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12413           !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
12414         uint32_t amount_ = amount % 32;
12415         EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
12416                    (operand.GetTypeEncodingValue() << 4) |
12417                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12418         AdvanceIT();
12419         return;
12420       }
12421     } else {
12422       // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12423       if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12424         uint32_t amount_ = amount % 32;
12425         EmitA32(0x00500000U | (cond.GetCondition() << 28) |
12426                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12427                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12428         return;
12429       }
12430       // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12431       if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12432         uint32_t amount_ = amount % 32;
12433         EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
12434                 (rd.GetCode() << 12) | rm.GetCode() |
12435                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12436         return;
12437       }
12438     }
12439   }
12440   if (operand.IsRegisterShiftedRegister()) {
12441     Register rm = operand.GetBaseRegister();
12442     Shift shift = operand.GetShift();
12443     Register rs = operand.GetShiftRegister();
12444     if (IsUsingA32()) {
12445       // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
12446       if (cond.IsNotNever() &&
12447           ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12448            AllowUnpredictable())) {
12449         EmitA32(0x00500010U | (cond.GetCondition() << 28) |
12450                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12451                 (shift.GetType() << 5) | (rs.GetCode() << 8));
12452         return;
12453       }
12454     }
12455   }
12456   Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
12457 }
12458 
subs(Register rd,const Operand & operand)12459 void Assembler::subs(Register rd, const Operand& operand) {
12460   VIXL_ASSERT(AllowAssembler());
12461   CheckIT(al);
12462   if (operand.IsImmediate()) {
12463     uint32_t imm = operand.GetImmediate();
12464     if (IsUsingT32()) {
12465       // SUBS{<q>} <Rdn>, #<imm8> ; T2
12466       if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
12467         EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12468         AdvanceIT();
12469         return;
12470       }
12471     }
12472   }
12473   Delegate(kSubs, &Assembler::subs, rd, operand);
12474 }
12475 
subw(Condition cond,Register rd,Register rn,const Operand & operand)12476 void Assembler::subw(Condition cond,
12477                      Register rd,
12478                      Register rn,
12479                      const Operand& operand) {
12480   VIXL_ASSERT(AllowAssembler());
12481   CheckIT(cond);
12482   if (operand.IsImmediate()) {
12483     uint32_t imm = operand.GetImmediate();
12484     if (IsUsingT32()) {
12485       // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
12486       if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12487           (!rd.IsPC() || AllowUnpredictable())) {
12488         EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12489                    (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12490         AdvanceIT();
12491         return;
12492       }
12493       // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
12494       if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
12495         EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12496                    ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12497         AdvanceIT();
12498         return;
12499       }
12500     }
12501   }
12502   Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
12503 }
12504 
svc(Condition cond,uint32_t imm)12505 void Assembler::svc(Condition cond, uint32_t imm) {
12506   VIXL_ASSERT(AllowAssembler());
12507   CheckIT(cond);
12508   if (IsUsingT32()) {
12509     // SVC{<c>}{<q>} {#}<imm> ; T1
12510     if ((imm <= 255)) {
12511       EmitT32_16(0xdf00 | imm);
12512       AdvanceIT();
12513       return;
12514     }
12515   } else {
12516     // SVC{<c>}{<q>} {#}<imm> ; A1
12517     if ((imm <= 16777215) && cond.IsNotNever()) {
12518       EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
12519       return;
12520     }
12521   }
12522   Delegate(kSvc, &Assembler::svc, cond, imm);
12523 }
12524 
sxtab(Condition cond,Register rd,Register rn,const Operand & operand)12525 void Assembler::sxtab(Condition cond,
12526                       Register rd,
12527                       Register rn,
12528                       const Operand& operand) {
12529   VIXL_ASSERT(AllowAssembler());
12530   CheckIT(cond);
12531   if (operand.IsImmediateShiftedRegister()) {
12532     Register rm = operand.GetBaseRegister();
12533     Shift shift = operand.GetShift();
12534     uint32_t amount = operand.GetShiftAmount();
12535     if (IsUsingT32()) {
12536       // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12537       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12538           ((amount % 8) == 0) && !rn.Is(pc) &&
12539           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12540         uint32_t amount_ = amount / 8;
12541         EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12542                    rm.GetCode() | (amount_ << 4));
12543         AdvanceIT();
12544         return;
12545       }
12546     } else {
12547       // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12548       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12549           ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12550           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12551         uint32_t amount_ = amount / 8;
12552         EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
12553                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12554                 (amount_ << 10));
12555         return;
12556       }
12557     }
12558   }
12559   Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
12560 }
12561 
sxtab16(Condition cond,Register rd,Register rn,const Operand & operand)12562 void Assembler::sxtab16(Condition cond,
12563                         Register rd,
12564                         Register rn,
12565                         const Operand& operand) {
12566   VIXL_ASSERT(AllowAssembler());
12567   CheckIT(cond);
12568   if (operand.IsImmediateShiftedRegister()) {
12569     Register rm = operand.GetBaseRegister();
12570     Shift shift = operand.GetShift();
12571     uint32_t amount = operand.GetShiftAmount();
12572     if (IsUsingT32()) {
12573       // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12574       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12575           ((amount % 8) == 0) && !rn.Is(pc) &&
12576           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12577         uint32_t amount_ = amount / 8;
12578         EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12579                    rm.GetCode() | (amount_ << 4));
12580         AdvanceIT();
12581         return;
12582       }
12583     } else {
12584       // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12585       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12586           ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12587           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12588         uint32_t amount_ = amount / 8;
12589         EmitA32(0x06800070U | (cond.GetCondition() << 28) |
12590                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12591                 (amount_ << 10));
12592         return;
12593       }
12594     }
12595   }
12596   Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
12597 }
12598 
sxtah(Condition cond,Register rd,Register rn,const Operand & operand)12599 void Assembler::sxtah(Condition cond,
12600                       Register rd,
12601                       Register rn,
12602                       const Operand& operand) {
12603   VIXL_ASSERT(AllowAssembler());
12604   CheckIT(cond);
12605   if (operand.IsImmediateShiftedRegister()) {
12606     Register rm = operand.GetBaseRegister();
12607     Shift shift = operand.GetShift();
12608     uint32_t amount = operand.GetShiftAmount();
12609     if (IsUsingT32()) {
12610       // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12611       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12612           ((amount % 8) == 0) && !rn.Is(pc) &&
12613           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12614         uint32_t amount_ = amount / 8;
12615         EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12616                    rm.GetCode() | (amount_ << 4));
12617         AdvanceIT();
12618         return;
12619       }
12620     } else {
12621       // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12622       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12623           ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12624           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12625         uint32_t amount_ = amount / 8;
12626         EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
12627                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12628                 (amount_ << 10));
12629         return;
12630       }
12631     }
12632   }
12633   Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
12634 }
12635 
sxtb(Condition cond,EncodingSize size,Register rd,const Operand & operand)12636 void Assembler::sxtb(Condition cond,
12637                      EncodingSize size,
12638                      Register rd,
12639                      const Operand& operand) {
12640   VIXL_ASSERT(AllowAssembler());
12641   CheckIT(cond);
12642   if (operand.IsImmediateShiftedRegister()) {
12643     Register rm = operand.GetBaseRegister();
12644     if (operand.IsPlainRegister()) {
12645       if (IsUsingT32()) {
12646         // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12647         if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12648           EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
12649           AdvanceIT();
12650           return;
12651         }
12652       }
12653     }
12654     Shift shift = operand.GetShift();
12655     uint32_t amount = operand.GetShiftAmount();
12656     if (IsUsingT32()) {
12657       // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12658       if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12659           (amount <= 24) && ((amount % 8) == 0) &&
12660           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12661         uint32_t amount_ = amount / 8;
12662         EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12663                    (amount_ << 4));
12664         AdvanceIT();
12665         return;
12666       }
12667     } else {
12668       // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12669       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12670           ((amount % 8) == 0) && cond.IsNotNever() &&
12671           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12672         uint32_t amount_ = amount / 8;
12673         EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
12674                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12675         return;
12676       }
12677     }
12678   }
12679   Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
12680 }
12681 
sxtb16(Condition cond,Register rd,const Operand & operand)12682 void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
12683   VIXL_ASSERT(AllowAssembler());
12684   CheckIT(cond);
12685   if (operand.IsImmediateShiftedRegister()) {
12686     Register rm = operand.GetBaseRegister();
12687     Shift shift = operand.GetShift();
12688     uint32_t amount = operand.GetShiftAmount();
12689     if (IsUsingT32()) {
12690       // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12691       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12692           ((amount % 8) == 0) &&
12693           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12694         uint32_t amount_ = amount / 8;
12695         EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12696                    (amount_ << 4));
12697         AdvanceIT();
12698         return;
12699       }
12700     } else {
12701       // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12702       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12703           ((amount % 8) == 0) && cond.IsNotNever() &&
12704           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12705         uint32_t amount_ = amount / 8;
12706         EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
12707                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12708         return;
12709       }
12710     }
12711   }
12712   Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
12713 }
12714 
sxth(Condition cond,EncodingSize size,Register rd,const Operand & operand)12715 void Assembler::sxth(Condition cond,
12716                      EncodingSize size,
12717                      Register rd,
12718                      const Operand& operand) {
12719   VIXL_ASSERT(AllowAssembler());
12720   CheckIT(cond);
12721   if (operand.IsImmediateShiftedRegister()) {
12722     Register rm = operand.GetBaseRegister();
12723     if (operand.IsPlainRegister()) {
12724       if (IsUsingT32()) {
12725         // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12726         if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12727           EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
12728           AdvanceIT();
12729           return;
12730         }
12731       }
12732     }
12733     Shift shift = operand.GetShift();
12734     uint32_t amount = operand.GetShiftAmount();
12735     if (IsUsingT32()) {
12736       // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12737       if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12738           (amount <= 24) && ((amount % 8) == 0) &&
12739           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12740         uint32_t amount_ = amount / 8;
12741         EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12742                    (amount_ << 4));
12743         AdvanceIT();
12744         return;
12745       }
12746     } else {
12747       // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12748       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12749           ((amount % 8) == 0) && cond.IsNotNever() &&
12750           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12751         uint32_t amount_ = amount / 8;
12752         EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
12753                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12754         return;
12755       }
12756     }
12757   }
12758   Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
12759 }
12760 
tbb(Condition cond,Register rn,Register rm)12761 void Assembler::tbb(Condition cond, Register rn, Register rm) {
12762   VIXL_ASSERT(AllowAssembler());
12763   CheckIT(cond);
12764   if (IsUsingT32()) {
12765     // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
12766     if (OutsideITBlockAndAlOrLast(cond) &&
12767         (!rm.IsPC() || AllowUnpredictable())) {
12768       EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
12769       AdvanceIT();
12770       return;
12771     }
12772   }
12773   Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
12774 }
12775 
tbh(Condition cond,Register rn,Register rm)12776 void Assembler::tbh(Condition cond, Register rn, Register rm) {
12777   VIXL_ASSERT(AllowAssembler());
12778   CheckIT(cond);
12779   if (IsUsingT32()) {
12780     // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
12781     if (OutsideITBlockAndAlOrLast(cond) &&
12782         (!rm.IsPC() || AllowUnpredictable())) {
12783       EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
12784       AdvanceIT();
12785       return;
12786     }
12787   }
12788   Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
12789 }
12790 
teq(Condition cond,Register rn,const Operand & operand)12791 void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
12792   VIXL_ASSERT(AllowAssembler());
12793   CheckIT(cond);
12794   if (operand.IsImmediate()) {
12795     uint32_t imm = operand.GetImmediate();
12796     if (IsUsingT32()) {
12797       ImmediateT32 immediate_t32(imm);
12798       // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
12799       if (immediate_t32.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
12800         EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
12801                    (immediate_t32.GetEncodingValue() & 0xff) |
12802                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12803                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12804         AdvanceIT();
12805         return;
12806       }
12807     } else {
12808       ImmediateA32 immediate_a32(imm);
12809       // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
12810       if (immediate_a32.IsValid() && cond.IsNotNever()) {
12811         EmitA32(0x03300000U | (cond.GetCondition() << 28) |
12812                 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12813         return;
12814       }
12815     }
12816   }
12817   if (operand.IsImmediateShiftedRegister()) {
12818     Register rm = operand.GetBaseRegister();
12819     Shift shift = operand.GetShift();
12820     uint32_t amount = operand.GetShiftAmount();
12821     if (IsUsingT32()) {
12822       // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
12823       if (shift.IsValidAmount(amount) &&
12824           ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12825         uint32_t amount_ = amount % 32;
12826         EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
12827                    (operand.GetTypeEncodingValue() << 4) |
12828                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12829         AdvanceIT();
12830         return;
12831       }
12832     } else {
12833       // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12834       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12835         uint32_t amount_ = amount % 32;
12836         EmitA32(0x01300000U | (cond.GetCondition() << 28) |
12837                 (rn.GetCode() << 16) | rm.GetCode() |
12838                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12839         return;
12840       }
12841     }
12842   }
12843   if (operand.IsRegisterShiftedRegister()) {
12844     Register rm = operand.GetBaseRegister();
12845     Shift shift = operand.GetShift();
12846     Register rs = operand.GetShiftRegister();
12847     if (IsUsingA32()) {
12848       // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
12849       if (cond.IsNotNever() &&
12850           ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
12851         EmitA32(0x01300010U | (cond.GetCondition() << 28) |
12852                 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
12853                 (rs.GetCode() << 8));
12854         return;
12855       }
12856     }
12857   }
12858   Delegate(kTeq, &Assembler::teq, cond, rn, operand);
12859 }
12860 
tst(Condition cond,EncodingSize size,Register rn,const Operand & operand)12861 void Assembler::tst(Condition cond,
12862                     EncodingSize size,
12863                     Register rn,
12864                     const Operand& operand) {
12865   VIXL_ASSERT(AllowAssembler());
12866   CheckIT(cond);
12867   if (operand.IsImmediate()) {
12868     uint32_t imm = operand.GetImmediate();
12869     if (IsUsingT32()) {
12870       ImmediateT32 immediate_t32(imm);
12871       // TST{<c>}{<q>} <Rn>, #<const> ; T1
12872       if (!size.IsNarrow() && immediate_t32.IsValid() &&
12873           (!rn.IsPC() || AllowUnpredictable())) {
12874         EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
12875                    (immediate_t32.GetEncodingValue() & 0xff) |
12876                    ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12877                    ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12878         AdvanceIT();
12879         return;
12880       }
12881     } else {
12882       ImmediateA32 immediate_a32(imm);
12883       // TST{<c>}{<q>} <Rn>, #<const> ; A1
12884       if (immediate_a32.IsValid() && cond.IsNotNever()) {
12885         EmitA32(0x03100000U | (cond.GetCondition() << 28) |
12886                 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12887         return;
12888       }
12889     }
12890   }
12891   if (operand.IsImmediateShiftedRegister()) {
12892     Register rm = operand.GetBaseRegister();
12893     if (operand.IsPlainRegister()) {
12894       if (IsUsingT32()) {
12895         // TST{<c>}{<q>} <Rn>, <Rm> ; T1
12896         if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
12897           EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
12898           AdvanceIT();
12899           return;
12900         }
12901       }
12902     }
12903     Shift shift = operand.GetShift();
12904     uint32_t amount = operand.GetShiftAmount();
12905     if (IsUsingT32()) {
12906       // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
12907       if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
12908           ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12909         uint32_t amount_ = amount % 32;
12910         EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
12911                    (operand.GetTypeEncodingValue() << 4) |
12912                    ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12913         AdvanceIT();
12914         return;
12915       }
12916     } else {
12917       // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12918       if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12919         uint32_t amount_ = amount % 32;
12920         EmitA32(0x01100000U | (cond.GetCondition() << 28) |
12921                 (rn.GetCode() << 16) | rm.GetCode() |
12922                 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12923         return;
12924       }
12925     }
12926   }
12927   if (operand.IsRegisterShiftedRegister()) {
12928     Register rm = operand.GetBaseRegister();
12929     Shift shift = operand.GetShift();
12930     Register rs = operand.GetShiftRegister();
12931     if (IsUsingA32()) {
12932       // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
12933       if (cond.IsNotNever() &&
12934           ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
12935         EmitA32(0x01100010U | (cond.GetCondition() << 28) |
12936                 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
12937                 (rs.GetCode() << 8));
12938         return;
12939       }
12940     }
12941   }
12942   Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
12943 }
12944 
uadd16(Condition cond,Register rd,Register rn,Register rm)12945 void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
12946   VIXL_ASSERT(AllowAssembler());
12947   CheckIT(cond);
12948   if (IsUsingT32()) {
12949     // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12950     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12951       EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12952                  rm.GetCode());
12953       AdvanceIT();
12954       return;
12955     }
12956   } else {
12957     // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12958     if (cond.IsNotNever() &&
12959         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12960       EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12961               (rn.GetCode() << 16) | rm.GetCode());
12962       return;
12963     }
12964   }
12965   Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
12966 }
12967 
uadd8(Condition cond,Register rd,Register rn,Register rm)12968 void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
12969   VIXL_ASSERT(AllowAssembler());
12970   CheckIT(cond);
12971   if (IsUsingT32()) {
12972     // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12973     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12974       EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12975                  rm.GetCode());
12976       AdvanceIT();
12977       return;
12978     }
12979   } else {
12980     // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12981     if (cond.IsNotNever() &&
12982         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12983       EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12984               (rn.GetCode() << 16) | rm.GetCode());
12985       return;
12986     }
12987   }
12988   Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
12989 }
12990 
uasx(Condition cond,Register rd,Register rn,Register rm)12991 void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
12992   VIXL_ASSERT(AllowAssembler());
12993   CheckIT(cond);
12994   if (IsUsingT32()) {
12995     // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12996     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12997       EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12998                  rm.GetCode());
12999       AdvanceIT();
13000       return;
13001     }
13002   } else {
13003     // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13004     if (cond.IsNotNever() &&
13005         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13006       EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13007               (rn.GetCode() << 16) | rm.GetCode());
13008       return;
13009     }
13010   }
13011   Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
13012 }
13013 
ubfx(Condition cond,Register rd,Register rn,uint32_t lsb,uint32_t width)13014 void Assembler::ubfx(
13015     Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
13016   VIXL_ASSERT(AllowAssembler());
13017   CheckIT(cond);
13018   if (IsUsingT32()) {
13019     // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
13020     if ((lsb <= 31) &&
13021         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
13022          AllowUnpredictable())) {
13023       uint32_t widthm1 = width - 1;
13024       EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13025                  ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
13026       AdvanceIT();
13027       return;
13028     }
13029   } else {
13030     // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
13031     if ((lsb <= 31) && cond.IsNotNever() &&
13032         (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
13033          AllowUnpredictable())) {
13034       uint32_t widthm1 = width - 1;
13035       EmitA32(0x07e00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13036               rn.GetCode() | (lsb << 7) | (widthm1 << 16));
13037       return;
13038     }
13039   }
13040   Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, width);
13041 }
13042 
udf(Condition cond,EncodingSize size,uint32_t imm)13043 void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
13044   VIXL_ASSERT(AllowAssembler());
13045   CheckIT(cond);
13046   if (IsUsingT32()) {
13047     // UDF{<c>}{<q>} {#}<imm> ; T1
13048     if (!size.IsWide() && (imm <= 255)) {
13049       if (cond.Is(al) || AllowStronglyDiscouraged()) {
13050         EmitT32_16(0xde00 | imm);
13051         AdvanceIT();
13052         return;
13053       }
13054     }
13055     // UDF{<c>}{<q>} {#}<imm> ; T2
13056     if (!size.IsNarrow() && (imm <= 65535)) {
13057       if (cond.Is(al) || AllowStronglyDiscouraged()) {
13058         EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
13059         AdvanceIT();
13060         return;
13061       }
13062     }
13063   } else {
13064     // UDF{<c>}{<q>} {#}<imm> ; A1
13065     if ((imm <= 65535)) {
13066       if (cond.Is(al) || AllowStronglyDiscouraged()) {
13067         EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
13068         return;
13069       }
13070     }
13071   }
13072   Delegate(kUdf, &Assembler::udf, cond, size, imm);
13073 }
13074 
udiv(Condition cond,Register rd,Register rn,Register rm)13075 void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
13076   VIXL_ASSERT(AllowAssembler());
13077   CheckIT(cond);
13078   if (IsUsingT32()) {
13079     // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13080     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13081       EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13082                  rm.GetCode());
13083       AdvanceIT();
13084       return;
13085     }
13086   } else {
13087     // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13088     if (cond.IsNotNever() &&
13089         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13090       EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13091               rn.GetCode() | (rm.GetCode() << 8));
13092       return;
13093     }
13094   }
13095   Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
13096 }
13097 
uhadd16(Condition cond,Register rd,Register rn,Register rm)13098 void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
13099   VIXL_ASSERT(AllowAssembler());
13100   CheckIT(cond);
13101   if (IsUsingT32()) {
13102     // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13103     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13104       EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13105                  rm.GetCode());
13106       AdvanceIT();
13107       return;
13108     }
13109   } else {
13110     // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13111     if (cond.IsNotNever() &&
13112         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13113       EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13114               (rn.GetCode() << 16) | rm.GetCode());
13115       return;
13116     }
13117   }
13118   Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
13119 }
13120 
uhadd8(Condition cond,Register rd,Register rn,Register rm)13121 void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
13122   VIXL_ASSERT(AllowAssembler());
13123   CheckIT(cond);
13124   if (IsUsingT32()) {
13125     // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13126     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13127       EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13128                  rm.GetCode());
13129       AdvanceIT();
13130       return;
13131     }
13132   } else {
13133     // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13134     if (cond.IsNotNever() &&
13135         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13136       EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13137               (rn.GetCode() << 16) | rm.GetCode());
13138       return;
13139     }
13140   }
13141   Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
13142 }
13143 
uhasx(Condition cond,Register rd,Register rn,Register rm)13144 void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
13145   VIXL_ASSERT(AllowAssembler());
13146   CheckIT(cond);
13147   if (IsUsingT32()) {
13148     // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13149     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13150       EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13151                  rm.GetCode());
13152       AdvanceIT();
13153       return;
13154     }
13155   } else {
13156     // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13157     if (cond.IsNotNever() &&
13158         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13159       EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13160               (rn.GetCode() << 16) | rm.GetCode());
13161       return;
13162     }
13163   }
13164   Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
13165 }
13166 
uhsax(Condition cond,Register rd,Register rn,Register rm)13167 void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
13168   VIXL_ASSERT(AllowAssembler());
13169   CheckIT(cond);
13170   if (IsUsingT32()) {
13171     // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13172     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13173       EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13174                  rm.GetCode());
13175       AdvanceIT();
13176       return;
13177     }
13178   } else {
13179     // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13180     if (cond.IsNotNever() &&
13181         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13182       EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13183               (rn.GetCode() << 16) | rm.GetCode());
13184       return;
13185     }
13186   }
13187   Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
13188 }
13189 
uhsub16(Condition cond,Register rd,Register rn,Register rm)13190 void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
13191   VIXL_ASSERT(AllowAssembler());
13192   CheckIT(cond);
13193   if (IsUsingT32()) {
13194     // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13195     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13196       EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13197                  rm.GetCode());
13198       AdvanceIT();
13199       return;
13200     }
13201   } else {
13202     // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13203     if (cond.IsNotNever() &&
13204         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13205       EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13206               (rn.GetCode() << 16) | rm.GetCode());
13207       return;
13208     }
13209   }
13210   Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
13211 }
13212 
uhsub8(Condition cond,Register rd,Register rn,Register rm)13213 void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
13214   VIXL_ASSERT(AllowAssembler());
13215   CheckIT(cond);
13216   if (IsUsingT32()) {
13217     // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13218     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13219       EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13220                  rm.GetCode());
13221       AdvanceIT();
13222       return;
13223     }
13224   } else {
13225     // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13226     if (cond.IsNotNever() &&
13227         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13228       EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13229               (rn.GetCode() << 16) | rm.GetCode());
13230       return;
13231     }
13232   }
13233   Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
13234 }
13235 
umaal(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)13236 void Assembler::umaal(
13237     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13238   VIXL_ASSERT(AllowAssembler());
13239   CheckIT(cond);
13240   if (IsUsingT32()) {
13241     // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
13242     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13243          AllowUnpredictable())) {
13244       EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13245                  (rn.GetCode() << 16) | rm.GetCode());
13246       AdvanceIT();
13247       return;
13248     }
13249   } else {
13250     // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13251     if (cond.IsNotNever() &&
13252         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13253          AllowUnpredictable())) {
13254       EmitA32(0x00400090U | (cond.GetCondition() << 28) |
13255               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13256               (rm.GetCode() << 8));
13257       return;
13258     }
13259   }
13260   Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
13261 }
13262 
umlal(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)13263 void Assembler::umlal(
13264     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13265   VIXL_ASSERT(AllowAssembler());
13266   CheckIT(cond);
13267   if (IsUsingT32()) {
13268     // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
13269     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13270          AllowUnpredictable())) {
13271       EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13272                  (rn.GetCode() << 16) | rm.GetCode());
13273       AdvanceIT();
13274       return;
13275     }
13276   } else {
13277     // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13278     if (cond.IsNotNever() &&
13279         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13280          AllowUnpredictable())) {
13281       EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
13282               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13283               (rm.GetCode() << 8));
13284       return;
13285     }
13286   }
13287   Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
13288 }
13289 
umlals(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)13290 void Assembler::umlals(
13291     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13292   VIXL_ASSERT(AllowAssembler());
13293   CheckIT(cond);
13294   if (IsUsingA32()) {
13295     // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13296     if (cond.IsNotNever() &&
13297         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13298          AllowUnpredictable())) {
13299       EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
13300               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13301               (rm.GetCode() << 8));
13302       return;
13303     }
13304   }
13305   Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
13306 }
13307 
umull(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)13308 void Assembler::umull(
13309     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13310   VIXL_ASSERT(AllowAssembler());
13311   CheckIT(cond);
13312   if (IsUsingT32()) {
13313     // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
13314     if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13315          AllowUnpredictable())) {
13316       EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13317                  (rn.GetCode() << 16) | rm.GetCode());
13318       AdvanceIT();
13319       return;
13320     }
13321   } else {
13322     // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13323     if (cond.IsNotNever() &&
13324         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13325          AllowUnpredictable())) {
13326       EmitA32(0x00800090U | (cond.GetCondition() << 28) |
13327               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13328               (rm.GetCode() << 8));
13329       return;
13330     }
13331   }
13332   Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
13333 }
13334 
umulls(Condition cond,Register rdlo,Register rdhi,Register rn,Register rm)13335 void Assembler::umulls(
13336     Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13337   VIXL_ASSERT(AllowAssembler());
13338   CheckIT(cond);
13339   if (IsUsingA32()) {
13340     // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13341     if (cond.IsNotNever() &&
13342         ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13343          AllowUnpredictable())) {
13344       EmitA32(0x00900090U | (cond.GetCondition() << 28) |
13345               (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13346               (rm.GetCode() << 8));
13347       return;
13348     }
13349   }
13350   Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
13351 }
13352 
uqadd16(Condition cond,Register rd,Register rn,Register rm)13353 void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
13354   VIXL_ASSERT(AllowAssembler());
13355   CheckIT(cond);
13356   if (IsUsingT32()) {
13357     // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13358     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13359       EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13360                  rm.GetCode());
13361       AdvanceIT();
13362       return;
13363     }
13364   } else {
13365     // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13366     if (cond.IsNotNever() &&
13367         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13368       EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13369               (rn.GetCode() << 16) | rm.GetCode());
13370       return;
13371     }
13372   }
13373   Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
13374 }
13375 
uqadd8(Condition cond,Register rd,Register rn,Register rm)13376 void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
13377   VIXL_ASSERT(AllowAssembler());
13378   CheckIT(cond);
13379   if (IsUsingT32()) {
13380     // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13381     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13382       EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13383                  rm.GetCode());
13384       AdvanceIT();
13385       return;
13386     }
13387   } else {
13388     // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13389     if (cond.IsNotNever() &&
13390         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13391       EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13392               (rn.GetCode() << 16) | rm.GetCode());
13393       return;
13394     }
13395   }
13396   Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
13397 }
13398 
uqasx(Condition cond,Register rd,Register rn,Register rm)13399 void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
13400   VIXL_ASSERT(AllowAssembler());
13401   CheckIT(cond);
13402   if (IsUsingT32()) {
13403     // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13404     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13405       EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13406                  rm.GetCode());
13407       AdvanceIT();
13408       return;
13409     }
13410   } else {
13411     // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13412     if (cond.IsNotNever() &&
13413         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13414       EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13415               (rn.GetCode() << 16) | rm.GetCode());
13416       return;
13417     }
13418   }
13419   Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
13420 }
13421 
uqsax(Condition cond,Register rd,Register rn,Register rm)13422 void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
13423   VIXL_ASSERT(AllowAssembler());
13424   CheckIT(cond);
13425   if (IsUsingT32()) {
13426     // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13427     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13428       EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13429                  rm.GetCode());
13430       AdvanceIT();
13431       return;
13432     }
13433   } else {
13434     // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13435     if (cond.IsNotNever() &&
13436         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13437       EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13438               (rn.GetCode() << 16) | rm.GetCode());
13439       return;
13440     }
13441   }
13442   Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
13443 }
13444 
uqsub16(Condition cond,Register rd,Register rn,Register rm)13445 void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
13446   VIXL_ASSERT(AllowAssembler());
13447   CheckIT(cond);
13448   if (IsUsingT32()) {
13449     // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13450     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13451       EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13452                  rm.GetCode());
13453       AdvanceIT();
13454       return;
13455     }
13456   } else {
13457     // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13458     if (cond.IsNotNever() &&
13459         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13460       EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13461               (rn.GetCode() << 16) | rm.GetCode());
13462       return;
13463     }
13464   }
13465   Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
13466 }
13467 
uqsub8(Condition cond,Register rd,Register rn,Register rm)13468 void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
13469   VIXL_ASSERT(AllowAssembler());
13470   CheckIT(cond);
13471   if (IsUsingT32()) {
13472     // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13473     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13474       EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13475                  rm.GetCode());
13476       AdvanceIT();
13477       return;
13478     }
13479   } else {
13480     // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13481     if (cond.IsNotNever() &&
13482         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13483       EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13484               (rn.GetCode() << 16) | rm.GetCode());
13485       return;
13486     }
13487   }
13488   Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
13489 }
13490 
usad8(Condition cond,Register rd,Register rn,Register rm)13491 void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
13492   VIXL_ASSERT(AllowAssembler());
13493   CheckIT(cond);
13494   if (IsUsingT32()) {
13495     // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13496     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13497       EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13498                  rm.GetCode());
13499       AdvanceIT();
13500       return;
13501     }
13502   } else {
13503     // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13504     if (cond.IsNotNever() &&
13505         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13506       EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13507               rn.GetCode() | (rm.GetCode() << 8));
13508       return;
13509     }
13510   }
13511   Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
13512 }
13513 
usada8(Condition cond,Register rd,Register rn,Register rm,Register ra)13514 void Assembler::usada8(
13515     Condition cond, Register rd, Register rn, Register rm, Register ra) {
13516   VIXL_ASSERT(AllowAssembler());
13517   CheckIT(cond);
13518   if (IsUsingT32()) {
13519     // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
13520     if (!ra.Is(pc) &&
13521         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13522       EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13523                  rm.GetCode() | (ra.GetCode() << 12));
13524       AdvanceIT();
13525       return;
13526     }
13527   } else {
13528     // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
13529     if (cond.IsNotNever() && !ra.Is(pc) &&
13530         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13531       EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13532               rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
13533       return;
13534     }
13535   }
13536   Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
13537 }
13538 
usat(Condition cond,Register rd,uint32_t imm,const Operand & operand)13539 void Assembler::usat(Condition cond,
13540                      Register rd,
13541                      uint32_t imm,
13542                      const Operand& operand) {
13543   VIXL_ASSERT(AllowAssembler());
13544   CheckIT(cond);
13545   if (operand.IsImmediateShiftedRegister()) {
13546     Register rn = operand.GetBaseRegister();
13547     Shift shift = operand.GetShift();
13548     uint32_t amount = operand.GetShiftAmount();
13549     if (IsUsingT32()) {
13550       // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
13551       if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31) &&
13552           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13553         EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13554                    (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13555                    ((amount & 0x1c) << 10));
13556         AdvanceIT();
13557         return;
13558       }
13559       // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
13560       if ((imm <= 31) && shift.IsLSL() && (amount <= 31) &&
13561           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13562         EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
13563                    (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13564                    ((amount & 0x1c) << 10));
13565         AdvanceIT();
13566         return;
13567       }
13568     } else {
13569       // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
13570       if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
13571           cond.IsNotNever() &&
13572           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13573         uint32_t amount_ = amount % 32;
13574         EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
13575                 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13576                 (amount_ << 7));
13577         return;
13578       }
13579       // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
13580       if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever() &&
13581           ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13582         EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
13583                 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13584                 (amount << 7));
13585         return;
13586       }
13587     }
13588   }
13589   Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
13590 }
13591 
usat16(Condition cond,Register rd,uint32_t imm,Register rn)13592 void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
13593   VIXL_ASSERT(AllowAssembler());
13594   CheckIT(cond);
13595   if (IsUsingT32()) {
13596     // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
13597     if ((imm <= 15) && ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13598       EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13599                  (rn.GetCode() << 16));
13600       AdvanceIT();
13601       return;
13602     }
13603   } else {
13604     // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
13605     if ((imm <= 15) && cond.IsNotNever() &&
13606         ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13607       EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13608               (imm << 16) | rn.GetCode());
13609       return;
13610     }
13611   }
13612   Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
13613 }
13614 
usax(Condition cond,Register rd,Register rn,Register rm)13615 void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
13616   VIXL_ASSERT(AllowAssembler());
13617   CheckIT(cond);
13618   if (IsUsingT32()) {
13619     // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13620     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13621       EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13622                  rm.GetCode());
13623       AdvanceIT();
13624       return;
13625     }
13626   } else {
13627     // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13628     if (cond.IsNotNever() &&
13629         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13630       EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13631               (rn.GetCode() << 16) | rm.GetCode());
13632       return;
13633     }
13634   }
13635   Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
13636 }
13637 
usub16(Condition cond,Register rd,Register rn,Register rm)13638 void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
13639   VIXL_ASSERT(AllowAssembler());
13640   CheckIT(cond);
13641   if (IsUsingT32()) {
13642     // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13643     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13644       EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13645                  rm.GetCode());
13646       AdvanceIT();
13647       return;
13648     }
13649   } else {
13650     // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13651     if (cond.IsNotNever() &&
13652         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13653       EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13654               (rn.GetCode() << 16) | rm.GetCode());
13655       return;
13656     }
13657   }
13658   Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
13659 }
13660 
usub8(Condition cond,Register rd,Register rn,Register rm)13661 void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
13662   VIXL_ASSERT(AllowAssembler());
13663   CheckIT(cond);
13664   if (IsUsingT32()) {
13665     // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13666     if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13667       EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13668                  rm.GetCode());
13669       AdvanceIT();
13670       return;
13671     }
13672   } else {
13673     // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13674     if (cond.IsNotNever() &&
13675         ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13676       EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13677               (rn.GetCode() << 16) | rm.GetCode());
13678       return;
13679     }
13680   }
13681   Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
13682 }
13683 
uxtab(Condition cond,Register rd,Register rn,const Operand & operand)13684 void Assembler::uxtab(Condition cond,
13685                       Register rd,
13686                       Register rn,
13687                       const Operand& operand) {
13688   VIXL_ASSERT(AllowAssembler());
13689   CheckIT(cond);
13690   if (operand.IsImmediateShiftedRegister()) {
13691     Register rm = operand.GetBaseRegister();
13692     Shift shift = operand.GetShift();
13693     uint32_t amount = operand.GetShiftAmount();
13694     if (IsUsingT32()) {
13695       // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13696       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13697           ((amount % 8) == 0) && !rn.Is(pc) &&
13698           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13699         uint32_t amount_ = amount / 8;
13700         EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13701                    rm.GetCode() | (amount_ << 4));
13702         AdvanceIT();
13703         return;
13704       }
13705     } else {
13706       // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13707       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13708           ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13709           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13710         uint32_t amount_ = amount / 8;
13711         EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
13712                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13713                 (amount_ << 10));
13714         return;
13715       }
13716     }
13717   }
13718   Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
13719 }
13720 
uxtab16(Condition cond,Register rd,Register rn,const Operand & operand)13721 void Assembler::uxtab16(Condition cond,
13722                         Register rd,
13723                         Register rn,
13724                         const Operand& operand) {
13725   VIXL_ASSERT(AllowAssembler());
13726   CheckIT(cond);
13727   if (operand.IsImmediateShiftedRegister()) {
13728     Register rm = operand.GetBaseRegister();
13729     Shift shift = operand.GetShift();
13730     uint32_t amount = operand.GetShiftAmount();
13731     if (IsUsingT32()) {
13732       // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13733       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13734           ((amount % 8) == 0) && !rn.Is(pc) &&
13735           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13736         uint32_t amount_ = amount / 8;
13737         EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13738                    rm.GetCode() | (amount_ << 4));
13739         AdvanceIT();
13740         return;
13741       }
13742     } else {
13743       // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13744       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13745           ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13746           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13747         uint32_t amount_ = amount / 8;
13748         EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
13749                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13750                 (amount_ << 10));
13751         return;
13752       }
13753     }
13754   }
13755   Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
13756 }
13757 
uxtah(Condition cond,Register rd,Register rn,const Operand & operand)13758 void Assembler::uxtah(Condition cond,
13759                       Register rd,
13760                       Register rn,
13761                       const Operand& operand) {
13762   VIXL_ASSERT(AllowAssembler());
13763   CheckIT(cond);
13764   if (operand.IsImmediateShiftedRegister()) {
13765     Register rm = operand.GetBaseRegister();
13766     Shift shift = operand.GetShift();
13767     uint32_t amount = operand.GetShiftAmount();
13768     if (IsUsingT32()) {
13769       // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13770       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13771           ((amount % 8) == 0) && !rn.Is(pc) &&
13772           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13773         uint32_t amount_ = amount / 8;
13774         EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13775                    rm.GetCode() | (amount_ << 4));
13776         AdvanceIT();
13777         return;
13778       }
13779     } else {
13780       // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13781       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13782           ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13783           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13784         uint32_t amount_ = amount / 8;
13785         EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
13786                 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13787                 (amount_ << 10));
13788         return;
13789       }
13790     }
13791   }
13792   Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
13793 }
13794 
uxtb(Condition cond,EncodingSize size,Register rd,const Operand & operand)13795 void Assembler::uxtb(Condition cond,
13796                      EncodingSize size,
13797                      Register rd,
13798                      const Operand& operand) {
13799   VIXL_ASSERT(AllowAssembler());
13800   CheckIT(cond);
13801   if (operand.IsImmediateShiftedRegister()) {
13802     Register rm = operand.GetBaseRegister();
13803     if (operand.IsPlainRegister()) {
13804       if (IsUsingT32()) {
13805         // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
13806         if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13807           EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
13808           AdvanceIT();
13809           return;
13810         }
13811       }
13812     }
13813     Shift shift = operand.GetShift();
13814     uint32_t amount = operand.GetShiftAmount();
13815     if (IsUsingT32()) {
13816       // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13817       if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
13818           (amount <= 24) && ((amount % 8) == 0) &&
13819           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13820         uint32_t amount_ = amount / 8;
13821         EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13822                    (amount_ << 4));
13823         AdvanceIT();
13824         return;
13825       }
13826     } else {
13827       // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13828       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13829           ((amount % 8) == 0) && cond.IsNotNever() &&
13830           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13831         uint32_t amount_ = amount / 8;
13832         EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
13833                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13834         return;
13835       }
13836     }
13837   }
13838   Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
13839 }
13840 
uxtb16(Condition cond,Register rd,const Operand & operand)13841 void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
13842   VIXL_ASSERT(AllowAssembler());
13843   CheckIT(cond);
13844   if (operand.IsImmediateShiftedRegister()) {
13845     Register rm = operand.GetBaseRegister();
13846     Shift shift = operand.GetShift();
13847     uint32_t amount = operand.GetShiftAmount();
13848     if (IsUsingT32()) {
13849       // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
13850       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13851           ((amount % 8) == 0) &&
13852           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13853         uint32_t amount_ = amount / 8;
13854         EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13855                    (amount_ << 4));
13856         AdvanceIT();
13857         return;
13858       }
13859     } else {
13860       // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13861       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13862           ((amount % 8) == 0) && cond.IsNotNever() &&
13863           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13864         uint32_t amount_ = amount / 8;
13865         EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
13866                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13867         return;
13868       }
13869     }
13870   }
13871   Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
13872 }
13873 
uxth(Condition cond,EncodingSize size,Register rd,const Operand & operand)13874 void Assembler::uxth(Condition cond,
13875                      EncodingSize size,
13876                      Register rd,
13877                      const Operand& operand) {
13878   VIXL_ASSERT(AllowAssembler());
13879   CheckIT(cond);
13880   if (operand.IsImmediateShiftedRegister()) {
13881     Register rm = operand.GetBaseRegister();
13882     if (operand.IsPlainRegister()) {
13883       if (IsUsingT32()) {
13884         // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
13885         if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13886           EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
13887           AdvanceIT();
13888           return;
13889         }
13890       }
13891     }
13892     Shift shift = operand.GetShift();
13893     uint32_t amount = operand.GetShiftAmount();
13894     if (IsUsingT32()) {
13895       // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13896       if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
13897           (amount <= 24) && ((amount % 8) == 0) &&
13898           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13899         uint32_t amount_ = amount / 8;
13900         EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13901                    (amount_ << 4));
13902         AdvanceIT();
13903         return;
13904       }
13905     } else {
13906       // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13907       if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13908           ((amount % 8) == 0) && cond.IsNotNever() &&
13909           ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13910         uint32_t amount_ = amount / 8;
13911         EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
13912                 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13913         return;
13914       }
13915     }
13916   }
13917   Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
13918 }
13919 
vaba(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)13920 void Assembler::vaba(
13921     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13922   VIXL_ASSERT(AllowAssembler());
13923   CheckIT(cond);
13924   Dt_U_size_1 encoded_dt(dt);
13925   if (IsUsingT32()) {
13926     // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
13927     if (encoded_dt.IsValid()) {
13928       if (cond.Is(al) || AllowStronglyDiscouraged()) {
13929         EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13930                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13931                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13932         AdvanceIT();
13933         return;
13934       }
13935     }
13936   } else {
13937     // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
13938     if (encoded_dt.IsValid()) {
13939       if (cond.Is(al)) {
13940         EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13941                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13942                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13943         return;
13944       }
13945     }
13946   }
13947   Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13948 }
13949 
vaba(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)13950 void Assembler::vaba(
13951     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13952   VIXL_ASSERT(AllowAssembler());
13953   CheckIT(cond);
13954   Dt_U_size_1 encoded_dt(dt);
13955   if (IsUsingT32()) {
13956     // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
13957     if (encoded_dt.IsValid()) {
13958       if (cond.Is(al) || AllowStronglyDiscouraged()) {
13959         EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13960                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13961                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13962         AdvanceIT();
13963         return;
13964       }
13965     }
13966   } else {
13967     // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
13968     if (encoded_dt.IsValid()) {
13969       if (cond.Is(al)) {
13970         EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13971                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13972                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13973         return;
13974       }
13975     }
13976   }
13977   Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13978 }
13979 
vabal(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)13980 void Assembler::vabal(
13981     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
13982   VIXL_ASSERT(AllowAssembler());
13983   CheckIT(cond);
13984   Dt_U_size_1 encoded_dt(dt);
13985   if (IsUsingT32()) {
13986     // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13987     if (encoded_dt.IsValid()) {
13988       if (cond.Is(al) || AllowStronglyDiscouraged()) {
13989         EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13990                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13991                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13992         AdvanceIT();
13993         return;
13994       }
13995     }
13996   } else {
13997     // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13998     if (encoded_dt.IsValid()) {
13999       if (cond.Is(al)) {
14000         EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14001                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14002                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14003         return;
14004       }
14005     }
14006   }
14007   Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
14008 }
14009 
vabd(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14010 void Assembler::vabd(
14011     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14012   VIXL_ASSERT(AllowAssembler());
14013   CheckIT(cond);
14014   Dt_U_size_1 encoded_dt(dt);
14015   if (IsUsingT32()) {
14016     // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14017     if (dt.Is(F32)) {
14018       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14019         EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14020                    rm.Encode(5, 0));
14021         AdvanceIT();
14022         return;
14023       }
14024     }
14025     // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14026     if (encoded_dt.IsValid()) {
14027       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14028         EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14029                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14030                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14031         AdvanceIT();
14032         return;
14033       }
14034     }
14035   } else {
14036     // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14037     if (dt.Is(F32)) {
14038       if (cond.Is(al)) {
14039         EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14040                 rm.Encode(5, 0));
14041         return;
14042       }
14043     }
14044     // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14045     if (encoded_dt.IsValid()) {
14046       if (cond.Is(al)) {
14047         EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14048                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14049                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14050         return;
14051       }
14052     }
14053   }
14054   Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14055 }
14056 
vabd(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14057 void Assembler::vabd(
14058     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14059   VIXL_ASSERT(AllowAssembler());
14060   CheckIT(cond);
14061   Dt_U_size_1 encoded_dt(dt);
14062   if (IsUsingT32()) {
14063     // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14064     if (dt.Is(F32)) {
14065       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14066         EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14067                    rm.Encode(5, 0));
14068         AdvanceIT();
14069         return;
14070       }
14071     }
14072     // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14073     if (encoded_dt.IsValid()) {
14074       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14075         EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14076                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14077                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14078         AdvanceIT();
14079         return;
14080       }
14081     }
14082   } else {
14083     // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14084     if (dt.Is(F32)) {
14085       if (cond.Is(al)) {
14086         EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14087                 rm.Encode(5, 0));
14088         return;
14089       }
14090     }
14091     // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14092     if (encoded_dt.IsValid()) {
14093       if (cond.Is(al)) {
14094         EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14095                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14096                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14097         return;
14098       }
14099     }
14100   }
14101   Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14102 }
14103 
vabdl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)14104 void Assembler::vabdl(
14105     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
14106   VIXL_ASSERT(AllowAssembler());
14107   CheckIT(cond);
14108   Dt_U_size_1 encoded_dt(dt);
14109   if (IsUsingT32()) {
14110     // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14111     if (encoded_dt.IsValid()) {
14112       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14113         EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14114                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14115                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14116         AdvanceIT();
14117         return;
14118       }
14119     }
14120   } else {
14121     // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14122     if (encoded_dt.IsValid()) {
14123       if (cond.Is(al)) {
14124         EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14125                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14126                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14127         return;
14128       }
14129     }
14130   }
14131   Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
14132 }
14133 
vabs(Condition cond,DataType dt,DRegister rd,DRegister rm)14134 void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14135   VIXL_ASSERT(AllowAssembler());
14136   CheckIT(cond);
14137   Dt_F_size_1 encoded_dt(dt);
14138   if (IsUsingT32()) {
14139     // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14140     if (encoded_dt.IsValid()) {
14141       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14142         EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14143                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14144                    rd.Encode(22, 12) | rm.Encode(5, 0));
14145         AdvanceIT();
14146         return;
14147       }
14148     }
14149     // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
14150     if (dt.Is(F64)) {
14151       EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14152       AdvanceIT();
14153       return;
14154     }
14155   } else {
14156     // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14157     if (encoded_dt.IsValid()) {
14158       if (cond.Is(al)) {
14159         EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14160                 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14161                 rd.Encode(22, 12) | rm.Encode(5, 0));
14162         return;
14163       }
14164     }
14165     // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
14166     if (dt.Is(F64) && cond.IsNotNever()) {
14167       EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14168               rm.Encode(5, 0));
14169       return;
14170     }
14171   }
14172   Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14173 }
14174 
vabs(Condition cond,DataType dt,QRegister rd,QRegister rm)14175 void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
14176   VIXL_ASSERT(AllowAssembler());
14177   CheckIT(cond);
14178   Dt_F_size_1 encoded_dt(dt);
14179   if (IsUsingT32()) {
14180     // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14181     if (encoded_dt.IsValid()) {
14182       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14183         EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14184                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14185                    rd.Encode(22, 12) | rm.Encode(5, 0));
14186         AdvanceIT();
14187         return;
14188       }
14189     }
14190   } else {
14191     // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14192     if (encoded_dt.IsValid()) {
14193       if (cond.Is(al)) {
14194         EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14195                 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14196                 rd.Encode(22, 12) | rm.Encode(5, 0));
14197         return;
14198       }
14199     }
14200   }
14201   Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14202 }
14203 
vabs(Condition cond,DataType dt,SRegister rd,SRegister rm)14204 void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
14205   VIXL_ASSERT(AllowAssembler());
14206   CheckIT(cond);
14207   if (IsUsingT32()) {
14208     // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
14209     if (dt.Is(F32)) {
14210       EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14211       AdvanceIT();
14212       return;
14213     }
14214   } else {
14215     // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
14216     if (dt.Is(F32) && cond.IsNotNever()) {
14217       EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14218               rm.Encode(5, 0));
14219       return;
14220     }
14221   }
14222   Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14223 }
14224 
vacge(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14225 void Assembler::vacge(
14226     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14227   VIXL_ASSERT(AllowAssembler());
14228   CheckIT(cond);
14229   if (IsUsingT32()) {
14230     // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14231     if (dt.Is(F32)) {
14232       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14233         EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14234                    rm.Encode(5, 0));
14235         AdvanceIT();
14236         return;
14237       }
14238     }
14239   } else {
14240     // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14241     if (dt.Is(F32)) {
14242       if (cond.Is(al)) {
14243         EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14244                 rm.Encode(5, 0));
14245         return;
14246       }
14247     }
14248   }
14249   Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14250 }
14251 
vacge(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14252 void Assembler::vacge(
14253     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14254   VIXL_ASSERT(AllowAssembler());
14255   CheckIT(cond);
14256   if (IsUsingT32()) {
14257     // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14258     if (dt.Is(F32)) {
14259       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14260         EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14261                    rm.Encode(5, 0));
14262         AdvanceIT();
14263         return;
14264       }
14265     }
14266   } else {
14267     // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14268     if (dt.Is(F32)) {
14269       if (cond.Is(al)) {
14270         EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14271                 rm.Encode(5, 0));
14272         return;
14273       }
14274     }
14275   }
14276   Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14277 }
14278 
vacgt(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14279 void Assembler::vacgt(
14280     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14281   VIXL_ASSERT(AllowAssembler());
14282   CheckIT(cond);
14283   if (IsUsingT32()) {
14284     // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14285     if (dt.Is(F32)) {
14286       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14287         EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14288                    rm.Encode(5, 0));
14289         AdvanceIT();
14290         return;
14291       }
14292     }
14293   } else {
14294     // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14295     if (dt.Is(F32)) {
14296       if (cond.Is(al)) {
14297         EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14298                 rm.Encode(5, 0));
14299         return;
14300       }
14301     }
14302   }
14303   Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14304 }
14305 
vacgt(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14306 void Assembler::vacgt(
14307     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14308   VIXL_ASSERT(AllowAssembler());
14309   CheckIT(cond);
14310   if (IsUsingT32()) {
14311     // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14312     if (dt.Is(F32)) {
14313       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14314         EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14315                    rm.Encode(5, 0));
14316         AdvanceIT();
14317         return;
14318       }
14319     }
14320   } else {
14321     // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14322     if (dt.Is(F32)) {
14323       if (cond.Is(al)) {
14324         EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14325                 rm.Encode(5, 0));
14326         return;
14327       }
14328     }
14329   }
14330   Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14331 }
14332 
vacle(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14333 void Assembler::vacle(
14334     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14335   VIXL_ASSERT(AllowAssembler());
14336   CheckIT(cond);
14337   if (IsUsingT32()) {
14338     // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14339     if (dt.Is(F32)) {
14340       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14341         EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14342                    rm.Encode(5, 0));
14343         AdvanceIT();
14344         return;
14345       }
14346     }
14347   } else {
14348     // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14349     if (dt.Is(F32)) {
14350       if (cond.Is(al)) {
14351         EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14352                 rm.Encode(5, 0));
14353         return;
14354       }
14355     }
14356   }
14357   Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14358 }
14359 
vacle(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14360 void Assembler::vacle(
14361     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14362   VIXL_ASSERT(AllowAssembler());
14363   CheckIT(cond);
14364   if (IsUsingT32()) {
14365     // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14366     if (dt.Is(F32)) {
14367       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14368         EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14369                    rm.Encode(5, 0));
14370         AdvanceIT();
14371         return;
14372       }
14373     }
14374   } else {
14375     // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14376     if (dt.Is(F32)) {
14377       if (cond.Is(al)) {
14378         EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14379                 rm.Encode(5, 0));
14380         return;
14381       }
14382     }
14383   }
14384   Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14385 }
14386 
vaclt(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14387 void Assembler::vaclt(
14388     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14389   VIXL_ASSERT(AllowAssembler());
14390   CheckIT(cond);
14391   if (IsUsingT32()) {
14392     // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14393     if (dt.Is(F32)) {
14394       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14395         EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14396                    rm.Encode(5, 0));
14397         AdvanceIT();
14398         return;
14399       }
14400     }
14401   } else {
14402     // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14403     if (dt.Is(F32)) {
14404       if (cond.Is(al)) {
14405         EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14406                 rm.Encode(5, 0));
14407         return;
14408       }
14409     }
14410   }
14411   Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14412 }
14413 
vaclt(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14414 void Assembler::vaclt(
14415     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14416   VIXL_ASSERT(AllowAssembler());
14417   CheckIT(cond);
14418   if (IsUsingT32()) {
14419     // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14420     if (dt.Is(F32)) {
14421       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14422         EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14423                    rm.Encode(5, 0));
14424         AdvanceIT();
14425         return;
14426       }
14427     }
14428   } else {
14429     // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14430     if (dt.Is(F32)) {
14431       if (cond.Is(al)) {
14432         EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14433                 rm.Encode(5, 0));
14434         return;
14435       }
14436     }
14437   }
14438   Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14439 }
14440 
vadd(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14441 void Assembler::vadd(
14442     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14443   VIXL_ASSERT(AllowAssembler());
14444   CheckIT(cond);
14445   Dt_size_2 encoded_dt(dt);
14446   if (IsUsingT32()) {
14447     // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14448     if (dt.Is(F32)) {
14449       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14450         EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14451                    rm.Encode(5, 0));
14452         AdvanceIT();
14453         return;
14454       }
14455     }
14456     // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
14457     if (dt.Is(F64)) {
14458       EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14459                  rm.Encode(5, 0));
14460       AdvanceIT();
14461       return;
14462     }
14463     // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14464     if (encoded_dt.IsValid()) {
14465       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14466         EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
14467                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14468         AdvanceIT();
14469         return;
14470       }
14471     }
14472   } else {
14473     // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14474     if (dt.Is(F32)) {
14475       if (cond.Is(al)) {
14476         EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14477                 rm.Encode(5, 0));
14478         return;
14479       }
14480     }
14481     // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
14482     if (dt.Is(F64) && cond.IsNotNever()) {
14483       EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14484               rn.Encode(7, 16) | rm.Encode(5, 0));
14485       return;
14486     }
14487     // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14488     if (encoded_dt.IsValid()) {
14489       if (cond.Is(al)) {
14490         EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
14491                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14492         return;
14493       }
14494     }
14495   }
14496   Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14497 }
14498 
vadd(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14499 void Assembler::vadd(
14500     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14501   VIXL_ASSERT(AllowAssembler());
14502   CheckIT(cond);
14503   Dt_size_2 encoded_dt(dt);
14504   if (IsUsingT32()) {
14505     // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14506     if (dt.Is(F32)) {
14507       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14508         EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14509                    rm.Encode(5, 0));
14510         AdvanceIT();
14511         return;
14512       }
14513     }
14514     // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14515     if (encoded_dt.IsValid()) {
14516       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14517         EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
14518                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14519         AdvanceIT();
14520         return;
14521       }
14522     }
14523   } else {
14524     // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14525     if (dt.Is(F32)) {
14526       if (cond.Is(al)) {
14527         EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14528                 rm.Encode(5, 0));
14529         return;
14530       }
14531     }
14532     // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14533     if (encoded_dt.IsValid()) {
14534       if (cond.Is(al)) {
14535         EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
14536                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14537         return;
14538       }
14539     }
14540   }
14541   Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14542 }
14543 
vadd(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)14544 void Assembler::vadd(
14545     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
14546   VIXL_ASSERT(AllowAssembler());
14547   CheckIT(cond);
14548   if (IsUsingT32()) {
14549     // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
14550     if (dt.Is(F32)) {
14551       EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14552                  rm.Encode(5, 0));
14553       AdvanceIT();
14554       return;
14555     }
14556   } else {
14557     // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
14558     if (dt.Is(F32) && cond.IsNotNever()) {
14559       EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14560               rn.Encode(7, 16) | rm.Encode(5, 0));
14561       return;
14562     }
14563   }
14564   Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14565 }
14566 
vaddhn(Condition cond,DataType dt,DRegister rd,QRegister rn,QRegister rm)14567 void Assembler::vaddhn(
14568     Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
14569   VIXL_ASSERT(AllowAssembler());
14570   CheckIT(cond);
14571   Dt_size_3 encoded_dt(dt);
14572   if (IsUsingT32()) {
14573     // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
14574     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14575       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14576         EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
14577                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14578         AdvanceIT();
14579         return;
14580       }
14581     }
14582   } else {
14583     // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
14584     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14585       if (cond.Is(al)) {
14586         EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
14587                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14588         return;
14589       }
14590     }
14591   }
14592   Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
14593 }
14594 
vaddl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)14595 void Assembler::vaddl(
14596     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
14597   VIXL_ASSERT(AllowAssembler());
14598   CheckIT(cond);
14599   Dt_U_size_1 encoded_dt(dt);
14600   if (IsUsingT32()) {
14601     // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14602     if (encoded_dt.IsValid()) {
14603       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14604         EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14605                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14606                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14607         AdvanceIT();
14608         return;
14609       }
14610     }
14611   } else {
14612     // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14613     if (encoded_dt.IsValid()) {
14614       if (cond.Is(al)) {
14615         EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14616                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14617                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14618         return;
14619       }
14620     }
14621   }
14622   Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
14623 }
14624 
vaddw(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegister rm)14625 void Assembler::vaddw(
14626     Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
14627   VIXL_ASSERT(AllowAssembler());
14628   CheckIT(cond);
14629   Dt_U_size_1 encoded_dt(dt);
14630   if (IsUsingT32()) {
14631     // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
14632     if (encoded_dt.IsValid()) {
14633       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14634         EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14635                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14636                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14637         AdvanceIT();
14638         return;
14639       }
14640     }
14641   } else {
14642     // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
14643     if (encoded_dt.IsValid()) {
14644       if (cond.Is(al)) {
14645         EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14646                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14647                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14648         return;
14649       }
14650     }
14651   }
14652   Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
14653 }
14654 
vand(Condition cond,DataType dt,DRegister rd,DRegister rn,const DOperand & operand)14655 void Assembler::vand(Condition cond,
14656                      DataType dt,
14657                      DRegister rd,
14658                      DRegister rn,
14659                      const DOperand& operand) {
14660   VIXL_ASSERT(AllowAssembler());
14661   CheckIT(cond);
14662   if (operand.IsImmediate()) {
14663     ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
14664     if (IsUsingT32()) {
14665       // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14666       if (encoded_dt.IsValid() && rd.Is(rn)) {
14667         if (cond.Is(al) || AllowStronglyDiscouraged()) {
14668           EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14669                      rd.Encode(22, 12) |
14670                      (encoded_dt.GetEncodedImmediate() & 0xf) |
14671                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14672                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14673           AdvanceIT();
14674           return;
14675         }
14676       }
14677     } else {
14678       // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14679       if (encoded_dt.IsValid() && rd.Is(rn)) {
14680         if (cond.Is(al)) {
14681           EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14682                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14683                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14684                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14685           return;
14686         }
14687       }
14688     }
14689   }
14690   if (operand.IsRegister()) {
14691     DRegister rm = operand.GetRegister();
14692     USE(dt);
14693     if (IsUsingT32()) {
14694       // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14695       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14696         EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14697                    rm.Encode(5, 0));
14698         AdvanceIT();
14699         return;
14700       }
14701     } else {
14702       // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14703       if (cond.Is(al)) {
14704         EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14705                 rm.Encode(5, 0));
14706         return;
14707       }
14708     }
14709   }
14710   Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14711 }
14712 
vand(Condition cond,DataType dt,QRegister rd,QRegister rn,const QOperand & operand)14713 void Assembler::vand(Condition cond,
14714                      DataType dt,
14715                      QRegister rd,
14716                      QRegister rn,
14717                      const QOperand& operand) {
14718   VIXL_ASSERT(AllowAssembler());
14719   CheckIT(cond);
14720   if (operand.IsImmediate()) {
14721     ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
14722     if (IsUsingT32()) {
14723       // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14724       if (encoded_dt.IsValid() && rd.Is(rn)) {
14725         if (cond.Is(al) || AllowStronglyDiscouraged()) {
14726           EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14727                      rd.Encode(22, 12) |
14728                      (encoded_dt.GetEncodedImmediate() & 0xf) |
14729                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14730                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14731           AdvanceIT();
14732           return;
14733         }
14734       }
14735     } else {
14736       // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14737       if (encoded_dt.IsValid() && rd.Is(rn)) {
14738         if (cond.Is(al)) {
14739           EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14740                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14741                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14742                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14743           return;
14744         }
14745       }
14746     }
14747   }
14748   if (operand.IsRegister()) {
14749     QRegister rm = operand.GetRegister();
14750     USE(dt);
14751     if (IsUsingT32()) {
14752       // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14753       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14754         EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14755                    rm.Encode(5, 0));
14756         AdvanceIT();
14757         return;
14758       }
14759     } else {
14760       // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14761       if (cond.Is(al)) {
14762         EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14763                 rm.Encode(5, 0));
14764         return;
14765       }
14766     }
14767   }
14768   Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14769 }
14770 
vbic(Condition cond,DataType dt,DRegister rd,DRegister rn,const DOperand & operand)14771 void Assembler::vbic(Condition cond,
14772                      DataType dt,
14773                      DRegister rd,
14774                      DRegister rn,
14775                      const DOperand& operand) {
14776   VIXL_ASSERT(AllowAssembler());
14777   CheckIT(cond);
14778   if (operand.IsImmediate()) {
14779     ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
14780     if (IsUsingT32()) {
14781       // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14782       if (encoded_dt.IsValid() && rd.Is(rn)) {
14783         if (cond.Is(al) || AllowStronglyDiscouraged()) {
14784           EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14785                      rd.Encode(22, 12) |
14786                      (encoded_dt.GetEncodedImmediate() & 0xf) |
14787                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14788                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14789           AdvanceIT();
14790           return;
14791         }
14792       }
14793     } else {
14794       // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14795       if (encoded_dt.IsValid() && rd.Is(rn)) {
14796         if (cond.Is(al)) {
14797           EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14798                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14799                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14800                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14801           return;
14802         }
14803       }
14804     }
14805   }
14806   if (operand.IsRegister()) {
14807     DRegister rm = operand.GetRegister();
14808     USE(dt);
14809     if (IsUsingT32()) {
14810       // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14811       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14812         EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14813                    rm.Encode(5, 0));
14814         AdvanceIT();
14815         return;
14816       }
14817     } else {
14818       // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14819       if (cond.Is(al)) {
14820         EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14821                 rm.Encode(5, 0));
14822         return;
14823       }
14824     }
14825   }
14826   Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14827 }
14828 
vbic(Condition cond,DataType dt,QRegister rd,QRegister rn,const QOperand & operand)14829 void Assembler::vbic(Condition cond,
14830                      DataType dt,
14831                      QRegister rd,
14832                      QRegister rn,
14833                      const QOperand& operand) {
14834   VIXL_ASSERT(AllowAssembler());
14835   CheckIT(cond);
14836   if (operand.IsImmediate()) {
14837     ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
14838     if (IsUsingT32()) {
14839       // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14840       if (encoded_dt.IsValid() && rd.Is(rn)) {
14841         if (cond.Is(al) || AllowStronglyDiscouraged()) {
14842           EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14843                      rd.Encode(22, 12) |
14844                      (encoded_dt.GetEncodedImmediate() & 0xf) |
14845                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14846                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14847           AdvanceIT();
14848           return;
14849         }
14850       }
14851     } else {
14852       // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14853       if (encoded_dt.IsValid() && rd.Is(rn)) {
14854         if (cond.Is(al)) {
14855           EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14856                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14857                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14858                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14859           return;
14860         }
14861       }
14862     }
14863   }
14864   if (operand.IsRegister()) {
14865     QRegister rm = operand.GetRegister();
14866     USE(dt);
14867     if (IsUsingT32()) {
14868       // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14869       if (cond.Is(al) || AllowStronglyDiscouraged()) {
14870         EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14871                    rm.Encode(5, 0));
14872         AdvanceIT();
14873         return;
14874       }
14875     } else {
14876       // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14877       if (cond.Is(al)) {
14878         EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14879                 rm.Encode(5, 0));
14880         return;
14881       }
14882     }
14883   }
14884   Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14885 }
14886 
vbif(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14887 void Assembler::vbif(
14888     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14889   VIXL_ASSERT(AllowAssembler());
14890   CheckIT(cond);
14891   USE(dt);
14892   if (IsUsingT32()) {
14893     // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14894     if (cond.Is(al) || AllowStronglyDiscouraged()) {
14895       EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14896                  rm.Encode(5, 0));
14897       AdvanceIT();
14898       return;
14899     }
14900   } else {
14901     // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14902     if (cond.Is(al)) {
14903       EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14904               rm.Encode(5, 0));
14905       return;
14906     }
14907   }
14908   Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14909 }
14910 
vbif(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14911 void Assembler::vbif(
14912     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14913   VIXL_ASSERT(AllowAssembler());
14914   CheckIT(cond);
14915   USE(dt);
14916   if (IsUsingT32()) {
14917     // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14918     if (cond.Is(al) || AllowStronglyDiscouraged()) {
14919       EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14920                  rm.Encode(5, 0));
14921       AdvanceIT();
14922       return;
14923     }
14924   } else {
14925     // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14926     if (cond.Is(al)) {
14927       EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14928               rm.Encode(5, 0));
14929       return;
14930     }
14931   }
14932   Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14933 }
14934 
vbit(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14935 void Assembler::vbit(
14936     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14937   VIXL_ASSERT(AllowAssembler());
14938   CheckIT(cond);
14939   USE(dt);
14940   if (IsUsingT32()) {
14941     // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14942     if (cond.Is(al) || AllowStronglyDiscouraged()) {
14943       EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14944                  rm.Encode(5, 0));
14945       AdvanceIT();
14946       return;
14947     }
14948   } else {
14949     // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14950     if (cond.Is(al)) {
14951       EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14952               rm.Encode(5, 0));
14953       return;
14954     }
14955   }
14956   Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14957 }
14958 
vbit(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)14959 void Assembler::vbit(
14960     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14961   VIXL_ASSERT(AllowAssembler());
14962   CheckIT(cond);
14963   USE(dt);
14964   if (IsUsingT32()) {
14965     // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14966     if (cond.Is(al) || AllowStronglyDiscouraged()) {
14967       EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14968                  rm.Encode(5, 0));
14969       AdvanceIT();
14970       return;
14971     }
14972   } else {
14973     // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14974     if (cond.Is(al)) {
14975       EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14976               rm.Encode(5, 0));
14977       return;
14978     }
14979   }
14980   Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14981 }
14982 
vbsl(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)14983 void Assembler::vbsl(
14984     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14985   VIXL_ASSERT(AllowAssembler());
14986   CheckIT(cond);
14987   USE(dt);
14988   if (IsUsingT32()) {
14989     // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14990     if (cond.Is(al) || AllowStronglyDiscouraged()) {
14991       EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14992                  rm.Encode(5, 0));
14993       AdvanceIT();
14994       return;
14995     }
14996   } else {
14997     // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14998     if (cond.Is(al)) {
14999       EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15000               rm.Encode(5, 0));
15001       return;
15002     }
15003   }
15004   Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
15005 }
15006 
vbsl(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)15007 void Assembler::vbsl(
15008     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15009   VIXL_ASSERT(AllowAssembler());
15010   CheckIT(cond);
15011   USE(dt);
15012   if (IsUsingT32()) {
15013     // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
15014     if (cond.Is(al) || AllowStronglyDiscouraged()) {
15015       EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15016                  rm.Encode(5, 0));
15017       AdvanceIT();
15018       return;
15019     }
15020   } else {
15021     // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
15022     if (cond.Is(al)) {
15023       EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15024               rm.Encode(5, 0));
15025       return;
15026     }
15027   }
15028   Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
15029 }
15030 
vceq(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)15031 void Assembler::vceq(Condition cond,
15032                      DataType dt,
15033                      DRegister rd,
15034                      DRegister rm,
15035                      const DOperand& operand) {
15036   VIXL_ASSERT(AllowAssembler());
15037   CheckIT(cond);
15038   if (operand.IsImmediate()) {
15039     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15040       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15041       Dt_F_size_2 encoded_dt(dt);
15042       if (IsUsingT32()) {
15043         // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15044         if (encoded_dt.IsValid() && (imm == 0)) {
15045           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15046             EmitT32_32(0xffb10100U |
15047                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15048                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15049                        rd.Encode(22, 12) | rm.Encode(5, 0));
15050             AdvanceIT();
15051             return;
15052           }
15053         }
15054       } else {
15055         // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15056         if (encoded_dt.IsValid() && (imm == 0)) {
15057           if (cond.Is(al)) {
15058             EmitA32(0xf3b10100U |
15059                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15060                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15061                     rd.Encode(22, 12) | rm.Encode(5, 0));
15062             return;
15063           }
15064         }
15065       }
15066     }
15067   }
15068   Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15069 }
15070 
vceq(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)15071 void Assembler::vceq(Condition cond,
15072                      DataType dt,
15073                      QRegister rd,
15074                      QRegister rm,
15075                      const QOperand& operand) {
15076   VIXL_ASSERT(AllowAssembler());
15077   CheckIT(cond);
15078   if (operand.IsImmediate()) {
15079     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15080       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15081       Dt_F_size_2 encoded_dt(dt);
15082       if (IsUsingT32()) {
15083         // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15084         if (encoded_dt.IsValid() && (imm == 0)) {
15085           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15086             EmitT32_32(0xffb10140U |
15087                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15088                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15089                        rd.Encode(22, 12) | rm.Encode(5, 0));
15090             AdvanceIT();
15091             return;
15092           }
15093         }
15094       } else {
15095         // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15096         if (encoded_dt.IsValid() && (imm == 0)) {
15097           if (cond.Is(al)) {
15098             EmitA32(0xf3b10140U |
15099                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15100                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15101                     rd.Encode(22, 12) | rm.Encode(5, 0));
15102             return;
15103           }
15104         }
15105       }
15106     }
15107   }
15108   Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15109 }
15110 
vceq(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)15111 void Assembler::vceq(
15112     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15113   VIXL_ASSERT(AllowAssembler());
15114   CheckIT(cond);
15115   Dt_size_4 encoded_dt(dt);
15116   Dt_sz_1 encoded_dt_2(dt);
15117   if (IsUsingT32()) {
15118     // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15119     if (encoded_dt.IsValid()) {
15120       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15121         EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
15122                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15123         AdvanceIT();
15124         return;
15125       }
15126     }
15127     // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
15128     if (encoded_dt_2.IsValid()) {
15129       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15130         EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15131                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15132         AdvanceIT();
15133         return;
15134       }
15135     }
15136   } else {
15137     // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15138     if (encoded_dt.IsValid()) {
15139       if (cond.Is(al)) {
15140         EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
15141                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15142         return;
15143       }
15144     }
15145     // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
15146     if (encoded_dt_2.IsValid()) {
15147       if (cond.Is(al)) {
15148         EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15149                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15150         return;
15151       }
15152     }
15153   }
15154   Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15155 }
15156 
vceq(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)15157 void Assembler::vceq(
15158     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15159   VIXL_ASSERT(AllowAssembler());
15160   CheckIT(cond);
15161   Dt_size_4 encoded_dt(dt);
15162   Dt_sz_1 encoded_dt_2(dt);
15163   if (IsUsingT32()) {
15164     // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15165     if (encoded_dt.IsValid()) {
15166       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15167         EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
15168                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15169         AdvanceIT();
15170         return;
15171       }
15172     }
15173     // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
15174     if (encoded_dt_2.IsValid()) {
15175       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15176         EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15177                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15178         AdvanceIT();
15179         return;
15180       }
15181     }
15182   } else {
15183     // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15184     if (encoded_dt.IsValid()) {
15185       if (cond.Is(al)) {
15186         EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
15187                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15188         return;
15189       }
15190     }
15191     // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
15192     if (encoded_dt_2.IsValid()) {
15193       if (cond.Is(al)) {
15194         EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15195                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15196         return;
15197       }
15198     }
15199   }
15200   Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15201 }
15202 
vcge(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)15203 void Assembler::vcge(Condition cond,
15204                      DataType dt,
15205                      DRegister rd,
15206                      DRegister rm,
15207                      const DOperand& operand) {
15208   VIXL_ASSERT(AllowAssembler());
15209   CheckIT(cond);
15210   if (operand.IsImmediate()) {
15211     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15212       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15213       Dt_F_size_1 encoded_dt(dt);
15214       if (IsUsingT32()) {
15215         // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15216         if (encoded_dt.IsValid() && (imm == 0)) {
15217           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15218             EmitT32_32(0xffb10080U |
15219                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15220                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15221                        rd.Encode(22, 12) | rm.Encode(5, 0));
15222             AdvanceIT();
15223             return;
15224           }
15225         }
15226       } else {
15227         // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15228         if (encoded_dt.IsValid() && (imm == 0)) {
15229           if (cond.Is(al)) {
15230             EmitA32(0xf3b10080U |
15231                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15232                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15233                     rd.Encode(22, 12) | rm.Encode(5, 0));
15234             return;
15235           }
15236         }
15237       }
15238     }
15239   }
15240   Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15241 }
15242 
vcge(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)15243 void Assembler::vcge(Condition cond,
15244                      DataType dt,
15245                      QRegister rd,
15246                      QRegister rm,
15247                      const QOperand& operand) {
15248   VIXL_ASSERT(AllowAssembler());
15249   CheckIT(cond);
15250   if (operand.IsImmediate()) {
15251     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15252       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15253       Dt_F_size_1 encoded_dt(dt);
15254       if (IsUsingT32()) {
15255         // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15256         if (encoded_dt.IsValid() && (imm == 0)) {
15257           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15258             EmitT32_32(0xffb100c0U |
15259                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15260                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15261                        rd.Encode(22, 12) | rm.Encode(5, 0));
15262             AdvanceIT();
15263             return;
15264           }
15265         }
15266       } else {
15267         // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15268         if (encoded_dt.IsValid() && (imm == 0)) {
15269           if (cond.Is(al)) {
15270             EmitA32(0xf3b100c0U |
15271                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15272                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15273                     rd.Encode(22, 12) | rm.Encode(5, 0));
15274             return;
15275           }
15276         }
15277       }
15278     }
15279   }
15280   Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15281 }
15282 
vcge(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)15283 void Assembler::vcge(
15284     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15285   VIXL_ASSERT(AllowAssembler());
15286   CheckIT(cond);
15287   Dt_U_size_1 encoded_dt(dt);
15288   if (IsUsingT32()) {
15289     // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15290     if (encoded_dt.IsValid()) {
15291       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15292         EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15293                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15294                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15295         AdvanceIT();
15296         return;
15297       }
15298     }
15299     // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15300     if (dt.Is(F32)) {
15301       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15302         EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15303                    rm.Encode(5, 0));
15304         AdvanceIT();
15305         return;
15306       }
15307     }
15308   } else {
15309     // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15310     if (encoded_dt.IsValid()) {
15311       if (cond.Is(al)) {
15312         EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15313                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15314                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15315         return;
15316       }
15317     }
15318     // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15319     if (dt.Is(F32)) {
15320       if (cond.Is(al)) {
15321         EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15322                 rm.Encode(5, 0));
15323         return;
15324       }
15325     }
15326   }
15327   Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15328 }
15329 
vcge(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)15330 void Assembler::vcge(
15331     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15332   VIXL_ASSERT(AllowAssembler());
15333   CheckIT(cond);
15334   Dt_U_size_1 encoded_dt(dt);
15335   if (IsUsingT32()) {
15336     // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15337     if (encoded_dt.IsValid()) {
15338       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15339         EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15340                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15341                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15342         AdvanceIT();
15343         return;
15344       }
15345     }
15346     // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15347     if (dt.Is(F32)) {
15348       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15349         EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15350                    rm.Encode(5, 0));
15351         AdvanceIT();
15352         return;
15353       }
15354     }
15355   } else {
15356     // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15357     if (encoded_dt.IsValid()) {
15358       if (cond.Is(al)) {
15359         EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15360                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15361                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15362         return;
15363       }
15364     }
15365     // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15366     if (dt.Is(F32)) {
15367       if (cond.Is(al)) {
15368         EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15369                 rm.Encode(5, 0));
15370         return;
15371       }
15372     }
15373   }
15374   Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15375 }
15376 
vcgt(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)15377 void Assembler::vcgt(Condition cond,
15378                      DataType dt,
15379                      DRegister rd,
15380                      DRegister rm,
15381                      const DOperand& operand) {
15382   VIXL_ASSERT(AllowAssembler());
15383   CheckIT(cond);
15384   if (operand.IsImmediate()) {
15385     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15386       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15387       Dt_F_size_1 encoded_dt(dt);
15388       if (IsUsingT32()) {
15389         // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15390         if (encoded_dt.IsValid() && (imm == 0)) {
15391           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15392             EmitT32_32(0xffb10000U |
15393                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15394                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15395                        rd.Encode(22, 12) | rm.Encode(5, 0));
15396             AdvanceIT();
15397             return;
15398           }
15399         }
15400       } else {
15401         // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15402         if (encoded_dt.IsValid() && (imm == 0)) {
15403           if (cond.Is(al)) {
15404             EmitA32(0xf3b10000U |
15405                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15406                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15407                     rd.Encode(22, 12) | rm.Encode(5, 0));
15408             return;
15409           }
15410         }
15411       }
15412     }
15413   }
15414   Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15415 }
15416 
vcgt(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)15417 void Assembler::vcgt(Condition cond,
15418                      DataType dt,
15419                      QRegister rd,
15420                      QRegister rm,
15421                      const QOperand& operand) {
15422   VIXL_ASSERT(AllowAssembler());
15423   CheckIT(cond);
15424   if (operand.IsImmediate()) {
15425     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15426       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15427       Dt_F_size_1 encoded_dt(dt);
15428       if (IsUsingT32()) {
15429         // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15430         if (encoded_dt.IsValid() && (imm == 0)) {
15431           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15432             EmitT32_32(0xffb10040U |
15433                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15434                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15435                        rd.Encode(22, 12) | rm.Encode(5, 0));
15436             AdvanceIT();
15437             return;
15438           }
15439         }
15440       } else {
15441         // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15442         if (encoded_dt.IsValid() && (imm == 0)) {
15443           if (cond.Is(al)) {
15444             EmitA32(0xf3b10040U |
15445                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15446                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15447                     rd.Encode(22, 12) | rm.Encode(5, 0));
15448             return;
15449           }
15450         }
15451       }
15452     }
15453   }
15454   Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15455 }
15456 
vcgt(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)15457 void Assembler::vcgt(
15458     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15459   VIXL_ASSERT(AllowAssembler());
15460   CheckIT(cond);
15461   Dt_U_size_1 encoded_dt(dt);
15462   if (IsUsingT32()) {
15463     // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15464     if (encoded_dt.IsValid()) {
15465       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15466         EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15467                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15468                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15469         AdvanceIT();
15470         return;
15471       }
15472     }
15473     // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15474     if (dt.Is(F32)) {
15475       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15476         EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15477                    rm.Encode(5, 0));
15478         AdvanceIT();
15479         return;
15480       }
15481     }
15482   } else {
15483     // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15484     if (encoded_dt.IsValid()) {
15485       if (cond.Is(al)) {
15486         EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15487                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15488                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15489         return;
15490       }
15491     }
15492     // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15493     if (dt.Is(F32)) {
15494       if (cond.Is(al)) {
15495         EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15496                 rm.Encode(5, 0));
15497         return;
15498       }
15499     }
15500   }
15501   Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15502 }
15503 
vcgt(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)15504 void Assembler::vcgt(
15505     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15506   VIXL_ASSERT(AllowAssembler());
15507   CheckIT(cond);
15508   Dt_U_size_1 encoded_dt(dt);
15509   if (IsUsingT32()) {
15510     // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15511     if (encoded_dt.IsValid()) {
15512       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15513         EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15514                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15515                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15516         AdvanceIT();
15517         return;
15518       }
15519     }
15520     // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15521     if (dt.Is(F32)) {
15522       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15523         EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15524                    rm.Encode(5, 0));
15525         AdvanceIT();
15526         return;
15527       }
15528     }
15529   } else {
15530     // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15531     if (encoded_dt.IsValid()) {
15532       if (cond.Is(al)) {
15533         EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15534                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15535                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15536         return;
15537       }
15538     }
15539     // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15540     if (dt.Is(F32)) {
15541       if (cond.Is(al)) {
15542         EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15543                 rm.Encode(5, 0));
15544         return;
15545       }
15546     }
15547   }
15548   Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15549 }
15550 
vcle(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)15551 void Assembler::vcle(Condition cond,
15552                      DataType dt,
15553                      DRegister rd,
15554                      DRegister rm,
15555                      const DOperand& operand) {
15556   VIXL_ASSERT(AllowAssembler());
15557   CheckIT(cond);
15558   if (operand.IsImmediate()) {
15559     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15560       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15561       Dt_F_size_1 encoded_dt(dt);
15562       if (IsUsingT32()) {
15563         // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15564         if (encoded_dt.IsValid() && (imm == 0)) {
15565           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15566             EmitT32_32(0xffb10180U |
15567                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15568                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15569                        rd.Encode(22, 12) | rm.Encode(5, 0));
15570             AdvanceIT();
15571             return;
15572           }
15573         }
15574       } else {
15575         // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15576         if (encoded_dt.IsValid() && (imm == 0)) {
15577           if (cond.Is(al)) {
15578             EmitA32(0xf3b10180U |
15579                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15580                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15581                     rd.Encode(22, 12) | rm.Encode(5, 0));
15582             return;
15583           }
15584         }
15585       }
15586     }
15587   }
15588   Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15589 }
15590 
vcle(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)15591 void Assembler::vcle(Condition cond,
15592                      DataType dt,
15593                      QRegister rd,
15594                      QRegister rm,
15595                      const QOperand& operand) {
15596   VIXL_ASSERT(AllowAssembler());
15597   CheckIT(cond);
15598   if (operand.IsImmediate()) {
15599     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15600       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15601       Dt_F_size_1 encoded_dt(dt);
15602       if (IsUsingT32()) {
15603         // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15604         if (encoded_dt.IsValid() && (imm == 0)) {
15605           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15606             EmitT32_32(0xffb101c0U |
15607                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15608                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15609                        rd.Encode(22, 12) | rm.Encode(5, 0));
15610             AdvanceIT();
15611             return;
15612           }
15613         }
15614       } else {
15615         // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15616         if (encoded_dt.IsValid() && (imm == 0)) {
15617           if (cond.Is(al)) {
15618             EmitA32(0xf3b101c0U |
15619                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15620                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15621                     rd.Encode(22, 12) | rm.Encode(5, 0));
15622             return;
15623           }
15624         }
15625       }
15626     }
15627   }
15628   Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15629 }
15630 
vcle(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)15631 void Assembler::vcle(
15632     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15633   VIXL_ASSERT(AllowAssembler());
15634   CheckIT(cond);
15635   Dt_U_size_1 encoded_dt(dt);
15636   if (IsUsingT32()) {
15637     // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15638     if (encoded_dt.IsValid()) {
15639       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15640         EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15641                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15642                    rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15643         AdvanceIT();
15644         return;
15645       }
15646     }
15647     // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15648     if (dt.Is(F32)) {
15649       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15650         EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15651                    rm.Encode(7, 16));
15652         AdvanceIT();
15653         return;
15654       }
15655     }
15656   } else {
15657     // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15658     if (encoded_dt.IsValid()) {
15659       if (cond.Is(al)) {
15660         EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15661                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15662                 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15663         return;
15664       }
15665     }
15666     // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15667     if (dt.Is(F32)) {
15668       if (cond.Is(al)) {
15669         EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15670                 rm.Encode(7, 16));
15671         return;
15672       }
15673     }
15674   }
15675   Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15676 }
15677 
vcle(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)15678 void Assembler::vcle(
15679     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15680   VIXL_ASSERT(AllowAssembler());
15681   CheckIT(cond);
15682   Dt_U_size_1 encoded_dt(dt);
15683   if (IsUsingT32()) {
15684     // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15685     if (encoded_dt.IsValid()) {
15686       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15687         EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15688                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15689                    rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15690         AdvanceIT();
15691         return;
15692       }
15693     }
15694     // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15695     if (dt.Is(F32)) {
15696       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15697         EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15698                    rm.Encode(7, 16));
15699         AdvanceIT();
15700         return;
15701       }
15702     }
15703   } else {
15704     // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15705     if (encoded_dt.IsValid()) {
15706       if (cond.Is(al)) {
15707         EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15708                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15709                 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15710         return;
15711       }
15712     }
15713     // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15714     if (dt.Is(F32)) {
15715       if (cond.Is(al)) {
15716         EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15717                 rm.Encode(7, 16));
15718         return;
15719       }
15720     }
15721   }
15722   Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15723 }
15724 
vcls(Condition cond,DataType dt,DRegister rd,DRegister rm)15725 void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
15726   VIXL_ASSERT(AllowAssembler());
15727   CheckIT(cond);
15728   Dt_size_5 encoded_dt(dt);
15729   if (IsUsingT32()) {
15730     // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15731     if (encoded_dt.IsValid()) {
15732       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15733         EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
15734                    rd.Encode(22, 12) | rm.Encode(5, 0));
15735         AdvanceIT();
15736         return;
15737       }
15738     }
15739   } else {
15740     // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15741     if (encoded_dt.IsValid()) {
15742       if (cond.Is(al)) {
15743         EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
15744                 rd.Encode(22, 12) | rm.Encode(5, 0));
15745         return;
15746       }
15747     }
15748   }
15749   Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15750 }
15751 
vcls(Condition cond,DataType dt,QRegister rd,QRegister rm)15752 void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
15753   VIXL_ASSERT(AllowAssembler());
15754   CheckIT(cond);
15755   Dt_size_5 encoded_dt(dt);
15756   if (IsUsingT32()) {
15757     // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15758     if (encoded_dt.IsValid()) {
15759       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15760         EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
15761                    rd.Encode(22, 12) | rm.Encode(5, 0));
15762         AdvanceIT();
15763         return;
15764       }
15765     }
15766   } else {
15767     // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15768     if (encoded_dt.IsValid()) {
15769       if (cond.Is(al)) {
15770         EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
15771                 rd.Encode(22, 12) | rm.Encode(5, 0));
15772         return;
15773       }
15774     }
15775   }
15776   Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15777 }
15778 
vclt(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)15779 void Assembler::vclt(Condition cond,
15780                      DataType dt,
15781                      DRegister rd,
15782                      DRegister rm,
15783                      const DOperand& operand) {
15784   VIXL_ASSERT(AllowAssembler());
15785   CheckIT(cond);
15786   if (operand.IsImmediate()) {
15787     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15788       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15789       Dt_F_size_1 encoded_dt(dt);
15790       if (IsUsingT32()) {
15791         // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15792         if (encoded_dt.IsValid() && (imm == 0)) {
15793           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15794             EmitT32_32(0xffb10200U |
15795                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15796                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15797                        rd.Encode(22, 12) | rm.Encode(5, 0));
15798             AdvanceIT();
15799             return;
15800           }
15801         }
15802       } else {
15803         // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15804         if (encoded_dt.IsValid() && (imm == 0)) {
15805           if (cond.Is(al)) {
15806             EmitA32(0xf3b10200U |
15807                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15808                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15809                     rd.Encode(22, 12) | rm.Encode(5, 0));
15810             return;
15811           }
15812         }
15813       }
15814     }
15815   }
15816   Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15817 }
15818 
vclt(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)15819 void Assembler::vclt(Condition cond,
15820                      DataType dt,
15821                      QRegister rd,
15822                      QRegister rm,
15823                      const QOperand& operand) {
15824   VIXL_ASSERT(AllowAssembler());
15825   CheckIT(cond);
15826   if (operand.IsImmediate()) {
15827     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15828       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15829       Dt_F_size_1 encoded_dt(dt);
15830       if (IsUsingT32()) {
15831         // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15832         if (encoded_dt.IsValid() && (imm == 0)) {
15833           if (cond.Is(al) || AllowStronglyDiscouraged()) {
15834             EmitT32_32(0xffb10240U |
15835                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15836                        ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15837                        rd.Encode(22, 12) | rm.Encode(5, 0));
15838             AdvanceIT();
15839             return;
15840           }
15841         }
15842       } else {
15843         // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15844         if (encoded_dt.IsValid() && (imm == 0)) {
15845           if (cond.Is(al)) {
15846             EmitA32(0xf3b10240U |
15847                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15848                     ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15849                     rd.Encode(22, 12) | rm.Encode(5, 0));
15850             return;
15851           }
15852         }
15853       }
15854     }
15855   }
15856   Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15857 }
15858 
vclt(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)15859 void Assembler::vclt(
15860     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15861   VIXL_ASSERT(AllowAssembler());
15862   CheckIT(cond);
15863   Dt_U_size_1 encoded_dt(dt);
15864   if (IsUsingT32()) {
15865     // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15866     if (encoded_dt.IsValid()) {
15867       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15868         EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15869                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15870                    rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15871         AdvanceIT();
15872         return;
15873       }
15874     }
15875     // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15876     if (dt.Is(F32)) {
15877       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15878         EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15879                    rm.Encode(7, 16));
15880         AdvanceIT();
15881         return;
15882       }
15883     }
15884   } else {
15885     // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15886     if (encoded_dt.IsValid()) {
15887       if (cond.Is(al)) {
15888         EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15889                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15890                 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15891         return;
15892       }
15893     }
15894     // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15895     if (dt.Is(F32)) {
15896       if (cond.Is(al)) {
15897         EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15898                 rm.Encode(7, 16));
15899         return;
15900       }
15901     }
15902   }
15903   Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15904 }
15905 
vclt(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)15906 void Assembler::vclt(
15907     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15908   VIXL_ASSERT(AllowAssembler());
15909   CheckIT(cond);
15910   Dt_U_size_1 encoded_dt(dt);
15911   if (IsUsingT32()) {
15912     // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15913     if (encoded_dt.IsValid()) {
15914       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15915         EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15916                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15917                    rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15918         AdvanceIT();
15919         return;
15920       }
15921     }
15922     // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15923     if (dt.Is(F32)) {
15924       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15925         EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15926                    rm.Encode(7, 16));
15927         AdvanceIT();
15928         return;
15929       }
15930     }
15931   } else {
15932     // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15933     if (encoded_dt.IsValid()) {
15934       if (cond.Is(al)) {
15935         EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15936                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15937                 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15938         return;
15939       }
15940     }
15941     // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15942     if (dt.Is(F32)) {
15943       if (cond.Is(al)) {
15944         EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15945                 rm.Encode(7, 16));
15946         return;
15947       }
15948     }
15949   }
15950   Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15951 }
15952 
vclz(Condition cond,DataType dt,DRegister rd,DRegister rm)15953 void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
15954   VIXL_ASSERT(AllowAssembler());
15955   CheckIT(cond);
15956   Dt_size_4 encoded_dt(dt);
15957   if (IsUsingT32()) {
15958     // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15959     if (encoded_dt.IsValid()) {
15960       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15961         EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
15962                    rd.Encode(22, 12) | rm.Encode(5, 0));
15963         AdvanceIT();
15964         return;
15965       }
15966     }
15967   } else {
15968     // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15969     if (encoded_dt.IsValid()) {
15970       if (cond.Is(al)) {
15971         EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
15972                 rd.Encode(22, 12) | rm.Encode(5, 0));
15973         return;
15974       }
15975     }
15976   }
15977   Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15978 }
15979 
vclz(Condition cond,DataType dt,QRegister rd,QRegister rm)15980 void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
15981   VIXL_ASSERT(AllowAssembler());
15982   CheckIT(cond);
15983   Dt_size_4 encoded_dt(dt);
15984   if (IsUsingT32()) {
15985     // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15986     if (encoded_dt.IsValid()) {
15987       if (cond.Is(al) || AllowStronglyDiscouraged()) {
15988         EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
15989                    rd.Encode(22, 12) | rm.Encode(5, 0));
15990         AdvanceIT();
15991         return;
15992       }
15993     }
15994   } else {
15995     // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15996     if (encoded_dt.IsValid()) {
15997       if (cond.Is(al)) {
15998         EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
15999                 rd.Encode(22, 12) | rm.Encode(5, 0));
16000         return;
16001       }
16002     }
16003   }
16004   Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
16005 }
16006 
vcmp(Condition cond,DataType dt,SRegister rd,const SOperand & operand)16007 void Assembler::vcmp(Condition cond,
16008                      DataType dt,
16009                      SRegister rd,
16010                      const SOperand& operand) {
16011   VIXL_ASSERT(AllowAssembler());
16012   CheckIT(cond);
16013   if (operand.IsRegister()) {
16014     SRegister rm = operand.GetRegister();
16015     if (IsUsingT32()) {
16016       // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16017       if (dt.Is(F32)) {
16018         EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16019         AdvanceIT();
16020         return;
16021       }
16022     } else {
16023       // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16024       if (dt.Is(F32) && cond.IsNotNever()) {
16025         EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16026                 rm.Encode(5, 0));
16027         return;
16028       }
16029     }
16030   }
16031   if (operand.IsImmediate()) {
16032     if (IsUsingT32()) {
16033       // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16034       if (dt.Is(F32) && (operand.IsFloatZero())) {
16035         EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
16036         AdvanceIT();
16037         return;
16038       }
16039     } else {
16040       // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16041       if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16042         EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16043         return;
16044       }
16045     }
16046   }
16047   Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
16048 }
16049 
vcmp(Condition cond,DataType dt,DRegister rd,const DOperand & operand)16050 void Assembler::vcmp(Condition cond,
16051                      DataType dt,
16052                      DRegister rd,
16053                      const DOperand& operand) {
16054   VIXL_ASSERT(AllowAssembler());
16055   CheckIT(cond);
16056   if (operand.IsRegister()) {
16057     DRegister rm = operand.GetRegister();
16058     if (IsUsingT32()) {
16059       // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16060       if (dt.Is(F64)) {
16061         EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16062         AdvanceIT();
16063         return;
16064       }
16065     } else {
16066       // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16067       if (dt.Is(F64) && cond.IsNotNever()) {
16068         EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16069                 rm.Encode(5, 0));
16070         return;
16071       }
16072     }
16073   }
16074   if (operand.IsImmediate()) {
16075     if (IsUsingT32()) {
16076       // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16077       if (dt.Is(F64) && (operand.IsFloatZero())) {
16078         EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
16079         AdvanceIT();
16080         return;
16081       }
16082     } else {
16083       // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16084       if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16085         EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16086         return;
16087       }
16088     }
16089   }
16090   Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
16091 }
16092 
vcmpe(Condition cond,DataType dt,SRegister rd,const SOperand & operand)16093 void Assembler::vcmpe(Condition cond,
16094                       DataType dt,
16095                       SRegister rd,
16096                       const SOperand& operand) {
16097   VIXL_ASSERT(AllowAssembler());
16098   CheckIT(cond);
16099   if (operand.IsRegister()) {
16100     SRegister rm = operand.GetRegister();
16101     if (IsUsingT32()) {
16102       // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16103       if (dt.Is(F32)) {
16104         EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16105         AdvanceIT();
16106         return;
16107       }
16108     } else {
16109       // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16110       if (dt.Is(F32) && cond.IsNotNever()) {
16111         EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16112                 rm.Encode(5, 0));
16113         return;
16114       }
16115     }
16116   }
16117   if (operand.IsImmediate()) {
16118     if (IsUsingT32()) {
16119       // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16120       if (dt.Is(F32) && (operand.IsFloatZero())) {
16121         EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
16122         AdvanceIT();
16123         return;
16124       }
16125     } else {
16126       // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16127       if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16128         EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16129         return;
16130       }
16131     }
16132   }
16133   Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
16134 }
16135 
vcmpe(Condition cond,DataType dt,DRegister rd,const DOperand & operand)16136 void Assembler::vcmpe(Condition cond,
16137                       DataType dt,
16138                       DRegister rd,
16139                       const DOperand& operand) {
16140   VIXL_ASSERT(AllowAssembler());
16141   CheckIT(cond);
16142   if (operand.IsRegister()) {
16143     DRegister rm = operand.GetRegister();
16144     if (IsUsingT32()) {
16145       // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16146       if (dt.Is(F64)) {
16147         EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16148         AdvanceIT();
16149         return;
16150       }
16151     } else {
16152       // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16153       if (dt.Is(F64) && cond.IsNotNever()) {
16154         EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16155                 rm.Encode(5, 0));
16156         return;
16157       }
16158     }
16159   }
16160   if (operand.IsImmediate()) {
16161     if (IsUsingT32()) {
16162       // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16163       if (dt.Is(F64) && (operand.IsFloatZero())) {
16164         EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
16165         AdvanceIT();
16166         return;
16167       }
16168     } else {
16169       // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16170       if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16171         EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16172         return;
16173       }
16174     }
16175   }
16176   Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
16177 }
16178 
vcnt(Condition cond,DataType dt,DRegister rd,DRegister rm)16179 void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
16180   VIXL_ASSERT(AllowAssembler());
16181   CheckIT(cond);
16182   if (IsUsingT32()) {
16183     // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
16184     if (dt.Is(Untyped8)) {
16185       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16186         EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16187         AdvanceIT();
16188         return;
16189       }
16190     }
16191   } else {
16192     // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
16193     if (dt.Is(Untyped8)) {
16194       if (cond.Is(al)) {
16195         EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16196         return;
16197       }
16198     }
16199   }
16200   Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16201 }
16202 
vcnt(Condition cond,DataType dt,QRegister rd,QRegister rm)16203 void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
16204   VIXL_ASSERT(AllowAssembler());
16205   CheckIT(cond);
16206   if (IsUsingT32()) {
16207     // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
16208     if (dt.Is(Untyped8)) {
16209       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16210         EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16211         AdvanceIT();
16212         return;
16213       }
16214     }
16215   } else {
16216     // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
16217     if (dt.Is(Untyped8)) {
16218       if (cond.Is(al)) {
16219         EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16220         return;
16221       }
16222     }
16223   }
16224   Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16225 }
16226 
vcvt(Condition cond,DataType dt1,DataType dt2,DRegister rd,SRegister rm)16227 void Assembler::vcvt(
16228     Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
16229   VIXL_ASSERT(AllowAssembler());
16230   CheckIT(cond);
16231   Dt_op_2 encoded_dt(dt2);
16232   if (IsUsingT32()) {
16233     // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
16234     if (dt1.Is(F64) && dt2.Is(F32)) {
16235       EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16236       AdvanceIT();
16237       return;
16238     }
16239     // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
16240     if (dt1.Is(F64) && encoded_dt.IsValid()) {
16241       EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
16242                  rd.Encode(22, 12) | rm.Encode(5, 0));
16243       AdvanceIT();
16244       return;
16245     }
16246   } else {
16247     // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
16248     if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
16249       EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16250               rm.Encode(5, 0));
16251       return;
16252     }
16253     // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
16254     if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
16255       EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
16256               (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16257               rm.Encode(5, 0));
16258       return;
16259     }
16260   }
16261   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16262 }
16263 
vcvt(Condition cond,DataType dt1,DataType dt2,SRegister rd,DRegister rm)16264 void Assembler::vcvt(
16265     Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16266   VIXL_ASSERT(AllowAssembler());
16267   CheckIT(cond);
16268   if (IsUsingT32()) {
16269     // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
16270     if (dt1.Is(F32) && dt2.Is(F64)) {
16271       EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16272       AdvanceIT();
16273       return;
16274     }
16275     // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16276     if (dt1.Is(U32) && dt2.Is(F64)) {
16277       EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16278       AdvanceIT();
16279       return;
16280     }
16281     // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16282     if (dt1.Is(S32) && dt2.Is(F64)) {
16283       EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16284       AdvanceIT();
16285       return;
16286     }
16287   } else {
16288     // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
16289     if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
16290       EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16291               rm.Encode(5, 0));
16292       return;
16293     }
16294     // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16295     if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16296       EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16297               rm.Encode(5, 0));
16298       return;
16299     }
16300     // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16301     if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16302       EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16303               rm.Encode(5, 0));
16304       return;
16305     }
16306   }
16307   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16308 }
16309 
vcvt(Condition cond,DataType dt1,DataType dt2,DRegister rd,DRegister rm,int32_t fbits)16310 void Assembler::vcvt(Condition cond,
16311                      DataType dt1,
16312                      DataType dt2,
16313                      DRegister rd,
16314                      DRegister rm,
16315                      int32_t fbits) {
16316   VIXL_ASSERT(AllowAssembler());
16317   CheckIT(cond);
16318   Dt_op_U_1 encoded_dt(dt1, dt2);
16319   Dt_U_sx_1 encoded_dt_2(dt2);
16320   Dt_U_sx_1 encoded_dt_3(dt1);
16321   if (IsUsingT32()) {
16322     // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
16323     if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16324       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16325         uint32_t fbits_ = 64 - fbits;
16326         EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16327                    ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16328                    rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16329         AdvanceIT();
16330         return;
16331       }
16332     }
16333     // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
16334     if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16335         (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16336          ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16337       unsigned offset = 32;
16338       if (dt2.Is(S16) || dt2.Is(U16)) {
16339         offset = 16;
16340       }
16341       uint32_t fbits_ = offset - fbits;
16342       EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16343                  ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16344                  rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16345                  ((fbits_ & 0x1e) >> 1));
16346       AdvanceIT();
16347       return;
16348     }
16349     // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
16350     if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16351         (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16352          ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16353       unsigned offset = 32;
16354       if (dt1.Is(S16) || dt1.Is(U16)) {
16355         offset = 16;
16356       }
16357       uint32_t fbits_ = offset - fbits;
16358       EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16359                  ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16360                  rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16361                  ((fbits_ & 0x1e) >> 1));
16362       AdvanceIT();
16363       return;
16364     }
16365   } else {
16366     // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
16367     if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16368       if (cond.Is(al)) {
16369         uint32_t fbits_ = 64 - fbits;
16370         EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16371                 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16372                 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16373         return;
16374       }
16375     }
16376     // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
16377     if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16378         (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16379          ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16380         cond.IsNotNever()) {
16381       unsigned offset = 32;
16382       if (dt2.Is(S16) || dt2.Is(U16)) {
16383         offset = 16;
16384       }
16385       uint32_t fbits_ = offset - fbits;
16386       EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
16387               ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16388               ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16389               rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16390               ((fbits_ & 0x1e) >> 1));
16391       return;
16392     }
16393     // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
16394     if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16395         (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16396          ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16397         cond.IsNotNever()) {
16398       unsigned offset = 32;
16399       if (dt1.Is(S16) || dt1.Is(U16)) {
16400         offset = 16;
16401       }
16402       uint32_t fbits_ = offset - fbits;
16403       EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
16404               ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16405               ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16406               rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16407               ((fbits_ & 0x1e) >> 1));
16408       return;
16409     }
16410   }
16411   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16412 }
16413 
vcvt(Condition cond,DataType dt1,DataType dt2,QRegister rd,QRegister rm,int32_t fbits)16414 void Assembler::vcvt(Condition cond,
16415                      DataType dt1,
16416                      DataType dt2,
16417                      QRegister rd,
16418                      QRegister rm,
16419                      int32_t fbits) {
16420   VIXL_ASSERT(AllowAssembler());
16421   CheckIT(cond);
16422   Dt_op_U_1 encoded_dt(dt1, dt2);
16423   if (IsUsingT32()) {
16424     // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
16425     if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16426       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16427         uint32_t fbits_ = 64 - fbits;
16428         EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16429                    ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16430                    rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16431         AdvanceIT();
16432         return;
16433       }
16434     }
16435   } else {
16436     // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
16437     if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16438       if (cond.Is(al)) {
16439         uint32_t fbits_ = 64 - fbits;
16440         EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16441                 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16442                 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16443         return;
16444       }
16445     }
16446   }
16447   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16448 }
16449 
vcvt(Condition cond,DataType dt1,DataType dt2,SRegister rd,SRegister rm,int32_t fbits)16450 void Assembler::vcvt(Condition cond,
16451                      DataType dt1,
16452                      DataType dt2,
16453                      SRegister rd,
16454                      SRegister rm,
16455                      int32_t fbits) {
16456   VIXL_ASSERT(AllowAssembler());
16457   CheckIT(cond);
16458   Dt_U_sx_1 encoded_dt(dt2);
16459   Dt_U_sx_1 encoded_dt_2(dt1);
16460   if (IsUsingT32()) {
16461     // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
16462     if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16463         (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16464          ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16465       unsigned offset = 32;
16466       if (dt2.Is(S16) || dt2.Is(U16)) {
16467         offset = 16;
16468       }
16469       uint32_t fbits_ = offset - fbits;
16470       EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16471                  ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16472                  rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16473                  ((fbits_ & 0x1e) >> 1));
16474       AdvanceIT();
16475       return;
16476     }
16477     // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
16478     if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16479         (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16480          ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16481       unsigned offset = 32;
16482       if (dt1.Is(S16) || dt1.Is(U16)) {
16483         offset = 16;
16484       }
16485       uint32_t fbits_ = offset - fbits;
16486       EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16487                  ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16488                  rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16489                  ((fbits_ & 0x1e) >> 1));
16490       AdvanceIT();
16491       return;
16492     }
16493   } else {
16494     // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
16495     if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16496         (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16497          ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16498         cond.IsNotNever()) {
16499       unsigned offset = 32;
16500       if (dt2.Is(S16) || dt2.Is(U16)) {
16501         offset = 16;
16502       }
16503       uint32_t fbits_ = offset - fbits;
16504       EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
16505               ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16506               ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16507               rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16508               ((fbits_ & 0x1e) >> 1));
16509       return;
16510     }
16511     // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
16512     if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16513         (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16514          ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16515         cond.IsNotNever()) {
16516       unsigned offset = 32;
16517       if (dt1.Is(S16) || dt1.Is(U16)) {
16518         offset = 16;
16519       }
16520       uint32_t fbits_ = offset - fbits;
16521       EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
16522               ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16523               ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16524               rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16525               ((fbits_ & 0x1e) >> 1));
16526       return;
16527     }
16528   }
16529   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16530 }
16531 
vcvt(Condition cond,DataType dt1,DataType dt2,DRegister rd,DRegister rm)16532 void Assembler::vcvt(
16533     Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16534   VIXL_ASSERT(AllowAssembler());
16535   CheckIT(cond);
16536   Dt_op_1 encoded_dt(dt1, dt2);
16537   if (IsUsingT32()) {
16538     // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
16539     if (encoded_dt.IsValid()) {
16540       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16541         EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
16542                    rd.Encode(22, 12) | rm.Encode(5, 0));
16543         AdvanceIT();
16544         return;
16545       }
16546     }
16547   } else {
16548     // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
16549     if (encoded_dt.IsValid()) {
16550       if (cond.Is(al)) {
16551         EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
16552                 rd.Encode(22, 12) | rm.Encode(5, 0));
16553         return;
16554       }
16555     }
16556   }
16557   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16558 }
16559 
vcvt(Condition cond,DataType dt1,DataType dt2,QRegister rd,QRegister rm)16560 void Assembler::vcvt(
16561     Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16562   VIXL_ASSERT(AllowAssembler());
16563   CheckIT(cond);
16564   Dt_op_1 encoded_dt(dt1, dt2);
16565   if (IsUsingT32()) {
16566     // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
16567     if (encoded_dt.IsValid()) {
16568       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16569         EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
16570                    rd.Encode(22, 12) | rm.Encode(5, 0));
16571         AdvanceIT();
16572         return;
16573       }
16574     }
16575   } else {
16576     // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
16577     if (encoded_dt.IsValid()) {
16578       if (cond.Is(al)) {
16579         EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
16580                 rd.Encode(22, 12) | rm.Encode(5, 0));
16581         return;
16582       }
16583     }
16584   }
16585   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16586 }
16587 
vcvt(Condition cond,DataType dt1,DataType dt2,DRegister rd,QRegister rm)16588 void Assembler::vcvt(
16589     Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
16590   VIXL_ASSERT(AllowAssembler());
16591   CheckIT(cond);
16592   if (IsUsingT32()) {
16593     // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
16594     if (dt1.Is(F16) && dt2.Is(F32)) {
16595       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16596         EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16597         AdvanceIT();
16598         return;
16599       }
16600     }
16601   } else {
16602     // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
16603     if (dt1.Is(F16) && dt2.Is(F32)) {
16604       if (cond.Is(al)) {
16605         EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16606         return;
16607       }
16608     }
16609   }
16610   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16611 }
16612 
vcvt(Condition cond,DataType dt1,DataType dt2,QRegister rd,DRegister rm)16613 void Assembler::vcvt(
16614     Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
16615   VIXL_ASSERT(AllowAssembler());
16616   CheckIT(cond);
16617   if (IsUsingT32()) {
16618     // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
16619     if (dt1.Is(F32) && dt2.Is(F16)) {
16620       if (cond.Is(al) || AllowStronglyDiscouraged()) {
16621         EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16622         AdvanceIT();
16623         return;
16624       }
16625     }
16626   } else {
16627     // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
16628     if (dt1.Is(F32) && dt2.Is(F16)) {
16629       if (cond.Is(al)) {
16630         EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16631         return;
16632       }
16633     }
16634   }
16635   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16636 }
16637 
vcvt(Condition cond,DataType dt1,DataType dt2,SRegister rd,SRegister rm)16638 void Assembler::vcvt(
16639     Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16640   VIXL_ASSERT(AllowAssembler());
16641   CheckIT(cond);
16642   Dt_op_2 encoded_dt(dt2);
16643   if (IsUsingT32()) {
16644     // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
16645     if (dt1.Is(U32) && dt2.Is(F32)) {
16646       EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16647       AdvanceIT();
16648       return;
16649     }
16650     // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
16651     if (dt1.Is(S32) && dt2.Is(F32)) {
16652       EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16653       AdvanceIT();
16654       return;
16655     }
16656     // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
16657     if (dt1.Is(F32) && encoded_dt.IsValid()) {
16658       EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
16659                  rd.Encode(22, 12) | rm.Encode(5, 0));
16660       AdvanceIT();
16661       return;
16662     }
16663   } else {
16664     // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
16665     if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
16666       EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16667               rm.Encode(5, 0));
16668       return;
16669     }
16670     // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
16671     if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
16672       EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16673               rm.Encode(5, 0));
16674       return;
16675     }
16676     // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
16677     if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
16678       EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
16679               (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16680               rm.Encode(5, 0));
16681       return;
16682     }
16683   }
16684   Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16685 }
16686 
vcvta(DataType dt1,DataType dt2,DRegister rd,DRegister rm)16687 void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16688   VIXL_ASSERT(AllowAssembler());
16689   CheckIT(al);
16690   Dt_op_3 encoded_dt(dt1);
16691   if (IsUsingT32()) {
16692     // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16693     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16694       EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
16695                  rd.Encode(22, 12) | rm.Encode(5, 0));
16696       AdvanceIT();
16697       return;
16698     }
16699   } else {
16700     // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16701     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16702       EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
16703               rd.Encode(22, 12) | rm.Encode(5, 0));
16704       return;
16705     }
16706   }
16707   Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16708 }
16709 
vcvta(DataType dt1,DataType dt2,QRegister rd,QRegister rm)16710 void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16711   VIXL_ASSERT(AllowAssembler());
16712   CheckIT(al);
16713   Dt_op_3 encoded_dt(dt1);
16714   if (IsUsingT32()) {
16715     // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16716     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16717       EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
16718                  rd.Encode(22, 12) | rm.Encode(5, 0));
16719       AdvanceIT();
16720       return;
16721     }
16722   } else {
16723     // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16724     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16725       EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
16726               rd.Encode(22, 12) | rm.Encode(5, 0));
16727       return;
16728     }
16729   }
16730   Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16731 }
16732 
vcvta(DataType dt1,DataType dt2,SRegister rd,SRegister rm)16733 void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16734   VIXL_ASSERT(AllowAssembler());
16735   CheckIT(al);
16736   Dt_op_2 encoded_dt(dt1);
16737   if (IsUsingT32()) {
16738     // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16739     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16740       EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16741                  rd.Encode(22, 12) | rm.Encode(5, 0));
16742       AdvanceIT();
16743       return;
16744     }
16745   } else {
16746     // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16747     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16748       EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16749               rd.Encode(22, 12) | rm.Encode(5, 0));
16750       return;
16751     }
16752   }
16753   Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16754 }
16755 
vcvta(DataType dt1,DataType dt2,SRegister rd,DRegister rm)16756 void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16757   VIXL_ASSERT(AllowAssembler());
16758   CheckIT(al);
16759   Dt_op_2 encoded_dt(dt1);
16760   if (IsUsingT32()) {
16761     // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16762     if (encoded_dt.IsValid() && dt2.Is(F64)) {
16763       EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16764                  rd.Encode(22, 12) | rm.Encode(5, 0));
16765       AdvanceIT();
16766       return;
16767     }
16768   } else {
16769     // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16770     if (encoded_dt.IsValid() && dt2.Is(F64)) {
16771       EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16772               rd.Encode(22, 12) | rm.Encode(5, 0));
16773       return;
16774     }
16775   }
16776   Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16777 }
16778 
vcvtb(Condition cond,DataType dt1,DataType dt2,SRegister rd,SRegister rm)16779 void Assembler::vcvtb(
16780     Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16781   VIXL_ASSERT(AllowAssembler());
16782   CheckIT(cond);
16783   if (IsUsingT32()) {
16784     // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16785     if (dt1.Is(F32) && dt2.Is(F16)) {
16786       EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16787       AdvanceIT();
16788       return;
16789     }
16790     // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16791     if (dt1.Is(F16) && dt2.Is(F32)) {
16792       EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16793       AdvanceIT();
16794       return;
16795     }
16796   } else {
16797     // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16798     if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16799       EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16800               rm.Encode(5, 0));
16801       return;
16802     }
16803     // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16804     if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16805       EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16806               rm.Encode(5, 0));
16807       return;
16808     }
16809   }
16810   Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16811 }
16812 
vcvtb(Condition cond,DataType dt1,DataType dt2,DRegister rd,SRegister rm)16813 void Assembler::vcvtb(
16814     Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
16815   VIXL_ASSERT(AllowAssembler());
16816   CheckIT(cond);
16817   if (IsUsingT32()) {
16818     // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16819     if (dt1.Is(F64) && dt2.Is(F16)) {
16820       EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16821       AdvanceIT();
16822       return;
16823     }
16824   } else {
16825     // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16826     if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16827       EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16828               rm.Encode(5, 0));
16829       return;
16830     }
16831   }
16832   Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16833 }
16834 
vcvtb(Condition cond,DataType dt1,DataType dt2,SRegister rd,DRegister rm)16835 void Assembler::vcvtb(
16836     Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16837   VIXL_ASSERT(AllowAssembler());
16838   CheckIT(cond);
16839   if (IsUsingT32()) {
16840     // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16841     if (dt1.Is(F16) && dt2.Is(F64)) {
16842       EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16843       AdvanceIT();
16844       return;
16845     }
16846   } else {
16847     // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16848     if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16849       EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16850               rm.Encode(5, 0));
16851       return;
16852     }
16853   }
16854   Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16855 }
16856 
vcvtm(DataType dt1,DataType dt2,DRegister rd,DRegister rm)16857 void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16858   VIXL_ASSERT(AllowAssembler());
16859   CheckIT(al);
16860   Dt_op_3 encoded_dt(dt1);
16861   if (IsUsingT32()) {
16862     // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16863     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16864       EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
16865                  rd.Encode(22, 12) | rm.Encode(5, 0));
16866       AdvanceIT();
16867       return;
16868     }
16869   } else {
16870     // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16871     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16872       EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
16873               rd.Encode(22, 12) | rm.Encode(5, 0));
16874       return;
16875     }
16876   }
16877   Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16878 }
16879 
vcvtm(DataType dt1,DataType dt2,QRegister rd,QRegister rm)16880 void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16881   VIXL_ASSERT(AllowAssembler());
16882   CheckIT(al);
16883   Dt_op_3 encoded_dt(dt1);
16884   if (IsUsingT32()) {
16885     // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16886     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16887       EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
16888                  rd.Encode(22, 12) | rm.Encode(5, 0));
16889       AdvanceIT();
16890       return;
16891     }
16892   } else {
16893     // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16894     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16895       EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
16896               rd.Encode(22, 12) | rm.Encode(5, 0));
16897       return;
16898     }
16899   }
16900   Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16901 }
16902 
vcvtm(DataType dt1,DataType dt2,SRegister rd,SRegister rm)16903 void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16904   VIXL_ASSERT(AllowAssembler());
16905   CheckIT(al);
16906   Dt_op_2 encoded_dt(dt1);
16907   if (IsUsingT32()) {
16908     // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16909     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16910       EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16911                  rd.Encode(22, 12) | rm.Encode(5, 0));
16912       AdvanceIT();
16913       return;
16914     }
16915   } else {
16916     // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16917     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16918       EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16919               rd.Encode(22, 12) | rm.Encode(5, 0));
16920       return;
16921     }
16922   }
16923   Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16924 }
16925 
vcvtm(DataType dt1,DataType dt2,SRegister rd,DRegister rm)16926 void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16927   VIXL_ASSERT(AllowAssembler());
16928   CheckIT(al);
16929   Dt_op_2 encoded_dt(dt1);
16930   if (IsUsingT32()) {
16931     // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16932     if (encoded_dt.IsValid() && dt2.Is(F64)) {
16933       EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16934                  rd.Encode(22, 12) | rm.Encode(5, 0));
16935       AdvanceIT();
16936       return;
16937     }
16938   } else {
16939     // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16940     if (encoded_dt.IsValid() && dt2.Is(F64)) {
16941       EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16942               rd.Encode(22, 12) | rm.Encode(5, 0));
16943       return;
16944     }
16945   }
16946   Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16947 }
16948 
vcvtn(DataType dt1,DataType dt2,DRegister rd,DRegister rm)16949 void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16950   VIXL_ASSERT(AllowAssembler());
16951   CheckIT(al);
16952   Dt_op_3 encoded_dt(dt1);
16953   if (IsUsingT32()) {
16954     // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16955     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16956       EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
16957                  rd.Encode(22, 12) | rm.Encode(5, 0));
16958       AdvanceIT();
16959       return;
16960     }
16961   } else {
16962     // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16963     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16964       EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
16965               rd.Encode(22, 12) | rm.Encode(5, 0));
16966       return;
16967     }
16968   }
16969   Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16970 }
16971 
vcvtn(DataType dt1,DataType dt2,QRegister rd,QRegister rm)16972 void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16973   VIXL_ASSERT(AllowAssembler());
16974   CheckIT(al);
16975   Dt_op_3 encoded_dt(dt1);
16976   if (IsUsingT32()) {
16977     // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16978     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16979       EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
16980                  rd.Encode(22, 12) | rm.Encode(5, 0));
16981       AdvanceIT();
16982       return;
16983     }
16984   } else {
16985     // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16986     if (encoded_dt.IsValid() && dt2.Is(F32)) {
16987       EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
16988               rd.Encode(22, 12) | rm.Encode(5, 0));
16989       return;
16990     }
16991   }
16992   Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16993 }
16994 
vcvtn(DataType dt1,DataType dt2,SRegister rd,SRegister rm)16995 void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16996   VIXL_ASSERT(AllowAssembler());
16997   CheckIT(al);
16998   Dt_op_2 encoded_dt(dt1);
16999   if (IsUsingT32()) {
17000     // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
17001     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17002       EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
17003                  rd.Encode(22, 12) | rm.Encode(5, 0));
17004       AdvanceIT();
17005       return;
17006     }
17007   } else {
17008     // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17009     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17010       EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
17011               rd.Encode(22, 12) | rm.Encode(5, 0));
17012       return;
17013     }
17014   }
17015   Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
17016 }
17017 
vcvtn(DataType dt1,DataType dt2,SRegister rd,DRegister rm)17018 void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17019   VIXL_ASSERT(AllowAssembler());
17020   CheckIT(al);
17021   Dt_op_2 encoded_dt(dt1);
17022   if (IsUsingT32()) {
17023     // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17024     if (encoded_dt.IsValid() && dt2.Is(F64)) {
17025       EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
17026                  rd.Encode(22, 12) | rm.Encode(5, 0));
17027       AdvanceIT();
17028       return;
17029     }
17030   } else {
17031     // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17032     if (encoded_dt.IsValid() && dt2.Is(F64)) {
17033       EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
17034               rd.Encode(22, 12) | rm.Encode(5, 0));
17035       return;
17036     }
17037   }
17038   Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
17039 }
17040 
vcvtp(DataType dt1,DataType dt2,DRegister rd,DRegister rm)17041 void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
17042   VIXL_ASSERT(AllowAssembler());
17043   CheckIT(al);
17044   Dt_op_3 encoded_dt(dt1);
17045   if (IsUsingT32()) {
17046     // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
17047     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17048       EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
17049                  rd.Encode(22, 12) | rm.Encode(5, 0));
17050       AdvanceIT();
17051       return;
17052     }
17053   } else {
17054     // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
17055     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17056       EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
17057               rd.Encode(22, 12) | rm.Encode(5, 0));
17058       return;
17059     }
17060   }
17061   Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17062 }
17063 
vcvtp(DataType dt1,DataType dt2,QRegister rd,QRegister rm)17064 void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
17065   VIXL_ASSERT(AllowAssembler());
17066   CheckIT(al);
17067   Dt_op_3 encoded_dt(dt1);
17068   if (IsUsingT32()) {
17069     // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
17070     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17071       EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
17072                  rd.Encode(22, 12) | rm.Encode(5, 0));
17073       AdvanceIT();
17074       return;
17075     }
17076   } else {
17077     // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
17078     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17079       EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
17080               rd.Encode(22, 12) | rm.Encode(5, 0));
17081       return;
17082     }
17083   }
17084   Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17085 }
17086 
vcvtp(DataType dt1,DataType dt2,SRegister rd,SRegister rm)17087 void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
17088   VIXL_ASSERT(AllowAssembler());
17089   CheckIT(al);
17090   Dt_op_2 encoded_dt(dt1);
17091   if (IsUsingT32()) {
17092     // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
17093     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17094       EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17095                  rd.Encode(22, 12) | rm.Encode(5, 0));
17096       AdvanceIT();
17097       return;
17098     }
17099   } else {
17100     // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17101     if (encoded_dt.IsValid() && dt2.Is(F32)) {
17102       EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17103               rd.Encode(22, 12) | rm.Encode(5, 0));
17104       return;
17105     }
17106   }
17107   Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17108 }
17109 
vcvtp(DataType dt1,DataType dt2,SRegister rd,DRegister rm)17110 void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17111   VIXL_ASSERT(AllowAssembler());
17112   CheckIT(al);
17113   Dt_op_2 encoded_dt(dt1);
17114   if (IsUsingT32()) {
17115     // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17116     if (encoded_dt.IsValid() && dt2.Is(F64)) {
17117       EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17118                  rd.Encode(22, 12) | rm.Encode(5, 0));
17119       AdvanceIT();
17120       return;
17121     }
17122   } else {
17123     // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17124     if (encoded_dt.IsValid() && dt2.Is(F64)) {
17125       EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17126               rd.Encode(22, 12) | rm.Encode(5, 0));
17127       return;
17128     }
17129   }
17130   Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17131 }
17132 
vcvtr(Condition cond,DataType dt1,DataType dt2,SRegister rd,SRegister rm)17133 void Assembler::vcvtr(
17134     Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
17135   VIXL_ASSERT(AllowAssembler());
17136   CheckIT(cond);
17137   if (IsUsingT32()) {
17138     // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
17139     if (dt1.Is(U32) && dt2.Is(F32)) {
17140       EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17141       AdvanceIT();
17142       return;
17143     }
17144     // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
17145     if (dt1.Is(S32) && dt2.Is(F32)) {
17146       EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17147       AdvanceIT();
17148       return;
17149     }
17150   } else {
17151     // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
17152     if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
17153       EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17154               rm.Encode(5, 0));
17155       return;
17156     }
17157     // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
17158     if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
17159       EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17160               rm.Encode(5, 0));
17161       return;
17162     }
17163   }
17164   Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17165 }
17166 
vcvtr(Condition cond,DataType dt1,DataType dt2,SRegister rd,DRegister rm)17167 void Assembler::vcvtr(
17168     Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17169   VIXL_ASSERT(AllowAssembler());
17170   CheckIT(cond);
17171   if (IsUsingT32()) {
17172     // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
17173     if (dt1.Is(U32) && dt2.Is(F64)) {
17174       EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17175       AdvanceIT();
17176       return;
17177     }
17178     // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
17179     if (dt1.Is(S32) && dt2.Is(F64)) {
17180       EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17181       AdvanceIT();
17182       return;
17183     }
17184   } else {
17185     // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
17186     if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
17187       EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17188               rm.Encode(5, 0));
17189       return;
17190     }
17191     // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
17192     if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
17193       EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17194               rm.Encode(5, 0));
17195       return;
17196     }
17197   }
17198   Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17199 }
17200 
vcvtt(Condition cond,DataType dt1,DataType dt2,SRegister rd,SRegister rm)17201 void Assembler::vcvtt(
17202     Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
17203   VIXL_ASSERT(AllowAssembler());
17204   CheckIT(cond);
17205   if (IsUsingT32()) {
17206     // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
17207     if (dt1.Is(F32) && dt2.Is(F16)) {
17208       EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17209       AdvanceIT();
17210       return;
17211     }
17212     // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
17213     if (dt1.Is(F16) && dt2.Is(F32)) {
17214       EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17215       AdvanceIT();
17216       return;
17217     }
17218   } else {
17219     // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
17220     if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
17221       EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17222               rm.Encode(5, 0));
17223       return;
17224     }
17225     // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
17226     if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
17227       EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17228               rm.Encode(5, 0));
17229       return;
17230     }
17231   }
17232   Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17233 }
17234 
vcvtt(Condition cond,DataType dt1,DataType dt2,DRegister rd,SRegister rm)17235 void Assembler::vcvtt(
17236     Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
17237   VIXL_ASSERT(AllowAssembler());
17238   CheckIT(cond);
17239   if (IsUsingT32()) {
17240     // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
17241     if (dt1.Is(F64) && dt2.Is(F16)) {
17242       EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17243       AdvanceIT();
17244       return;
17245     }
17246   } else {
17247     // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
17248     if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
17249       EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17250               rm.Encode(5, 0));
17251       return;
17252     }
17253   }
17254   Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17255 }
17256 
vcvtt(Condition cond,DataType dt1,DataType dt2,SRegister rd,DRegister rm)17257 void Assembler::vcvtt(
17258     Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17259   VIXL_ASSERT(AllowAssembler());
17260   CheckIT(cond);
17261   if (IsUsingT32()) {
17262     // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
17263     if (dt1.Is(F16) && dt2.Is(F64)) {
17264       EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17265       AdvanceIT();
17266       return;
17267     }
17268   } else {
17269     // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
17270     if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
17271       EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17272               rm.Encode(5, 0));
17273       return;
17274     }
17275   }
17276   Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17277 }
17278 
vdiv(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)17279 void Assembler::vdiv(
17280     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17281   VIXL_ASSERT(AllowAssembler());
17282   CheckIT(cond);
17283   if (IsUsingT32()) {
17284     // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
17285     if (dt.Is(F32)) {
17286       EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17287                  rm.Encode(5, 0));
17288       AdvanceIT();
17289       return;
17290     }
17291   } else {
17292     // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
17293     if (dt.Is(F32) && cond.IsNotNever()) {
17294       EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17295               rn.Encode(7, 16) | rm.Encode(5, 0));
17296       return;
17297     }
17298   }
17299   Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17300 }
17301 
vdiv(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17302 void Assembler::vdiv(
17303     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17304   VIXL_ASSERT(AllowAssembler());
17305   CheckIT(cond);
17306   if (IsUsingT32()) {
17307     // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
17308     if (dt.Is(F64)) {
17309       EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17310                  rm.Encode(5, 0));
17311       AdvanceIT();
17312       return;
17313     }
17314   } else {
17315     // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
17316     if (dt.Is(F64) && cond.IsNotNever()) {
17317       EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17318               rn.Encode(7, 16) | rm.Encode(5, 0));
17319       return;
17320     }
17321   }
17322   Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17323 }
17324 
vdup(Condition cond,DataType dt,QRegister rd,Register rt)17325 void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
17326   VIXL_ASSERT(AllowAssembler());
17327   CheckIT(cond);
17328   Dt_B_E_1 encoded_dt(dt);
17329   if (IsUsingT32()) {
17330     // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
17331     if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
17332       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17333         EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17334                    ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17335                    rd.Encode(7, 16) | (rt.GetCode() << 12));
17336         AdvanceIT();
17337         return;
17338       }
17339     }
17340   } else {
17341     // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
17342     if (encoded_dt.IsValid() && cond.IsNotNever() &&
17343         (!rt.IsPC() || AllowUnpredictable())) {
17344       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17345         EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
17346                 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17347                 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17348                 rd.Encode(7, 16) | (rt.GetCode() << 12));
17349         return;
17350       }
17351     }
17352   }
17353   Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17354 }
17355 
vdup(Condition cond,DataType dt,DRegister rd,Register rt)17356 void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
17357   VIXL_ASSERT(AllowAssembler());
17358   CheckIT(cond);
17359   Dt_B_E_1 encoded_dt(dt);
17360   if (IsUsingT32()) {
17361     // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
17362     if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
17363       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17364         EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17365                    ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17366                    rd.Encode(7, 16) | (rt.GetCode() << 12));
17367         AdvanceIT();
17368         return;
17369       }
17370     }
17371   } else {
17372     // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
17373     if (encoded_dt.IsValid() && cond.IsNotNever() &&
17374         (!rt.IsPC() || AllowUnpredictable())) {
17375       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17376         EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
17377                 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17378                 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17379                 rd.Encode(7, 16) | (rt.GetCode() << 12));
17380         return;
17381       }
17382     }
17383   }
17384   Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17385 }
17386 
vdup(Condition cond,DataType dt,DRegister rd,DRegisterLane rm)17387 void Assembler::vdup(Condition cond,
17388                      DataType dt,
17389                      DRegister rd,
17390                      DRegisterLane rm) {
17391   VIXL_ASSERT(AllowAssembler());
17392   CheckIT(cond);
17393   Dt_imm4_1 encoded_dt(dt, rm);
17394   if (IsUsingT32()) {
17395     // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
17396     if (encoded_dt.IsValid()) {
17397       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17398         EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
17399                    rd.Encode(22, 12) | rm.Encode(5, 0));
17400         AdvanceIT();
17401         return;
17402       }
17403     }
17404   } else {
17405     // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
17406     if (encoded_dt.IsValid()) {
17407       if (cond.Is(al)) {
17408         EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
17409                 rd.Encode(22, 12) | rm.Encode(5, 0));
17410         return;
17411       }
17412     }
17413   }
17414   Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17415 }
17416 
vdup(Condition cond,DataType dt,QRegister rd,DRegisterLane rm)17417 void Assembler::vdup(Condition cond,
17418                      DataType dt,
17419                      QRegister rd,
17420                      DRegisterLane rm) {
17421   VIXL_ASSERT(AllowAssembler());
17422   CheckIT(cond);
17423   Dt_imm4_1 encoded_dt(dt, rm);
17424   if (IsUsingT32()) {
17425     // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
17426     if (encoded_dt.IsValid()) {
17427       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17428         EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
17429                    rd.Encode(22, 12) | rm.Encode(5, 0));
17430         AdvanceIT();
17431         return;
17432       }
17433     }
17434   } else {
17435     // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
17436     if (encoded_dt.IsValid()) {
17437       if (cond.Is(al)) {
17438         EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
17439                 rd.Encode(22, 12) | rm.Encode(5, 0));
17440         return;
17441       }
17442     }
17443   }
17444   Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17445 }
17446 
veor(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17447 void Assembler::veor(
17448     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17449   VIXL_ASSERT(AllowAssembler());
17450   CheckIT(cond);
17451   USE(dt);
17452   if (IsUsingT32()) {
17453     // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
17454     if (cond.Is(al) || AllowStronglyDiscouraged()) {
17455       EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17456                  rm.Encode(5, 0));
17457       AdvanceIT();
17458       return;
17459     }
17460   } else {
17461     // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
17462     if (cond.Is(al)) {
17463       EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17464               rm.Encode(5, 0));
17465       return;
17466     }
17467   }
17468   Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17469 }
17470 
veor(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)17471 void Assembler::veor(
17472     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17473   VIXL_ASSERT(AllowAssembler());
17474   CheckIT(cond);
17475   USE(dt);
17476   if (IsUsingT32()) {
17477     // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
17478     if (cond.Is(al) || AllowStronglyDiscouraged()) {
17479       EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17480                  rm.Encode(5, 0));
17481       AdvanceIT();
17482       return;
17483     }
17484   } else {
17485     // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
17486     if (cond.Is(al)) {
17487       EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17488               rm.Encode(5, 0));
17489       return;
17490     }
17491   }
17492   Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17493 }
17494 
vext(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm,const DOperand & operand)17495 void Assembler::vext(Condition cond,
17496                      DataType dt,
17497                      DRegister rd,
17498                      DRegister rn,
17499                      DRegister rm,
17500                      const DOperand& operand) {
17501   VIXL_ASSERT(AllowAssembler());
17502   CheckIT(cond);
17503   if (operand.IsImmediate()) {
17504     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17505       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
17506       if (IsUsingT32()) {
17507         // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17508         if (dt.Is(Untyped8) && (imm <= 7)) {
17509           if (cond.Is(al) || AllowStronglyDiscouraged()) {
17510             EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17511                        rm.Encode(5, 0) | (imm << 8));
17512             AdvanceIT();
17513             return;
17514           }
17515         }
17516         // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17517         if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17518             (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17519           if (cond.Is(al) || AllowStronglyDiscouraged()) {
17520             uint32_t imm4 = imm / dt.GetSize();
17521             EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17522                        rm.Encode(5, 0) | (imm4 << 8));
17523             AdvanceIT();
17524             return;
17525           }
17526         }
17527       } else {
17528         // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17529         if (dt.Is(Untyped8) && (imm <= 7)) {
17530           if (cond.Is(al)) {
17531             EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17532                     rm.Encode(5, 0) | (imm << 8));
17533             return;
17534           }
17535         }
17536         // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17537         if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17538             (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17539           if (cond.Is(al)) {
17540             uint32_t imm4 = imm / dt.GetSize();
17541             EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17542                     rm.Encode(5, 0) | (imm4 << 8));
17543             return;
17544           }
17545         }
17546       }
17547     }
17548   }
17549   Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17550 }
17551 
vext(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm,const QOperand & operand)17552 void Assembler::vext(Condition cond,
17553                      DataType dt,
17554                      QRegister rd,
17555                      QRegister rn,
17556                      QRegister rm,
17557                      const QOperand& operand) {
17558   VIXL_ASSERT(AllowAssembler());
17559   CheckIT(cond);
17560   if (operand.IsImmediate()) {
17561     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17562       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
17563       if (IsUsingT32()) {
17564         // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17565         if (dt.Is(Untyped8) && (imm <= 15)) {
17566           if (cond.Is(al) || AllowStronglyDiscouraged()) {
17567             EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17568                        rm.Encode(5, 0) | (imm << 8));
17569             AdvanceIT();
17570             return;
17571           }
17572         }
17573         // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17574         if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17575             (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17576           if (cond.Is(al) || AllowStronglyDiscouraged()) {
17577             uint32_t imm4 = imm / dt.GetSize();
17578             EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17579                        rm.Encode(5, 0) | (imm4 << 8));
17580             AdvanceIT();
17581             return;
17582           }
17583         }
17584       } else {
17585         // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17586         if (dt.Is(Untyped8) && (imm <= 15)) {
17587           if (cond.Is(al)) {
17588             EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17589                     rm.Encode(5, 0) | (imm << 8));
17590             return;
17591           }
17592         }
17593         // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17594         if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17595             (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17596           if (cond.Is(al)) {
17597             uint32_t imm4 = imm / dt.GetSize();
17598             EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17599                     rm.Encode(5, 0) | (imm4 << 8));
17600             return;
17601           }
17602         }
17603       }
17604     }
17605   }
17606   Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17607 }
17608 
vfma(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17609 void Assembler::vfma(
17610     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17611   VIXL_ASSERT(AllowAssembler());
17612   CheckIT(cond);
17613   if (IsUsingT32()) {
17614     // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17615     if (dt.Is(F32)) {
17616       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17617         EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17618                    rm.Encode(5, 0));
17619         AdvanceIT();
17620         return;
17621       }
17622     }
17623     // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17624     if (dt.Is(F64)) {
17625       EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17626                  rm.Encode(5, 0));
17627       AdvanceIT();
17628       return;
17629     }
17630   } else {
17631     // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17632     if (dt.Is(F32)) {
17633       if (cond.Is(al)) {
17634         EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17635                 rm.Encode(5, 0));
17636         return;
17637       }
17638     }
17639     // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17640     if (dt.Is(F64) && cond.IsNotNever()) {
17641       EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17642               rn.Encode(7, 16) | rm.Encode(5, 0));
17643       return;
17644     }
17645   }
17646   Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17647 }
17648 
vfma(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)17649 void Assembler::vfma(
17650     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17651   VIXL_ASSERT(AllowAssembler());
17652   CheckIT(cond);
17653   if (IsUsingT32()) {
17654     // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17655     if (dt.Is(F32)) {
17656       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17657         EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17658                    rm.Encode(5, 0));
17659         AdvanceIT();
17660         return;
17661       }
17662     }
17663   } else {
17664     // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17665     if (dt.Is(F32)) {
17666       if (cond.Is(al)) {
17667         EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17668                 rm.Encode(5, 0));
17669         return;
17670       }
17671     }
17672   }
17673   Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17674 }
17675 
vfma(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)17676 void Assembler::vfma(
17677     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17678   VIXL_ASSERT(AllowAssembler());
17679   CheckIT(cond);
17680   if (IsUsingT32()) {
17681     // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17682     if (dt.Is(F32)) {
17683       EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17684                  rm.Encode(5, 0));
17685       AdvanceIT();
17686       return;
17687     }
17688   } else {
17689     // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17690     if (dt.Is(F32) && cond.IsNotNever()) {
17691       EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17692               rn.Encode(7, 16) | rm.Encode(5, 0));
17693       return;
17694     }
17695   }
17696   Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17697 }
17698 
vfms(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17699 void Assembler::vfms(
17700     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17701   VIXL_ASSERT(AllowAssembler());
17702   CheckIT(cond);
17703   if (IsUsingT32()) {
17704     // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17705     if (dt.Is(F32)) {
17706       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17707         EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17708                    rm.Encode(5, 0));
17709         AdvanceIT();
17710         return;
17711       }
17712     }
17713     // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17714     if (dt.Is(F64)) {
17715       EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17716                  rm.Encode(5, 0));
17717       AdvanceIT();
17718       return;
17719     }
17720   } else {
17721     // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17722     if (dt.Is(F32)) {
17723       if (cond.Is(al)) {
17724         EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17725                 rm.Encode(5, 0));
17726         return;
17727       }
17728     }
17729     // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17730     if (dt.Is(F64) && cond.IsNotNever()) {
17731       EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17732               rn.Encode(7, 16) | rm.Encode(5, 0));
17733       return;
17734     }
17735   }
17736   Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17737 }
17738 
vfms(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)17739 void Assembler::vfms(
17740     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17741   VIXL_ASSERT(AllowAssembler());
17742   CheckIT(cond);
17743   if (IsUsingT32()) {
17744     // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17745     if (dt.Is(F32)) {
17746       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17747         EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17748                    rm.Encode(5, 0));
17749         AdvanceIT();
17750         return;
17751       }
17752     }
17753   } else {
17754     // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17755     if (dt.Is(F32)) {
17756       if (cond.Is(al)) {
17757         EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17758                 rm.Encode(5, 0));
17759         return;
17760       }
17761     }
17762   }
17763   Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17764 }
17765 
vfms(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)17766 void Assembler::vfms(
17767     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17768   VIXL_ASSERT(AllowAssembler());
17769   CheckIT(cond);
17770   if (IsUsingT32()) {
17771     // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17772     if (dt.Is(F32)) {
17773       EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17774                  rm.Encode(5, 0));
17775       AdvanceIT();
17776       return;
17777     }
17778   } else {
17779     // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17780     if (dt.Is(F32) && cond.IsNotNever()) {
17781       EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17782               rn.Encode(7, 16) | rm.Encode(5, 0));
17783       return;
17784     }
17785   }
17786   Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17787 }
17788 
vfnma(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)17789 void Assembler::vfnma(
17790     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17791   VIXL_ASSERT(AllowAssembler());
17792   CheckIT(cond);
17793   if (IsUsingT32()) {
17794     // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17795     if (dt.Is(F32)) {
17796       EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17797                  rm.Encode(5, 0));
17798       AdvanceIT();
17799       return;
17800     }
17801   } else {
17802     // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17803     if (dt.Is(F32) && cond.IsNotNever()) {
17804       EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17805               rn.Encode(7, 16) | rm.Encode(5, 0));
17806       return;
17807     }
17808   }
17809   Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17810 }
17811 
vfnma(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17812 void Assembler::vfnma(
17813     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17814   VIXL_ASSERT(AllowAssembler());
17815   CheckIT(cond);
17816   if (IsUsingT32()) {
17817     // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17818     if (dt.Is(F64)) {
17819       EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17820                  rm.Encode(5, 0));
17821       AdvanceIT();
17822       return;
17823     }
17824   } else {
17825     // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17826     if (dt.Is(F64) && cond.IsNotNever()) {
17827       EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17828               rn.Encode(7, 16) | rm.Encode(5, 0));
17829       return;
17830     }
17831   }
17832   Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17833 }
17834 
vfnms(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)17835 void Assembler::vfnms(
17836     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17837   VIXL_ASSERT(AllowAssembler());
17838   CheckIT(cond);
17839   if (IsUsingT32()) {
17840     // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17841     if (dt.Is(F32)) {
17842       EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17843                  rm.Encode(5, 0));
17844       AdvanceIT();
17845       return;
17846     }
17847   } else {
17848     // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17849     if (dt.Is(F32) && cond.IsNotNever()) {
17850       EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17851               rn.Encode(7, 16) | rm.Encode(5, 0));
17852       return;
17853     }
17854   }
17855   Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17856 }
17857 
vfnms(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17858 void Assembler::vfnms(
17859     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17860   VIXL_ASSERT(AllowAssembler());
17861   CheckIT(cond);
17862   if (IsUsingT32()) {
17863     // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17864     if (dt.Is(F64)) {
17865       EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17866                  rm.Encode(5, 0));
17867       AdvanceIT();
17868       return;
17869     }
17870   } else {
17871     // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17872     if (dt.Is(F64) && cond.IsNotNever()) {
17873       EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17874               rn.Encode(7, 16) | rm.Encode(5, 0));
17875       return;
17876     }
17877   }
17878   Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17879 }
17880 
vhadd(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17881 void Assembler::vhadd(
17882     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17883   VIXL_ASSERT(AllowAssembler());
17884   CheckIT(cond);
17885   Dt_U_size_1 encoded_dt(dt);
17886   if (IsUsingT32()) {
17887     // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17888     if (encoded_dt.IsValid()) {
17889       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17890         EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17891                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17892                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17893         AdvanceIT();
17894         return;
17895       }
17896     }
17897   } else {
17898     // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17899     if (encoded_dt.IsValid()) {
17900       if (cond.Is(al)) {
17901         EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17902                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17903                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17904         return;
17905       }
17906     }
17907   }
17908   Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17909 }
17910 
vhadd(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)17911 void Assembler::vhadd(
17912     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17913   VIXL_ASSERT(AllowAssembler());
17914   CheckIT(cond);
17915   Dt_U_size_1 encoded_dt(dt);
17916   if (IsUsingT32()) {
17917     // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17918     if (encoded_dt.IsValid()) {
17919       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17920         EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17921                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17922                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17923         AdvanceIT();
17924         return;
17925       }
17926     }
17927   } else {
17928     // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17929     if (encoded_dt.IsValid()) {
17930       if (cond.Is(al)) {
17931         EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17932                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17933                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17934         return;
17935       }
17936     }
17937   }
17938   Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17939 }
17940 
vhsub(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)17941 void Assembler::vhsub(
17942     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17943   VIXL_ASSERT(AllowAssembler());
17944   CheckIT(cond);
17945   Dt_U_size_1 encoded_dt(dt);
17946   if (IsUsingT32()) {
17947     // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17948     if (encoded_dt.IsValid()) {
17949       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17950         EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17951                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17952                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17953         AdvanceIT();
17954         return;
17955       }
17956     }
17957   } else {
17958     // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17959     if (encoded_dt.IsValid()) {
17960       if (cond.Is(al)) {
17961         EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17962                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17963                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17964         return;
17965       }
17966     }
17967   }
17968   Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17969 }
17970 
vhsub(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)17971 void Assembler::vhsub(
17972     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17973   VIXL_ASSERT(AllowAssembler());
17974   CheckIT(cond);
17975   Dt_U_size_1 encoded_dt(dt);
17976   if (IsUsingT32()) {
17977     // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17978     if (encoded_dt.IsValid()) {
17979       if (cond.Is(al) || AllowStronglyDiscouraged()) {
17980         EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17981                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17982                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17983         AdvanceIT();
17984         return;
17985       }
17986     }
17987   } else {
17988     // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17989     if (encoded_dt.IsValid()) {
17990       if (cond.Is(al)) {
17991         EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17992                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17993                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17994         return;
17995       }
17996     }
17997   }
17998   Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17999 }
18000 
vld1(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)18001 void Assembler::vld1(Condition cond,
18002                      DataType dt,
18003                      const NeonRegisterList& nreglist,
18004                      const AlignedMemOperand& operand) {
18005   VIXL_ASSERT(AllowAssembler());
18006   CheckIT(cond);
18007   if (operand.IsImmediateZero()) {
18008     Register rn = operand.GetBaseRegister();
18009     Alignment align = operand.GetAlignment();
18010     Dt_size_6 encoded_dt(dt);
18011     Dt_size_7 encoded_dt_2(dt);
18012     Align_align_1 encoded_align_1(align, nreglist);
18013     Align_a_1 encoded_align_2(align, dt);
18014     Align_index_align_1 encoded_align_3(align, nreglist, dt);
18015     if (IsUsingT32()) {
18016       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18017       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18018           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18019           operand.IsOffset() && encoded_align_1.IsValid() &&
18020           (!rn.IsPC() || AllowUnpredictable())) {
18021         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18022           const DRegister& first = nreglist.GetFirstDRegister();
18023           uint32_t len_encoding;
18024           switch (nreglist.GetLength()) {
18025             default:
18026               VIXL_UNREACHABLE_OR_FALLTHROUGH();
18027             case 1:
18028               len_encoding = 0x7;
18029               break;
18030             case 2:
18031               len_encoding = 0xa;
18032               break;
18033             case 3:
18034               len_encoding = 0x6;
18035               break;
18036             case 4:
18037               len_encoding = 0x2;
18038               break;
18039           }
18040           EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18041                      (encoded_align_1.GetEncodingValue() << 4) |
18042                      first.Encode(22, 12) | (len_encoding << 8) |
18043                      (rn.GetCode() << 16));
18044           AdvanceIT();
18045           return;
18046         }
18047       }
18048       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18049       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18050           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18051           operand.IsPostIndex() && encoded_align_1.IsValid() &&
18052           (!rn.IsPC() || AllowUnpredictable())) {
18053         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18054           const DRegister& first = nreglist.GetFirstDRegister();
18055           uint32_t len_encoding;
18056           switch (nreglist.GetLength()) {
18057             default:
18058               VIXL_UNREACHABLE_OR_FALLTHROUGH();
18059             case 1:
18060               len_encoding = 0x7;
18061               break;
18062             case 2:
18063               len_encoding = 0xa;
18064               break;
18065             case 3:
18066               len_encoding = 0x6;
18067               break;
18068             case 4:
18069               len_encoding = 0x2;
18070               break;
18071           }
18072           EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18073                      (encoded_align_1.GetEncodingValue() << 4) |
18074                      first.Encode(22, 12) | (len_encoding << 8) |
18075                      (rn.GetCode() << 16));
18076           AdvanceIT();
18077           return;
18078         }
18079       }
18080       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18081       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18082           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18083           operand.IsOffset() && encoded_align_2.IsValid() &&
18084           (!rn.IsPC() || AllowUnpredictable())) {
18085         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18086           const DRegister& first = nreglist.GetFirstDRegister();
18087           uint32_t len_encoding = nreglist.GetLength() - 1;
18088           EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18089                      (encoded_align_2.GetEncodingValue() << 4) |
18090                      first.Encode(22, 12) | (len_encoding << 5) |
18091                      (rn.GetCode() << 16));
18092           AdvanceIT();
18093           return;
18094         }
18095       }
18096       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18097       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18098           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18099           operand.IsPostIndex() && encoded_align_2.IsValid() &&
18100           (!rn.IsPC() || AllowUnpredictable())) {
18101         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18102           const DRegister& first = nreglist.GetFirstDRegister();
18103           uint32_t len_encoding = nreglist.GetLength() - 1;
18104           EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18105                      (encoded_align_2.GetEncodingValue() << 4) |
18106                      first.Encode(22, 12) | (len_encoding << 5) |
18107                      (rn.GetCode() << 16));
18108           AdvanceIT();
18109           return;
18110         }
18111       }
18112       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18113       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18114           (nreglist.GetLength() == 1) && operand.IsOffset() &&
18115           encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18116         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18117           const DRegister& first = nreglist.GetFirstDRegister();
18118           EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18119                      (encoded_align_3.GetEncodingValue() << 4) |
18120                      first.Encode(22, 12) | (rn.GetCode() << 16));
18121           AdvanceIT();
18122           return;
18123         }
18124       }
18125       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18126       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18127           (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
18128           encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18129         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18130           const DRegister& first = nreglist.GetFirstDRegister();
18131           EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18132                      (encoded_align_3.GetEncodingValue() << 4) |
18133                      first.Encode(22, 12) | (rn.GetCode() << 16));
18134           AdvanceIT();
18135           return;
18136         }
18137       }
18138     } else {
18139       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18140       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18141           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18142           operand.IsOffset() && encoded_align_1.IsValid() &&
18143           (!rn.IsPC() || AllowUnpredictable())) {
18144         if (cond.Is(al)) {
18145           const DRegister& first = nreglist.GetFirstDRegister();
18146           uint32_t len_encoding;
18147           switch (nreglist.GetLength()) {
18148             default:
18149               VIXL_UNREACHABLE_OR_FALLTHROUGH();
18150             case 1:
18151               len_encoding = 0x7;
18152               break;
18153             case 2:
18154               len_encoding = 0xa;
18155               break;
18156             case 3:
18157               len_encoding = 0x6;
18158               break;
18159             case 4:
18160               len_encoding = 0x2;
18161               break;
18162           }
18163           EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18164                   (encoded_align_1.GetEncodingValue() << 4) |
18165                   first.Encode(22, 12) | (len_encoding << 8) |
18166                   (rn.GetCode() << 16));
18167           return;
18168         }
18169       }
18170       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18171       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18172           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18173           operand.IsPostIndex() && encoded_align_1.IsValid() &&
18174           (!rn.IsPC() || AllowUnpredictable())) {
18175         if (cond.Is(al)) {
18176           const DRegister& first = nreglist.GetFirstDRegister();
18177           uint32_t len_encoding;
18178           switch (nreglist.GetLength()) {
18179             default:
18180               VIXL_UNREACHABLE_OR_FALLTHROUGH();
18181             case 1:
18182               len_encoding = 0x7;
18183               break;
18184             case 2:
18185               len_encoding = 0xa;
18186               break;
18187             case 3:
18188               len_encoding = 0x6;
18189               break;
18190             case 4:
18191               len_encoding = 0x2;
18192               break;
18193           }
18194           EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18195                   (encoded_align_1.GetEncodingValue() << 4) |
18196                   first.Encode(22, 12) | (len_encoding << 8) |
18197                   (rn.GetCode() << 16));
18198           return;
18199         }
18200       }
18201       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18202       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18203           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18204           operand.IsOffset() && encoded_align_2.IsValid() &&
18205           (!rn.IsPC() || AllowUnpredictable())) {
18206         if (cond.Is(al)) {
18207           const DRegister& first = nreglist.GetFirstDRegister();
18208           uint32_t len_encoding = nreglist.GetLength() - 1;
18209           EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18210                   (encoded_align_2.GetEncodingValue() << 4) |
18211                   first.Encode(22, 12) | (len_encoding << 5) |
18212                   (rn.GetCode() << 16));
18213           return;
18214         }
18215       }
18216       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18217       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18218           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18219           operand.IsPostIndex() && encoded_align_2.IsValid() &&
18220           (!rn.IsPC() || AllowUnpredictable())) {
18221         if (cond.Is(al)) {
18222           const DRegister& first = nreglist.GetFirstDRegister();
18223           uint32_t len_encoding = nreglist.GetLength() - 1;
18224           EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18225                   (encoded_align_2.GetEncodingValue() << 4) |
18226                   first.Encode(22, 12) | (len_encoding << 5) |
18227                   (rn.GetCode() << 16));
18228           return;
18229         }
18230       }
18231       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18232       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18233           (nreglist.GetLength() == 1) && operand.IsOffset() &&
18234           encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18235         if (cond.Is(al)) {
18236           const DRegister& first = nreglist.GetFirstDRegister();
18237           EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18238                   (encoded_align_3.GetEncodingValue() << 4) |
18239                   first.Encode(22, 12) | (rn.GetCode() << 16));
18240           return;
18241         }
18242       }
18243       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18244       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18245           (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
18246           encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18247         if (cond.Is(al)) {
18248           const DRegister& first = nreglist.GetFirstDRegister();
18249           EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18250                   (encoded_align_3.GetEncodingValue() << 4) |
18251                   first.Encode(22, 12) | (rn.GetCode() << 16));
18252           return;
18253         }
18254       }
18255     }
18256   }
18257   if (operand.IsPlainRegister()) {
18258     Register rn = operand.GetBaseRegister();
18259     Alignment align = operand.GetAlignment();
18260     Register rm = operand.GetOffsetRegister();
18261     Dt_size_6 encoded_dt(dt);
18262     Dt_size_7 encoded_dt_2(dt);
18263     Align_align_1 encoded_align_1(align, nreglist);
18264     Align_a_1 encoded_align_2(align, dt);
18265     Align_index_align_1 encoded_align_3(align, nreglist, dt);
18266     if (IsUsingT32()) {
18267       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18268       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18269           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18270           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18271         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18272           const DRegister& first = nreglist.GetFirstDRegister();
18273           uint32_t len_encoding;
18274           switch (nreglist.GetLength()) {
18275             default:
18276               VIXL_UNREACHABLE_OR_FALLTHROUGH();
18277             case 1:
18278               len_encoding = 0x7;
18279               break;
18280             case 2:
18281               len_encoding = 0xa;
18282               break;
18283             case 3:
18284               len_encoding = 0x6;
18285               break;
18286             case 4:
18287               len_encoding = 0x2;
18288               break;
18289           }
18290           EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18291                      (encoded_align_1.GetEncodingValue() << 4) |
18292                      first.Encode(22, 12) | (len_encoding << 8) |
18293                      (rn.GetCode() << 16) | rm.GetCode());
18294           AdvanceIT();
18295           return;
18296         }
18297       }
18298       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18299       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18300           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18301           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18302         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18303           const DRegister& first = nreglist.GetFirstDRegister();
18304           uint32_t len_encoding = nreglist.GetLength() - 1;
18305           EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18306                      (encoded_align_2.GetEncodingValue() << 4) |
18307                      first.Encode(22, 12) | (len_encoding << 5) |
18308                      (rn.GetCode() << 16) | rm.GetCode());
18309           AdvanceIT();
18310           return;
18311         }
18312       }
18313       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18314       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18315           (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18316           (!rn.IsPC() || AllowUnpredictable())) {
18317         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18318           const DRegister& first = nreglist.GetFirstDRegister();
18319           EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18320                      (encoded_align_3.GetEncodingValue() << 4) |
18321                      first.Encode(22, 12) | (rn.GetCode() << 16) |
18322                      rm.GetCode());
18323           AdvanceIT();
18324           return;
18325         }
18326       }
18327     } else {
18328       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18329       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18330           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18331           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18332         if (cond.Is(al)) {
18333           const DRegister& first = nreglist.GetFirstDRegister();
18334           uint32_t len_encoding;
18335           switch (nreglist.GetLength()) {
18336             default:
18337               VIXL_UNREACHABLE_OR_FALLTHROUGH();
18338             case 1:
18339               len_encoding = 0x7;
18340               break;
18341             case 2:
18342               len_encoding = 0xa;
18343               break;
18344             case 3:
18345               len_encoding = 0x6;
18346               break;
18347             case 4:
18348               len_encoding = 0x2;
18349               break;
18350           }
18351           EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18352                   (encoded_align_1.GetEncodingValue() << 4) |
18353                   first.Encode(22, 12) | (len_encoding << 8) |
18354                   (rn.GetCode() << 16) | rm.GetCode());
18355           return;
18356         }
18357       }
18358       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18359       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18360           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18361           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18362         if (cond.Is(al)) {
18363           const DRegister& first = nreglist.GetFirstDRegister();
18364           uint32_t len_encoding = nreglist.GetLength() - 1;
18365           EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18366                   (encoded_align_2.GetEncodingValue() << 4) |
18367                   first.Encode(22, 12) | (len_encoding << 5) |
18368                   (rn.GetCode() << 16) | rm.GetCode());
18369           return;
18370         }
18371       }
18372       // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18373       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18374           (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18375           (!rn.IsPC() || AllowUnpredictable())) {
18376         if (cond.Is(al)) {
18377           const DRegister& first = nreglist.GetFirstDRegister();
18378           EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18379                   (encoded_align_3.GetEncodingValue() << 4) |
18380                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18381           return;
18382         }
18383       }
18384     }
18385   }
18386   Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
18387 }
18388 
vld2(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)18389 void Assembler::vld2(Condition cond,
18390                      DataType dt,
18391                      const NeonRegisterList& nreglist,
18392                      const AlignedMemOperand& operand) {
18393   VIXL_ASSERT(AllowAssembler());
18394   CheckIT(cond);
18395   if (operand.IsImmediateZero()) {
18396     Register rn = operand.GetBaseRegister();
18397     Alignment align = operand.GetAlignment();
18398     Dt_size_7 encoded_dt(dt);
18399     Align_align_2 encoded_align_1(align, nreglist);
18400     Align_a_2 encoded_align_2(align, dt);
18401     Align_index_align_2 encoded_align_3(align, nreglist, dt);
18402     if (IsUsingT32()) {
18403       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18404       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18405           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18406            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18407            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18408           operand.IsOffset() && encoded_align_1.IsValid() &&
18409           (!rn.IsPC() || AllowUnpredictable())) {
18410         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18411           const DRegister& first = nreglist.GetFirstDRegister();
18412           uint32_t len_encoding;
18413           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18414             len_encoding = 0x8;
18415           }
18416           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18417             len_encoding = 0x9;
18418           }
18419           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18420             len_encoding = 0x3;
18421           }
18422           EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18423                      (encoded_align_1.GetEncodingValue() << 4) |
18424                      first.Encode(22, 12) | (len_encoding << 8) |
18425                      (rn.GetCode() << 16));
18426           AdvanceIT();
18427           return;
18428         }
18429       }
18430       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18431       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18432           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18433            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18434            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18435           operand.IsPostIndex() && encoded_align_1.IsValid() &&
18436           (!rn.IsPC() || AllowUnpredictable())) {
18437         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18438           const DRegister& first = nreglist.GetFirstDRegister();
18439           uint32_t len_encoding;
18440           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18441             len_encoding = 0x8;
18442           }
18443           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18444             len_encoding = 0x9;
18445           }
18446           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18447             len_encoding = 0x3;
18448           }
18449           EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18450                      (encoded_align_1.GetEncodingValue() << 4) |
18451                      first.Encode(22, 12) | (len_encoding << 8) |
18452                      (rn.GetCode() << 16));
18453           AdvanceIT();
18454           return;
18455         }
18456       }
18457       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18458       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18459           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18460            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18461           operand.IsOffset() && encoded_align_2.IsValid() &&
18462           (!rn.IsPC() || AllowUnpredictable())) {
18463         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18464           const DRegister& first = nreglist.GetFirstDRegister();
18465           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18466           EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18467                      (encoded_align_2.GetEncodingValue() << 4) |
18468                      first.Encode(22, 12) | (len_encoding << 5) |
18469                      (rn.GetCode() << 16));
18470           AdvanceIT();
18471           return;
18472         }
18473       }
18474       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18475       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18476           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18477            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18478           operand.IsPostIndex() && encoded_align_2.IsValid() &&
18479           (!rn.IsPC() || AllowUnpredictable())) {
18480         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18481           const DRegister& first = nreglist.GetFirstDRegister();
18482           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18483           EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18484                      (encoded_align_2.GetEncodingValue() << 4) |
18485                      first.Encode(22, 12) | (len_encoding << 5) |
18486                      (rn.GetCode() << 16));
18487           AdvanceIT();
18488           return;
18489         }
18490       }
18491       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18492       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18493           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18494            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18495           operand.IsOffset() && encoded_align_3.IsValid() &&
18496           (!rn.IsPC() || AllowUnpredictable())) {
18497         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18498           const DRegister& first = nreglist.GetFirstDRegister();
18499           EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18500                      (encoded_align_3.GetEncodingValue() << 4) |
18501                      first.Encode(22, 12) | (rn.GetCode() << 16));
18502           AdvanceIT();
18503           return;
18504         }
18505       }
18506       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18507       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18508           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18509            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18510           operand.IsPostIndex() && encoded_align_3.IsValid() &&
18511           (!rn.IsPC() || AllowUnpredictable())) {
18512         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18513           const DRegister& first = nreglist.GetFirstDRegister();
18514           EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18515                      (encoded_align_3.GetEncodingValue() << 4) |
18516                      first.Encode(22, 12) | (rn.GetCode() << 16));
18517           AdvanceIT();
18518           return;
18519         }
18520       }
18521     } else {
18522       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18523       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18524           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18525            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18526            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18527           operand.IsOffset() && encoded_align_1.IsValid() &&
18528           (!rn.IsPC() || AllowUnpredictable())) {
18529         if (cond.Is(al)) {
18530           const DRegister& first = nreglist.GetFirstDRegister();
18531           uint32_t len_encoding;
18532           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18533             len_encoding = 0x8;
18534           }
18535           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18536             len_encoding = 0x9;
18537           }
18538           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18539             len_encoding = 0x3;
18540           }
18541           EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18542                   (encoded_align_1.GetEncodingValue() << 4) |
18543                   first.Encode(22, 12) | (len_encoding << 8) |
18544                   (rn.GetCode() << 16));
18545           return;
18546         }
18547       }
18548       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18549       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18550           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18551            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18552            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18553           operand.IsPostIndex() && encoded_align_1.IsValid() &&
18554           (!rn.IsPC() || AllowUnpredictable())) {
18555         if (cond.Is(al)) {
18556           const DRegister& first = nreglist.GetFirstDRegister();
18557           uint32_t len_encoding;
18558           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18559             len_encoding = 0x8;
18560           }
18561           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18562             len_encoding = 0x9;
18563           }
18564           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18565             len_encoding = 0x3;
18566           }
18567           EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18568                   (encoded_align_1.GetEncodingValue() << 4) |
18569                   first.Encode(22, 12) | (len_encoding << 8) |
18570                   (rn.GetCode() << 16));
18571           return;
18572         }
18573       }
18574       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18575       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18576           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18577            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18578           operand.IsOffset() && encoded_align_2.IsValid() &&
18579           (!rn.IsPC() || AllowUnpredictable())) {
18580         if (cond.Is(al)) {
18581           const DRegister& first = nreglist.GetFirstDRegister();
18582           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18583           EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18584                   (encoded_align_2.GetEncodingValue() << 4) |
18585                   first.Encode(22, 12) | (len_encoding << 5) |
18586                   (rn.GetCode() << 16));
18587           return;
18588         }
18589       }
18590       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18591       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18592           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18593            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18594           operand.IsPostIndex() && encoded_align_2.IsValid() &&
18595           (!rn.IsPC() || AllowUnpredictable())) {
18596         if (cond.Is(al)) {
18597           const DRegister& first = nreglist.GetFirstDRegister();
18598           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18599           EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18600                   (encoded_align_2.GetEncodingValue() << 4) |
18601                   first.Encode(22, 12) | (len_encoding << 5) |
18602                   (rn.GetCode() << 16));
18603           return;
18604         }
18605       }
18606       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18607       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18608           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18609            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18610           operand.IsOffset() && encoded_align_3.IsValid() &&
18611           (!rn.IsPC() || AllowUnpredictable())) {
18612         if (cond.Is(al)) {
18613           const DRegister& first = nreglist.GetFirstDRegister();
18614           EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18615                   (encoded_align_3.GetEncodingValue() << 4) |
18616                   first.Encode(22, 12) | (rn.GetCode() << 16));
18617           return;
18618         }
18619       }
18620       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18621       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18622           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18623            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18624           operand.IsPostIndex() && encoded_align_3.IsValid() &&
18625           (!rn.IsPC() || AllowUnpredictable())) {
18626         if (cond.Is(al)) {
18627           const DRegister& first = nreglist.GetFirstDRegister();
18628           EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18629                   (encoded_align_3.GetEncodingValue() << 4) |
18630                   first.Encode(22, 12) | (rn.GetCode() << 16));
18631           return;
18632         }
18633       }
18634     }
18635   }
18636   if (operand.IsPlainRegister()) {
18637     Register rn = operand.GetBaseRegister();
18638     Alignment align = operand.GetAlignment();
18639     Register rm = operand.GetOffsetRegister();
18640     Dt_size_7 encoded_dt(dt);
18641     Align_align_2 encoded_align_1(align, nreglist);
18642     Align_a_2 encoded_align_2(align, dt);
18643     Align_index_align_2 encoded_align_3(align, nreglist, dt);
18644     if (IsUsingT32()) {
18645       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18646       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18647           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18648            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18649            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18650           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18651         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18652           const DRegister& first = nreglist.GetFirstDRegister();
18653           uint32_t len_encoding;
18654           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18655             len_encoding = 0x8;
18656           }
18657           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18658             len_encoding = 0x9;
18659           }
18660           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18661             len_encoding = 0x3;
18662           }
18663           EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18664                      (encoded_align_1.GetEncodingValue() << 4) |
18665                      first.Encode(22, 12) | (len_encoding << 8) |
18666                      (rn.GetCode() << 16) | rm.GetCode());
18667           AdvanceIT();
18668           return;
18669         }
18670       }
18671       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18672       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18673           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18674            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18675           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18676         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18677           const DRegister& first = nreglist.GetFirstDRegister();
18678           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18679           EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18680                      (encoded_align_2.GetEncodingValue() << 4) |
18681                      first.Encode(22, 12) | (len_encoding << 5) |
18682                      (rn.GetCode() << 16) | rm.GetCode());
18683           AdvanceIT();
18684           return;
18685         }
18686       }
18687       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18688       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18689           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18690            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18691           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18692         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18693           const DRegister& first = nreglist.GetFirstDRegister();
18694           EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
18695                      (encoded_align_3.GetEncodingValue() << 4) |
18696                      first.Encode(22, 12) | (rn.GetCode() << 16) |
18697                      rm.GetCode());
18698           AdvanceIT();
18699           return;
18700         }
18701       }
18702     } else {
18703       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18704       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18705           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18706            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18707            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18708           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18709         if (cond.Is(al)) {
18710           const DRegister& first = nreglist.GetFirstDRegister();
18711           uint32_t len_encoding;
18712           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18713             len_encoding = 0x8;
18714           }
18715           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18716             len_encoding = 0x9;
18717           }
18718           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18719             len_encoding = 0x3;
18720           }
18721           EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18722                   (encoded_align_1.GetEncodingValue() << 4) |
18723                   first.Encode(22, 12) | (len_encoding << 8) |
18724                   (rn.GetCode() << 16) | rm.GetCode());
18725           return;
18726         }
18727       }
18728       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18729       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18730           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18731            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18732           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18733         if (cond.Is(al)) {
18734           const DRegister& first = nreglist.GetFirstDRegister();
18735           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18736           EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18737                   (encoded_align_2.GetEncodingValue() << 4) |
18738                   first.Encode(22, 12) | (len_encoding << 5) |
18739                   (rn.GetCode() << 16) | rm.GetCode());
18740           return;
18741         }
18742       }
18743       // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18744       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18745           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18746            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18747           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18748         if (cond.Is(al)) {
18749           const DRegister& first = nreglist.GetFirstDRegister();
18750           EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
18751                   (encoded_align_3.GetEncodingValue() << 4) |
18752                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18753           return;
18754         }
18755       }
18756     }
18757   }
18758   Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
18759 }
18760 
vld3(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)18761 void Assembler::vld3(Condition cond,
18762                      DataType dt,
18763                      const NeonRegisterList& nreglist,
18764                      const AlignedMemOperand& operand) {
18765   VIXL_ASSERT(AllowAssembler());
18766   CheckIT(cond);
18767   if (operand.IsImmediateZero()) {
18768     Register rn = operand.GetBaseRegister();
18769     Alignment align = operand.GetAlignment();
18770     Dt_size_7 encoded_dt(dt);
18771     Align_align_3 encoded_align_1(align);
18772     if (IsUsingT32()) {
18773       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18774       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18775           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18776            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18777           operand.IsOffset() && encoded_align_1.IsValid() &&
18778           (!rn.IsPC() || AllowUnpredictable())) {
18779         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18780           const DRegister& first = nreglist.GetFirstDRegister();
18781           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18782           EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18783                      (encoded_align_1.GetEncodingValue() << 4) |
18784                      first.Encode(22, 12) | (len_encoding << 8) |
18785                      (rn.GetCode() << 16));
18786           AdvanceIT();
18787           return;
18788         }
18789       }
18790       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18791       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18792           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18793            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18794           operand.IsPostIndex() && encoded_align_1.IsValid() &&
18795           (!rn.IsPC() || AllowUnpredictable())) {
18796         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18797           const DRegister& first = nreglist.GetFirstDRegister();
18798           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18799           EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18800                      (encoded_align_1.GetEncodingValue() << 4) |
18801                      first.Encode(22, 12) | (len_encoding << 8) |
18802                      (rn.GetCode() << 16));
18803           AdvanceIT();
18804           return;
18805         }
18806       }
18807     } else {
18808       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18809       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18810           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18811            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18812           operand.IsOffset() && encoded_align_1.IsValid() &&
18813           (!rn.IsPC() || AllowUnpredictable())) {
18814         if (cond.Is(al)) {
18815           const DRegister& first = nreglist.GetFirstDRegister();
18816           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18817           EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18818                   (encoded_align_1.GetEncodingValue() << 4) |
18819                   first.Encode(22, 12) | (len_encoding << 8) |
18820                   (rn.GetCode() << 16));
18821           return;
18822         }
18823       }
18824       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18825       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18826           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18827            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18828           operand.IsPostIndex() && encoded_align_1.IsValid() &&
18829           (!rn.IsPC() || AllowUnpredictable())) {
18830         if (cond.Is(al)) {
18831           const DRegister& first = nreglist.GetFirstDRegister();
18832           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18833           EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18834                   (encoded_align_1.GetEncodingValue() << 4) |
18835                   first.Encode(22, 12) | (len_encoding << 8) |
18836                   (rn.GetCode() << 16));
18837           return;
18838         }
18839       }
18840     }
18841   }
18842   if (operand.IsPlainRegister()) {
18843     Register rn = operand.GetBaseRegister();
18844     Alignment align = operand.GetAlignment();
18845     Register rm = operand.GetOffsetRegister();
18846     Dt_size_7 encoded_dt(dt);
18847     Align_align_3 encoded_align_1(align);
18848     if (IsUsingT32()) {
18849       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18850       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18851           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18852            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18853           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18854         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18855           const DRegister& first = nreglist.GetFirstDRegister();
18856           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18857           EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18858                      (encoded_align_1.GetEncodingValue() << 4) |
18859                      first.Encode(22, 12) | (len_encoding << 8) |
18860                      (rn.GetCode() << 16) | rm.GetCode());
18861           AdvanceIT();
18862           return;
18863         }
18864       }
18865     } else {
18866       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18867       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18868           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18869            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18870           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18871         if (cond.Is(al)) {
18872           const DRegister& first = nreglist.GetFirstDRegister();
18873           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18874           EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18875                   (encoded_align_1.GetEncodingValue() << 4) |
18876                   first.Encode(22, 12) | (len_encoding << 8) |
18877                   (rn.GetCode() << 16) | rm.GetCode());
18878           return;
18879         }
18880       }
18881     }
18882   }
18883   Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
18884 }
18885 
vld3(Condition cond,DataType dt,const NeonRegisterList & nreglist,const MemOperand & operand)18886 void Assembler::vld3(Condition cond,
18887                      DataType dt,
18888                      const NeonRegisterList& nreglist,
18889                      const MemOperand& operand) {
18890   VIXL_ASSERT(AllowAssembler());
18891   CheckIT(cond);
18892   if (operand.IsImmediateZero()) {
18893     Register rn = operand.GetBaseRegister();
18894     Dt_size_7 encoded_dt(dt);
18895     Index_1 encoded_align_1(nreglist, dt);
18896     if (IsUsingT32()) {
18897       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18898       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18899           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18900            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18901           operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18902         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18903           const DRegister& first = nreglist.GetFirstDRegister();
18904           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18905           EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18906                      first.Encode(22, 12) | (len_encoding << 5) |
18907                      (rn.GetCode() << 16));
18908           AdvanceIT();
18909           return;
18910         }
18911       }
18912       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18913       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18914           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18915            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18916           operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18917         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18918           const DRegister& first = nreglist.GetFirstDRegister();
18919           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18920           EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18921                      first.Encode(22, 12) | (len_encoding << 5) |
18922                      (rn.GetCode() << 16));
18923           AdvanceIT();
18924           return;
18925         }
18926       }
18927       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18928       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18929           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18930            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18931           operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18932         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18933           const DRegister& first = nreglist.GetFirstDRegister();
18934           EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18935                      (encoded_align_1.GetEncodingValue() << 4) |
18936                      first.Encode(22, 12) | (rn.GetCode() << 16));
18937           AdvanceIT();
18938           return;
18939         }
18940       }
18941       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18942       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18943           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18944            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18945           operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18946         if (cond.Is(al) || AllowStronglyDiscouraged()) {
18947           const DRegister& first = nreglist.GetFirstDRegister();
18948           EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18949                      (encoded_align_1.GetEncodingValue() << 4) |
18950                      first.Encode(22, 12) | (rn.GetCode() << 16));
18951           AdvanceIT();
18952           return;
18953         }
18954       }
18955     } else {
18956       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18957       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18958           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18959            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18960           operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18961         if (cond.Is(al)) {
18962           const DRegister& first = nreglist.GetFirstDRegister();
18963           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18964           EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18965                   first.Encode(22, 12) | (len_encoding << 5) |
18966                   (rn.GetCode() << 16));
18967           return;
18968         }
18969       }
18970       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18971       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18972           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18973            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18974           operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18975         if (cond.Is(al)) {
18976           const DRegister& first = nreglist.GetFirstDRegister();
18977           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18978           EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18979                   first.Encode(22, 12) | (len_encoding << 5) |
18980                   (rn.GetCode() << 16));
18981           return;
18982         }
18983       }
18984       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18985       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18986           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18987            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18988           operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18989         if (cond.Is(al)) {
18990           const DRegister& first = nreglist.GetFirstDRegister();
18991           EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18992                   (encoded_align_1.GetEncodingValue() << 4) |
18993                   first.Encode(22, 12) | (rn.GetCode() << 16));
18994           return;
18995         }
18996       }
18997       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18998       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18999           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19000            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19001           operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
19002         if (cond.Is(al)) {
19003           const DRegister& first = nreglist.GetFirstDRegister();
19004           EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
19005                   (encoded_align_1.GetEncodingValue() << 4) |
19006                   first.Encode(22, 12) | (rn.GetCode() << 16));
19007           return;
19008         }
19009       }
19010     }
19011   }
19012   if (operand.IsPlainRegister()) {
19013     Register rn = operand.GetBaseRegister();
19014     Sign sign = operand.GetSign();
19015     Register rm = operand.GetOffsetRegister();
19016     Dt_size_7 encoded_dt(dt);
19017     Index_1 encoded_align_1(nreglist, dt);
19018     if (IsUsingT32()) {
19019       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
19020       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
19021           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19022            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19023           sign.IsPlus() && operand.IsPostIndex() &&
19024           (!rn.IsPC() || AllowUnpredictable())) {
19025         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19026           const DRegister& first = nreglist.GetFirstDRegister();
19027           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19028           EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19029                      first.Encode(22, 12) | (len_encoding << 5) |
19030                      (rn.GetCode() << 16) | rm.GetCode());
19031           AdvanceIT();
19032           return;
19033         }
19034       }
19035       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
19036       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19037           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19038            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19039           sign.IsPlus() && operand.IsPostIndex() &&
19040           (!rn.IsPC() || AllowUnpredictable())) {
19041         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19042           const DRegister& first = nreglist.GetFirstDRegister();
19043           EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
19044                      (encoded_align_1.GetEncodingValue() << 4) |
19045                      first.Encode(22, 12) | (rn.GetCode() << 16) |
19046                      rm.GetCode());
19047           AdvanceIT();
19048           return;
19049         }
19050       }
19051     } else {
19052       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19053       if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
19054           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19055            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19056           sign.IsPlus() && operand.IsPostIndex() &&
19057           (!rn.IsPC() || AllowUnpredictable())) {
19058         if (cond.Is(al)) {
19059           const DRegister& first = nreglist.GetFirstDRegister();
19060           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19061           EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19062                   first.Encode(22, 12) | (len_encoding << 5) |
19063                   (rn.GetCode() << 16) | rm.GetCode());
19064           return;
19065         }
19066       }
19067       // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19068       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19069           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19070            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19071           sign.IsPlus() && operand.IsPostIndex() &&
19072           (!rn.IsPC() || AllowUnpredictable())) {
19073         if (cond.Is(al)) {
19074           const DRegister& first = nreglist.GetFirstDRegister();
19075           EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
19076                   (encoded_align_1.GetEncodingValue() << 4) |
19077                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19078           return;
19079         }
19080       }
19081     }
19082   }
19083   Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
19084 }
19085 
vld4(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)19086 void Assembler::vld4(Condition cond,
19087                      DataType dt,
19088                      const NeonRegisterList& nreglist,
19089                      const AlignedMemOperand& operand) {
19090   VIXL_ASSERT(AllowAssembler());
19091   CheckIT(cond);
19092   if (operand.IsImmediateZero()) {
19093     Register rn = operand.GetBaseRegister();
19094     Alignment align = operand.GetAlignment();
19095     Dt_size_7 encoded_dt(dt);
19096     Dt_size_8 encoded_dt_2(dt, align);
19097     Align_align_4 encoded_align_1(align);
19098     Align_a_3 encoded_align_2(align, dt);
19099     Align_index_align_3 encoded_align_3(align, nreglist, dt);
19100     if (IsUsingT32()) {
19101       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19102       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19103           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19104            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19105           operand.IsOffset() && encoded_align_1.IsValid() &&
19106           (!rn.IsPC() || AllowUnpredictable())) {
19107         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19108           const DRegister& first = nreglist.GetFirstDRegister();
19109           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19110           EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
19111                      (encoded_align_1.GetEncodingValue() << 4) |
19112                      first.Encode(22, 12) | (len_encoding << 8) |
19113                      (rn.GetCode() << 16));
19114           AdvanceIT();
19115           return;
19116         }
19117       }
19118       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19119       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19120           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19121            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19122           operand.IsPostIndex() && encoded_align_1.IsValid() &&
19123           (!rn.IsPC() || AllowUnpredictable())) {
19124         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19125           const DRegister& first = nreglist.GetFirstDRegister();
19126           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19127           EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
19128                      (encoded_align_1.GetEncodingValue() << 4) |
19129                      first.Encode(22, 12) | (len_encoding << 8) |
19130                      (rn.GetCode() << 16));
19131           AdvanceIT();
19132           return;
19133         }
19134       }
19135       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19136       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19137           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19138            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19139           operand.IsOffset() && encoded_align_2.IsValid() &&
19140           (!rn.IsPC() || AllowUnpredictable())) {
19141         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19142           const DRegister& first = nreglist.GetFirstDRegister();
19143           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19144           EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19145                      (encoded_align_2.GetEncodingValue() << 4) |
19146                      first.Encode(22, 12) | (len_encoding << 5) |
19147                      (rn.GetCode() << 16));
19148           AdvanceIT();
19149           return;
19150         }
19151       }
19152       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19153       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19154           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19155            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19156           operand.IsPostIndex() && encoded_align_2.IsValid() &&
19157           (!rn.IsPC() || AllowUnpredictable())) {
19158         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19159           const DRegister& first = nreglist.GetFirstDRegister();
19160           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19161           EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19162                      (encoded_align_2.GetEncodingValue() << 4) |
19163                      first.Encode(22, 12) | (len_encoding << 5) |
19164                      (rn.GetCode() << 16));
19165           AdvanceIT();
19166           return;
19167         }
19168       }
19169       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19170       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19171           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19172            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19173           operand.IsOffset() && encoded_align_3.IsValid() &&
19174           (!rn.IsPC() || AllowUnpredictable())) {
19175         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19176           const DRegister& first = nreglist.GetFirstDRegister();
19177           EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19178                      (encoded_align_3.GetEncodingValue() << 4) |
19179                      first.Encode(22, 12) | (rn.GetCode() << 16));
19180           AdvanceIT();
19181           return;
19182         }
19183       }
19184       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19185       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19186           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19187            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19188           operand.IsPostIndex() && encoded_align_3.IsValid() &&
19189           (!rn.IsPC() || AllowUnpredictable())) {
19190         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19191           const DRegister& first = nreglist.GetFirstDRegister();
19192           EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19193                      (encoded_align_3.GetEncodingValue() << 4) |
19194                      first.Encode(22, 12) | (rn.GetCode() << 16));
19195           AdvanceIT();
19196           return;
19197         }
19198       }
19199     } else {
19200       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19201       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19202           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19203            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19204           operand.IsOffset() && encoded_align_1.IsValid() &&
19205           (!rn.IsPC() || AllowUnpredictable())) {
19206         if (cond.Is(al)) {
19207           const DRegister& first = nreglist.GetFirstDRegister();
19208           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19209           EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
19210                   (encoded_align_1.GetEncodingValue() << 4) |
19211                   first.Encode(22, 12) | (len_encoding << 8) |
19212                   (rn.GetCode() << 16));
19213           return;
19214         }
19215       }
19216       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19217       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19218           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19219            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19220           operand.IsPostIndex() && encoded_align_1.IsValid() &&
19221           (!rn.IsPC() || AllowUnpredictable())) {
19222         if (cond.Is(al)) {
19223           const DRegister& first = nreglist.GetFirstDRegister();
19224           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19225           EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
19226                   (encoded_align_1.GetEncodingValue() << 4) |
19227                   first.Encode(22, 12) | (len_encoding << 8) |
19228                   (rn.GetCode() << 16));
19229           return;
19230         }
19231       }
19232       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19233       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19234           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19235            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19236           operand.IsOffset() && encoded_align_2.IsValid() &&
19237           (!rn.IsPC() || AllowUnpredictable())) {
19238         if (cond.Is(al)) {
19239           const DRegister& first = nreglist.GetFirstDRegister();
19240           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19241           EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19242                   (encoded_align_2.GetEncodingValue() << 4) |
19243                   first.Encode(22, 12) | (len_encoding << 5) |
19244                   (rn.GetCode() << 16));
19245           return;
19246         }
19247       }
19248       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19249       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19250           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19251            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19252           operand.IsPostIndex() && encoded_align_2.IsValid() &&
19253           (!rn.IsPC() || AllowUnpredictable())) {
19254         if (cond.Is(al)) {
19255           const DRegister& first = nreglist.GetFirstDRegister();
19256           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19257           EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19258                   (encoded_align_2.GetEncodingValue() << 4) |
19259                   first.Encode(22, 12) | (len_encoding << 5) |
19260                   (rn.GetCode() << 16));
19261           return;
19262         }
19263       }
19264       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19265       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19266           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19267            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19268           operand.IsOffset() && encoded_align_3.IsValid() &&
19269           (!rn.IsPC() || AllowUnpredictable())) {
19270         if (cond.Is(al)) {
19271           const DRegister& first = nreglist.GetFirstDRegister();
19272           EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19273                   (encoded_align_3.GetEncodingValue() << 4) |
19274                   first.Encode(22, 12) | (rn.GetCode() << 16));
19275           return;
19276         }
19277       }
19278       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19279       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19280           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19281            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19282           operand.IsPostIndex() && encoded_align_3.IsValid() &&
19283           (!rn.IsPC() || AllowUnpredictable())) {
19284         if (cond.Is(al)) {
19285           const DRegister& first = nreglist.GetFirstDRegister();
19286           EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19287                   (encoded_align_3.GetEncodingValue() << 4) |
19288                   first.Encode(22, 12) | (rn.GetCode() << 16));
19289           return;
19290         }
19291       }
19292     }
19293   }
19294   if (operand.IsPlainRegister()) {
19295     Register rn = operand.GetBaseRegister();
19296     Alignment align = operand.GetAlignment();
19297     Register rm = operand.GetOffsetRegister();
19298     Dt_size_7 encoded_dt(dt);
19299     Dt_size_8 encoded_dt_2(dt, align);
19300     Align_align_4 encoded_align_1(align);
19301     Align_a_3 encoded_align_2(align, dt);
19302     Align_index_align_3 encoded_align_3(align, nreglist, dt);
19303     if (IsUsingT32()) {
19304       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19305       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19306           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19307            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19308           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19309         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19310           const DRegister& first = nreglist.GetFirstDRegister();
19311           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19312           EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
19313                      (encoded_align_1.GetEncodingValue() << 4) |
19314                      first.Encode(22, 12) | (len_encoding << 8) |
19315                      (rn.GetCode() << 16) | rm.GetCode());
19316           AdvanceIT();
19317           return;
19318         }
19319       }
19320       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19321       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19322           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19323            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19324           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19325         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19326           const DRegister& first = nreglist.GetFirstDRegister();
19327           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19328           EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19329                      (encoded_align_2.GetEncodingValue() << 4) |
19330                      first.Encode(22, 12) | (len_encoding << 5) |
19331                      (rn.GetCode() << 16) | rm.GetCode());
19332           AdvanceIT();
19333           return;
19334         }
19335       }
19336       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19337       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19338           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19339            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19340           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19341         if (cond.Is(al) || AllowStronglyDiscouraged()) {
19342           const DRegister& first = nreglist.GetFirstDRegister();
19343           EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
19344                      (encoded_align_3.GetEncodingValue() << 4) |
19345                      first.Encode(22, 12) | (rn.GetCode() << 16) |
19346                      rm.GetCode());
19347           AdvanceIT();
19348           return;
19349         }
19350       }
19351     } else {
19352       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19353       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19354           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19355            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19356           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19357         if (cond.Is(al)) {
19358           const DRegister& first = nreglist.GetFirstDRegister();
19359           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19360           EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
19361                   (encoded_align_1.GetEncodingValue() << 4) |
19362                   first.Encode(22, 12) | (len_encoding << 8) |
19363                   (rn.GetCode() << 16) | rm.GetCode());
19364           return;
19365         }
19366       }
19367       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19368       if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19369           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19370            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19371           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19372         if (cond.Is(al)) {
19373           const DRegister& first = nreglist.GetFirstDRegister();
19374           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19375           EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19376                   (encoded_align_2.GetEncodingValue() << 4) |
19377                   first.Encode(22, 12) | (len_encoding << 5) |
19378                   (rn.GetCode() << 16) | rm.GetCode());
19379           return;
19380         }
19381       }
19382       // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19383       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19384           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19385            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19386           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19387         if (cond.Is(al)) {
19388           const DRegister& first = nreglist.GetFirstDRegister();
19389           EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
19390                   (encoded_align_3.GetEncodingValue() << 4) |
19391                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19392           return;
19393         }
19394       }
19395     }
19396   }
19397   Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
19398 }
19399 
vldm(Condition cond,DataType dt,Register rn,WriteBack write_back,DRegisterList dreglist)19400 void Assembler::vldm(Condition cond,
19401                      DataType dt,
19402                      Register rn,
19403                      WriteBack write_back,
19404                      DRegisterList dreglist) {
19405   VIXL_ASSERT(AllowAssembler());
19406   CheckIT(cond);
19407   USE(dt);
19408   if (IsUsingT32()) {
19409     // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
19410     if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19411          AllowUnpredictable())) {
19412       const DRegister& dreg = dreglist.GetFirstDRegister();
19413       unsigned len = dreglist.GetLength() * 2;
19414       EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19415                  (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19416                  (len & 0xff));
19417       AdvanceIT();
19418       return;
19419     }
19420   } else {
19421     // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
19422     if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19423                                (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19424                               AllowUnpredictable())) {
19425       const DRegister& dreg = dreglist.GetFirstDRegister();
19426       unsigned len = dreglist.GetLength() * 2;
19427       EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19428               (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19429               (len & 0xff));
19430       return;
19431     }
19432   }
19433   Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
19434 }
19435 
vldm(Condition cond,DataType dt,Register rn,WriteBack write_back,SRegisterList sreglist)19436 void Assembler::vldm(Condition cond,
19437                      DataType dt,
19438                      Register rn,
19439                      WriteBack write_back,
19440                      SRegisterList sreglist) {
19441   VIXL_ASSERT(AllowAssembler());
19442   CheckIT(cond);
19443   USE(dt);
19444   if (IsUsingT32()) {
19445     // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
19446     if ((!rn.IsPC() || AllowUnpredictable())) {
19447       const SRegister& sreg = sreglist.GetFirstSRegister();
19448       unsigned len = sreglist.GetLength();
19449       EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19450                  (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19451                  (len & 0xff));
19452       AdvanceIT();
19453       return;
19454     }
19455   } else {
19456     // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
19457     if (cond.IsNotNever() &&
19458         ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
19459       const SRegister& sreg = sreglist.GetFirstSRegister();
19460       unsigned len = sreglist.GetLength();
19461       EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19462               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19463               (len & 0xff));
19464       return;
19465     }
19466   }
19467   Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
19468 }
19469 
vldmdb(Condition cond,DataType dt,Register rn,WriteBack write_back,DRegisterList dreglist)19470 void Assembler::vldmdb(Condition cond,
19471                        DataType dt,
19472                        Register rn,
19473                        WriteBack write_back,
19474                        DRegisterList dreglist) {
19475   VIXL_ASSERT(AllowAssembler());
19476   CheckIT(cond);
19477   USE(dt);
19478   if (IsUsingT32()) {
19479     // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
19480     if (write_back.DoesWriteBack() &&
19481         (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19482          AllowUnpredictable())) {
19483       const DRegister& dreg = dreglist.GetFirstDRegister();
19484       unsigned len = dreglist.GetLength() * 2;
19485       EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
19486                  (len & 0xff));
19487       AdvanceIT();
19488       return;
19489     }
19490   } else {
19491     // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
19492     if (write_back.DoesWriteBack() && cond.IsNotNever() &&
19493         (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19494          AllowUnpredictable())) {
19495       const DRegister& dreg = dreglist.GetFirstDRegister();
19496       unsigned len = dreglist.GetLength() * 2;
19497       EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19498               dreg.Encode(22, 12) | (len & 0xff));
19499       return;
19500     }
19501   }
19502   Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
19503 }
19504 
vldmdb(Condition cond,DataType dt,Register rn,WriteBack write_back,SRegisterList sreglist)19505 void Assembler::vldmdb(Condition cond,
19506                        DataType dt,
19507                        Register rn,
19508                        WriteBack write_back,
19509                        SRegisterList sreglist) {
19510   VIXL_ASSERT(AllowAssembler());
19511   CheckIT(cond);
19512   USE(dt);
19513   if (IsUsingT32()) {
19514     // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
19515     if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
19516       const SRegister& sreg = sreglist.GetFirstSRegister();
19517       unsigned len = sreglist.GetLength();
19518       EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
19519                  (len & 0xff));
19520       AdvanceIT();
19521       return;
19522     }
19523   } else {
19524     // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
19525     if (write_back.DoesWriteBack() && cond.IsNotNever() &&
19526         (!rn.IsPC() || AllowUnpredictable())) {
19527       const SRegister& sreg = sreglist.GetFirstSRegister();
19528       unsigned len = sreglist.GetLength();
19529       EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19530               sreg.Encode(22, 12) | (len & 0xff));
19531       return;
19532     }
19533   }
19534   Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
19535 }
19536 
vldmia(Condition cond,DataType dt,Register rn,WriteBack write_back,DRegisterList dreglist)19537 void Assembler::vldmia(Condition cond,
19538                        DataType dt,
19539                        Register rn,
19540                        WriteBack write_back,
19541                        DRegisterList dreglist) {
19542   VIXL_ASSERT(AllowAssembler());
19543   CheckIT(cond);
19544   USE(dt);
19545   if (IsUsingT32()) {
19546     // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
19547     if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19548          AllowUnpredictable())) {
19549       const DRegister& dreg = dreglist.GetFirstDRegister();
19550       unsigned len = dreglist.GetLength() * 2;
19551       EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19552                  (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19553                  (len & 0xff));
19554       AdvanceIT();
19555       return;
19556     }
19557   } else {
19558     // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
19559     if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19560                                (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19561                               AllowUnpredictable())) {
19562       const DRegister& dreg = dreglist.GetFirstDRegister();
19563       unsigned len = dreglist.GetLength() * 2;
19564       EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19565               (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19566               (len & 0xff));
19567       return;
19568     }
19569   }
19570   Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
19571 }
19572 
vldmia(Condition cond,DataType dt,Register rn,WriteBack write_back,SRegisterList sreglist)19573 void Assembler::vldmia(Condition cond,
19574                        DataType dt,
19575                        Register rn,
19576                        WriteBack write_back,
19577                        SRegisterList sreglist) {
19578   VIXL_ASSERT(AllowAssembler());
19579   CheckIT(cond);
19580   USE(dt);
19581   if (IsUsingT32()) {
19582     // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
19583     if ((!rn.IsPC() || AllowUnpredictable())) {
19584       const SRegister& sreg = sreglist.GetFirstSRegister();
19585       unsigned len = sreglist.GetLength();
19586       EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19587                  (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19588                  (len & 0xff));
19589       AdvanceIT();
19590       return;
19591     }
19592   } else {
19593     // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
19594     if (cond.IsNotNever() &&
19595         ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
19596       const SRegister& sreg = sreglist.GetFirstSRegister();
19597       unsigned len = sreglist.GetLength();
19598       EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19599               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19600               (len & 0xff));
19601       return;
19602     }
19603   }
19604   Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
19605 }
19606 
vldr(Condition cond,DataType dt,DRegister rd,Location * location)19607 void Assembler::vldr(Condition cond,
19608                      DataType dt,
19609                      DRegister rd,
19610                      Location* location) {
19611   VIXL_ASSERT(AllowAssembler());
19612   CheckIT(cond);
19613   Location::Offset offset =
19614       location->IsBound()
19615           ? location->GetLocation() -
19616                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19617           : 0;
19618   if (IsUsingT32()) {
19619     // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19620     if (dt.IsNoneOr(Untyped64) &&
19621         ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19622           ((offset & 0x3) == 0)) ||
19623          !location->IsBound())) {
19624       static class EmitOp : public Location::EmitOperator {
19625        public:
19626         EmitOp() : Location::EmitOperator(T32) {}
19627         virtual uint32_t Encode(uint32_t instr,
19628                                 Location::Offset program_counter,
19629                                 const Location* loc) const VIXL_OVERRIDE {
19630           program_counter += kT32PcDelta;
19631           Location::Offset off =
19632               loc->GetLocation() - AlignDown(program_counter, 4);
19633           VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
19634           int32_t target = off >> 2;
19635           uint32_t U = (target >= 0);
19636           target = abs(target) | (U << 8);
19637           return instr | (target & 0xff) | ((target & 0x100) << 15);
19638         }
19639       } immop;
19640       EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12),
19641                       location,
19642                       immop,
19643                       &kT32DataInfo));
19644       AdvanceIT();
19645       return;
19646     }
19647   } else {
19648     // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19649     if (dt.IsNoneOr(Untyped64) &&
19650         ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19651           ((offset & 0x3) == 0)) ||
19652          !location->IsBound()) &&
19653         cond.IsNotNever()) {
19654       static class EmitOp : public Location::EmitOperator {
19655        public:
19656         EmitOp() : Location::EmitOperator(A32) {}
19657         virtual uint32_t Encode(uint32_t instr,
19658                                 Location::Offset program_counter,
19659                                 const Location* loc) const VIXL_OVERRIDE {
19660           program_counter += kA32PcDelta;
19661           Location::Offset off =
19662               loc->GetLocation() - AlignDown(program_counter, 4);
19663           VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
19664           int32_t target = off >> 2;
19665           uint32_t U = (target >= 0);
19666           target = abs(target) | (U << 8);
19667           return instr | (target & 0xff) | ((target & 0x100) << 15);
19668         }
19669       } immop;
19670       EmitA32(
19671           Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
19672                location,
19673                immop,
19674                &kA32DataInfo));
19675       return;
19676     }
19677   }
19678   Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
19679 }
19680 
vldr_info(Condition cond,DataType dt,DRegister rd,Location * location,const struct ReferenceInfo ** info)19681 bool Assembler::vldr_info(Condition cond,
19682                           DataType dt,
19683                           DRegister rd,
19684                           Location* location,
19685                           const struct ReferenceInfo** info) {
19686   VIXL_ASSERT(!location->IsBound());
19687   USE(location);
19688   USE(rd);
19689   if (IsUsingT32()) {
19690     // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19691     if (dt.IsNoneOr(Untyped64)) {
19692       *info = &kT32DataInfo;
19693       return true;
19694     }
19695   } else {
19696     // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19697     if (dt.IsNoneOr(Untyped64) && cond.IsNotNever()) {
19698       *info = &kA32DataInfo;
19699       return true;
19700     }
19701   }
19702   return false;
19703 }
19704 
vldr(Condition cond,DataType dt,DRegister rd,const MemOperand & operand)19705 void Assembler::vldr(Condition cond,
19706                      DataType dt,
19707                      DRegister rd,
19708                      const MemOperand& operand) {
19709   VIXL_ASSERT(AllowAssembler());
19710   CheckIT(cond);
19711   if (operand.IsImmediate()) {
19712     Register rn = operand.GetBaseRegister();
19713     int32_t offset = operand.GetOffsetImmediate();
19714     if (IsUsingT32()) {
19715       // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
19716       if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19717           ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
19718         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19719         uint32_t offset_ = abs(offset) >> 2;
19720         EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19721         AdvanceIT();
19722         return;
19723       }
19724       // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
19725       if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19726           ((offset % 4) == 0) && operand.IsOffset() &&
19727           ((rn.GetCode() & 0xf) != 0xf)) {
19728         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19729         uint32_t offset_ = abs(offset) >> 2;
19730         EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19731                    offset_ | (sign << 23));
19732         AdvanceIT();
19733         return;
19734       }
19735     } else {
19736       // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
19737       if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19738           ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19739           cond.IsNotNever()) {
19740         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19741         uint32_t offset_ = abs(offset) >> 2;
19742         EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19743                 offset_ | (sign << 23));
19744         return;
19745       }
19746       // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
19747       if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19748           ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19749           ((rn.GetCode() & 0xf) != 0xf)) {
19750         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19751         uint32_t offset_ = abs(offset) >> 2;
19752         EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19753                 (rn.GetCode() << 16) | offset_ | (sign << 23));
19754         return;
19755       }
19756     }
19757   }
19758   Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19759 }
19760 
vldr(Condition cond,DataType dt,SRegister rd,Location * location)19761 void Assembler::vldr(Condition cond,
19762                      DataType dt,
19763                      SRegister rd,
19764                      Location* location) {
19765   VIXL_ASSERT(AllowAssembler());
19766   CheckIT(cond);
19767   Location::Offset offset =
19768       location->IsBound()
19769           ? location->GetLocation() -
19770                 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19771           : 0;
19772   if (IsUsingT32()) {
19773     // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19774     if (dt.IsNoneOr(Untyped32) &&
19775         ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19776           ((offset & 0x3) == 0)) ||
19777          !location->IsBound())) {
19778       static class EmitOp : public Location::EmitOperator {
19779        public:
19780         EmitOp() : Location::EmitOperator(T32) {}
19781         virtual uint32_t Encode(uint32_t instr,
19782                                 Location::Offset program_counter,
19783                                 const Location* loc) const VIXL_OVERRIDE {
19784           program_counter += kT32PcDelta;
19785           Location::Offset off =
19786               loc->GetLocation() - AlignDown(program_counter, 4);
19787           VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
19788           int32_t target = off >> 2;
19789           uint32_t U = (target >= 0);
19790           target = abs(target) | (U << 8);
19791           return instr | (target & 0xff) | ((target & 0x100) << 15);
19792         }
19793       } immop;
19794       EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12),
19795                       location,
19796                       immop,
19797                       &kT32DataInfo));
19798       AdvanceIT();
19799       return;
19800     }
19801   } else {
19802     // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19803     if (dt.IsNoneOr(Untyped32) &&
19804         ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19805           ((offset & 0x3) == 0)) ||
19806          !location->IsBound()) &&
19807         cond.IsNotNever()) {
19808       static class EmitOp : public Location::EmitOperator {
19809        public:
19810         EmitOp() : Location::EmitOperator(A32) {}
19811         virtual uint32_t Encode(uint32_t instr,
19812                                 Location::Offset program_counter,
19813                                 const Location* loc) const VIXL_OVERRIDE {
19814           program_counter += kA32PcDelta;
19815           Location::Offset off =
19816               loc->GetLocation() - AlignDown(program_counter, 4);
19817           VIXL_ASSERT((off >= -1020) && (off <= 1020) && ((off & 0x3) == 0));
19818           int32_t target = off >> 2;
19819           uint32_t U = (target >= 0);
19820           target = abs(target) | (U << 8);
19821           return instr | (target & 0xff) | ((target & 0x100) << 15);
19822         }
19823       } immop;
19824       EmitA32(
19825           Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
19826                location,
19827                immop,
19828                &kA32DataInfo));
19829       return;
19830     }
19831   }
19832   Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
19833 }
19834 
vldr_info(Condition cond,DataType dt,SRegister rd,Location * location,const struct ReferenceInfo ** info)19835 bool Assembler::vldr_info(Condition cond,
19836                           DataType dt,
19837                           SRegister rd,
19838                           Location* location,
19839                           const struct ReferenceInfo** info) {
19840   VIXL_ASSERT(!location->IsBound());
19841   USE(location);
19842   USE(rd);
19843   if (IsUsingT32()) {
19844     // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19845     if (dt.IsNoneOr(Untyped32)) {
19846       *info = &kT32DataInfo;
19847       return true;
19848     }
19849   } else {
19850     // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19851     if (dt.IsNoneOr(Untyped32) && cond.IsNotNever()) {
19852       *info = &kA32DataInfo;
19853       return true;
19854     }
19855   }
19856   return false;
19857 }
19858 
vldr(Condition cond,DataType dt,SRegister rd,const MemOperand & operand)19859 void Assembler::vldr(Condition cond,
19860                      DataType dt,
19861                      SRegister rd,
19862                      const MemOperand& operand) {
19863   VIXL_ASSERT(AllowAssembler());
19864   CheckIT(cond);
19865   if (operand.IsImmediate()) {
19866     Register rn = operand.GetBaseRegister();
19867     int32_t offset = operand.GetOffsetImmediate();
19868     if (IsUsingT32()) {
19869       // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
19870       if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19871           ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
19872         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19873         uint32_t offset_ = abs(offset) >> 2;
19874         EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19875         AdvanceIT();
19876         return;
19877       }
19878       // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
19879       if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19880           ((offset % 4) == 0) && operand.IsOffset() &&
19881           ((rn.GetCode() & 0xf) != 0xf)) {
19882         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19883         uint32_t offset_ = abs(offset) >> 2;
19884         EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19885                    offset_ | (sign << 23));
19886         AdvanceIT();
19887         return;
19888       }
19889     } else {
19890       // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
19891       if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19892           ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19893           cond.IsNotNever()) {
19894         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19895         uint32_t offset_ = abs(offset) >> 2;
19896         EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19897                 offset_ | (sign << 23));
19898         return;
19899       }
19900       // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
19901       if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19902           ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19903           ((rn.GetCode() & 0xf) != 0xf)) {
19904         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19905         uint32_t offset_ = abs(offset) >> 2;
19906         EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19907                 (rn.GetCode() << 16) | offset_ | (sign << 23));
19908         return;
19909       }
19910     }
19911   }
19912   Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19913 }
19914 
vmax(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)19915 void Assembler::vmax(
19916     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19917   VIXL_ASSERT(AllowAssembler());
19918   CheckIT(cond);
19919   Dt_U_size_1 encoded_dt(dt);
19920   if (IsUsingT32()) {
19921     // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
19922     if (dt.Is(F32)) {
19923       if (cond.Is(al) || AllowStronglyDiscouraged()) {
19924         EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19925                    rm.Encode(5, 0));
19926         AdvanceIT();
19927         return;
19928       }
19929     }
19930     // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
19931     if (encoded_dt.IsValid()) {
19932       if (cond.Is(al) || AllowStronglyDiscouraged()) {
19933         EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19934                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19935                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19936         AdvanceIT();
19937         return;
19938       }
19939     }
19940   } else {
19941     // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
19942     if (dt.Is(F32)) {
19943       if (cond.Is(al)) {
19944         EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19945                 rm.Encode(5, 0));
19946         return;
19947       }
19948     }
19949     // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
19950     if (encoded_dt.IsValid()) {
19951       if (cond.Is(al)) {
19952         EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19953                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19954                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19955         return;
19956       }
19957     }
19958   }
19959   Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19960 }
19961 
vmax(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)19962 void Assembler::vmax(
19963     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19964   VIXL_ASSERT(AllowAssembler());
19965   CheckIT(cond);
19966   Dt_U_size_1 encoded_dt(dt);
19967   if (IsUsingT32()) {
19968     // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
19969     if (dt.Is(F32)) {
19970       if (cond.Is(al) || AllowStronglyDiscouraged()) {
19971         EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19972                    rm.Encode(5, 0));
19973         AdvanceIT();
19974         return;
19975       }
19976     }
19977     // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
19978     if (encoded_dt.IsValid()) {
19979       if (cond.Is(al) || AllowStronglyDiscouraged()) {
19980         EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19981                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19982                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19983         AdvanceIT();
19984         return;
19985       }
19986     }
19987   } else {
19988     // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
19989     if (dt.Is(F32)) {
19990       if (cond.Is(al)) {
19991         EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19992                 rm.Encode(5, 0));
19993         return;
19994       }
19995     }
19996     // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
19997     if (encoded_dt.IsValid()) {
19998       if (cond.Is(al)) {
19999         EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20000                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20001                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20002         return;
20003       }
20004     }
20005   }
20006   Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
20007 }
20008 
vmaxnm(DataType dt,DRegister rd,DRegister rn,DRegister rm)20009 void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20010   VIXL_ASSERT(AllowAssembler());
20011   CheckIT(al);
20012   if (IsUsingT32()) {
20013     // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20014     if (OutsideITBlock() && dt.Is(F32)) {
20015       EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20016                  rm.Encode(5, 0));
20017       AdvanceIT();
20018       return;
20019     }
20020     // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20021     if (OutsideITBlock() && dt.Is(F64)) {
20022       EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20023                  rm.Encode(5, 0));
20024       AdvanceIT();
20025       return;
20026     }
20027   } else {
20028     // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20029     if (dt.Is(F32)) {
20030       EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20031               rm.Encode(5, 0));
20032       return;
20033     }
20034     // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20035     if (dt.Is(F64)) {
20036       EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20037               rm.Encode(5, 0));
20038       return;
20039     }
20040   }
20041   Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20042 }
20043 
vmaxnm(DataType dt,QRegister rd,QRegister rn,QRegister rm)20044 void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20045   VIXL_ASSERT(AllowAssembler());
20046   CheckIT(al);
20047   if (IsUsingT32()) {
20048     // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20049     if (OutsideITBlock() && dt.Is(F32)) {
20050       EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20051                  rm.Encode(5, 0));
20052       AdvanceIT();
20053       return;
20054     }
20055   } else {
20056     // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20057     if (dt.Is(F32)) {
20058       EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20059               rm.Encode(5, 0));
20060       return;
20061     }
20062   }
20063   Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20064 }
20065 
vmaxnm(DataType dt,SRegister rd,SRegister rn,SRegister rm)20066 void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20067   VIXL_ASSERT(AllowAssembler());
20068   CheckIT(al);
20069   if (IsUsingT32()) {
20070     // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20071     if (OutsideITBlock() && dt.Is(F32)) {
20072       EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20073                  rm.Encode(5, 0));
20074       AdvanceIT();
20075       return;
20076     }
20077   } else {
20078     // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20079     if (dt.Is(F32)) {
20080       EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20081               rm.Encode(5, 0));
20082       return;
20083     }
20084   }
20085   Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20086 }
20087 
vmin(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)20088 void Assembler::vmin(
20089     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20090   VIXL_ASSERT(AllowAssembler());
20091   CheckIT(cond);
20092   Dt_U_size_1 encoded_dt(dt);
20093   if (IsUsingT32()) {
20094     // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20095     if (dt.Is(F32)) {
20096       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20097         EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20098                    rm.Encode(5, 0));
20099         AdvanceIT();
20100         return;
20101       }
20102     }
20103     // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20104     if (encoded_dt.IsValid()) {
20105       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20106         EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20107                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20108                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20109         AdvanceIT();
20110         return;
20111       }
20112     }
20113   } else {
20114     // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20115     if (dt.Is(F32)) {
20116       if (cond.Is(al)) {
20117         EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20118                 rm.Encode(5, 0));
20119         return;
20120       }
20121     }
20122     // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20123     if (encoded_dt.IsValid()) {
20124       if (cond.Is(al)) {
20125         EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20126                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20127                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20128         return;
20129       }
20130     }
20131   }
20132   Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20133 }
20134 
vmin(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)20135 void Assembler::vmin(
20136     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20137   VIXL_ASSERT(AllowAssembler());
20138   CheckIT(cond);
20139   Dt_U_size_1 encoded_dt(dt);
20140   if (IsUsingT32()) {
20141     // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20142     if (dt.Is(F32)) {
20143       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20144         EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20145                    rm.Encode(5, 0));
20146         AdvanceIT();
20147         return;
20148       }
20149     }
20150     // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20151     if (encoded_dt.IsValid()) {
20152       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20153         EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20154                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20155                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20156         AdvanceIT();
20157         return;
20158       }
20159     }
20160   } else {
20161     // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20162     if (dt.Is(F32)) {
20163       if (cond.Is(al)) {
20164         EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20165                 rm.Encode(5, 0));
20166         return;
20167       }
20168     }
20169     // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20170     if (encoded_dt.IsValid()) {
20171       if (cond.Is(al)) {
20172         EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20173                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20174                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20175         return;
20176       }
20177     }
20178   }
20179   Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20180 }
20181 
vminnm(DataType dt,DRegister rd,DRegister rn,DRegister rm)20182 void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20183   VIXL_ASSERT(AllowAssembler());
20184   CheckIT(al);
20185   if (IsUsingT32()) {
20186     // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20187     if (OutsideITBlock() && dt.Is(F32)) {
20188       EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20189                  rm.Encode(5, 0));
20190       AdvanceIT();
20191       return;
20192     }
20193     // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20194     if (OutsideITBlock() && dt.Is(F64)) {
20195       EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20196                  rm.Encode(5, 0));
20197       AdvanceIT();
20198       return;
20199     }
20200   } else {
20201     // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20202     if (dt.Is(F32)) {
20203       EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20204               rm.Encode(5, 0));
20205       return;
20206     }
20207     // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20208     if (dt.Is(F64)) {
20209       EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20210               rm.Encode(5, 0));
20211       return;
20212     }
20213   }
20214   Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20215 }
20216 
vminnm(DataType dt,QRegister rd,QRegister rn,QRegister rm)20217 void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20218   VIXL_ASSERT(AllowAssembler());
20219   CheckIT(al);
20220   if (IsUsingT32()) {
20221     // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20222     if (OutsideITBlock() && dt.Is(F32)) {
20223       EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20224                  rm.Encode(5, 0));
20225       AdvanceIT();
20226       return;
20227     }
20228   } else {
20229     // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20230     if (dt.Is(F32)) {
20231       EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20232               rm.Encode(5, 0));
20233       return;
20234     }
20235   }
20236   Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20237 }
20238 
vminnm(DataType dt,SRegister rd,SRegister rn,SRegister rm)20239 void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20240   VIXL_ASSERT(AllowAssembler());
20241   CheckIT(al);
20242   if (IsUsingT32()) {
20243     // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20244     if (OutsideITBlock() && dt.Is(F32)) {
20245       EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20246                  rm.Encode(5, 0));
20247       AdvanceIT();
20248       return;
20249     }
20250   } else {
20251     // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20252     if (dt.Is(F32)) {
20253       EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20254               rm.Encode(5, 0));
20255       return;
20256     }
20257   }
20258   Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20259 }
20260 
vmla(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegisterLane rm)20261 void Assembler::vmla(
20262     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
20263   VIXL_ASSERT(AllowAssembler());
20264   CheckIT(cond);
20265   Dt_size_9 encoded_dt(dt);
20266   if (IsUsingT32()) {
20267     // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20268     if (encoded_dt.IsValid() &&
20269         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20270          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20271           (rm.GetLane() <= 1)))) {
20272       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20273         EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20274                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20275                    rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20276         AdvanceIT();
20277         return;
20278       }
20279     }
20280   } else {
20281     // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20282     if (encoded_dt.IsValid() &&
20283         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20284          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20285           (rm.GetLane() <= 1)))) {
20286       if (cond.Is(al)) {
20287         EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20288                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20289                 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20290         return;
20291       }
20292     }
20293   }
20294   Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20295 }
20296 
vmla(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegisterLane rm)20297 void Assembler::vmla(
20298     Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
20299   VIXL_ASSERT(AllowAssembler());
20300   CheckIT(cond);
20301   Dt_size_9 encoded_dt(dt);
20302   if (IsUsingT32()) {
20303     // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20304     if (encoded_dt.IsValid() &&
20305         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20306          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20307           (rm.GetLane() <= 1)))) {
20308       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20309         EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20310                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20311                    rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20312         AdvanceIT();
20313         return;
20314       }
20315     }
20316   } else {
20317     // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20318     if (encoded_dt.IsValid() &&
20319         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20320          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20321           (rm.GetLane() <= 1)))) {
20322       if (cond.Is(al)) {
20323         EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20324                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20325                 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20326         return;
20327       }
20328     }
20329   }
20330   Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20331 }
20332 
vmla(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)20333 void Assembler::vmla(
20334     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20335   VIXL_ASSERT(AllowAssembler());
20336   CheckIT(cond);
20337   Dt_size_10 encoded_dt(dt);
20338   if (IsUsingT32()) {
20339     // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20340     if (dt.Is(F32)) {
20341       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20342         EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20343                    rm.Encode(5, 0));
20344         AdvanceIT();
20345         return;
20346       }
20347     }
20348     // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20349     if (dt.Is(F64)) {
20350       EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20351                  rm.Encode(5, 0));
20352       AdvanceIT();
20353       return;
20354     }
20355     // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20356     if (encoded_dt.IsValid()) {
20357       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20358         EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
20359                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20360         AdvanceIT();
20361         return;
20362       }
20363     }
20364   } else {
20365     // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20366     if (dt.Is(F32)) {
20367       if (cond.Is(al)) {
20368         EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20369                 rm.Encode(5, 0));
20370         return;
20371       }
20372     }
20373     // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20374     if (dt.Is(F64) && cond.IsNotNever()) {
20375       EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20376               rn.Encode(7, 16) | rm.Encode(5, 0));
20377       return;
20378     }
20379     // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20380     if (encoded_dt.IsValid()) {
20381       if (cond.Is(al)) {
20382         EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
20383                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20384         return;
20385       }
20386     }
20387   }
20388   Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20389 }
20390 
vmla(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)20391 void Assembler::vmla(
20392     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20393   VIXL_ASSERT(AllowAssembler());
20394   CheckIT(cond);
20395   Dt_size_10 encoded_dt(dt);
20396   if (IsUsingT32()) {
20397     // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20398     if (dt.Is(F32)) {
20399       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20400         EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20401                    rm.Encode(5, 0));
20402         AdvanceIT();
20403         return;
20404       }
20405     }
20406     // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20407     if (encoded_dt.IsValid()) {
20408       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20409         EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
20410                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20411         AdvanceIT();
20412         return;
20413       }
20414     }
20415   } else {
20416     // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20417     if (dt.Is(F32)) {
20418       if (cond.Is(al)) {
20419         EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20420                 rm.Encode(5, 0));
20421         return;
20422       }
20423     }
20424     // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20425     if (encoded_dt.IsValid()) {
20426       if (cond.Is(al)) {
20427         EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
20428                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20429         return;
20430       }
20431     }
20432   }
20433   Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20434 }
20435 
vmla(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)20436 void Assembler::vmla(
20437     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20438   VIXL_ASSERT(AllowAssembler());
20439   CheckIT(cond);
20440   if (IsUsingT32()) {
20441     // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20442     if (dt.Is(F32)) {
20443       EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20444                  rm.Encode(5, 0));
20445       AdvanceIT();
20446       return;
20447     }
20448   } else {
20449     // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20450     if (dt.Is(F32) && cond.IsNotNever()) {
20451       EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20452               rn.Encode(7, 16) | rm.Encode(5, 0));
20453       return;
20454     }
20455   }
20456   Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20457 }
20458 
vmlal(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegisterLane rm)20459 void Assembler::vmlal(
20460     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
20461   VIXL_ASSERT(AllowAssembler());
20462   CheckIT(cond);
20463   Dt_size_11 encoded_dt(dt);
20464   if (IsUsingT32()) {
20465     // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20466     if (encoded_dt.IsValid() &&
20467         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20468          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20469           (rm.GetLane() <= 1)))) {
20470       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20471         EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
20472                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20473                    rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20474         AdvanceIT();
20475         return;
20476       }
20477     }
20478   } else {
20479     // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20480     if (encoded_dt.IsValid() &&
20481         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20482          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20483           (rm.GetLane() <= 1)))) {
20484       if (cond.Is(al)) {
20485         EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
20486                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20487                 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20488         return;
20489       }
20490     }
20491   }
20492   Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20493 }
20494 
vmlal(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)20495 void Assembler::vmlal(
20496     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
20497   VIXL_ASSERT(AllowAssembler());
20498   CheckIT(cond);
20499   Dt_size_12 encoded_dt(dt);
20500   if (IsUsingT32()) {
20501     // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20502     if (encoded_dt.IsValid()) {
20503       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20504         EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
20505                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20506                    rn.Encode(7, 16) | rm.Encode(5, 0));
20507         AdvanceIT();
20508         return;
20509       }
20510     }
20511   } else {
20512     // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20513     if (encoded_dt.IsValid()) {
20514       if (cond.Is(al)) {
20515         EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
20516                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20517                 rn.Encode(7, 16) | rm.Encode(5, 0));
20518         return;
20519       }
20520     }
20521   }
20522   Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20523 }
20524 
vmls(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegisterLane rm)20525 void Assembler::vmls(
20526     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
20527   VIXL_ASSERT(AllowAssembler());
20528   CheckIT(cond);
20529   Dt_size_9 encoded_dt(dt);
20530   if (IsUsingT32()) {
20531     // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20532     if (encoded_dt.IsValid() &&
20533         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20534          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20535           (rm.GetLane() <= 1)))) {
20536       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20537         EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20538                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20539                    rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20540         AdvanceIT();
20541         return;
20542       }
20543     }
20544   } else {
20545     // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20546     if (encoded_dt.IsValid() &&
20547         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20548          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20549           (rm.GetLane() <= 1)))) {
20550       if (cond.Is(al)) {
20551         EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20552                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20553                 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20554         return;
20555       }
20556     }
20557   }
20558   Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20559 }
20560 
vmls(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegisterLane rm)20561 void Assembler::vmls(
20562     Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
20563   VIXL_ASSERT(AllowAssembler());
20564   CheckIT(cond);
20565   Dt_size_9 encoded_dt(dt);
20566   if (IsUsingT32()) {
20567     // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20568     if (encoded_dt.IsValid() &&
20569         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20570          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20571           (rm.GetLane() <= 1)))) {
20572       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20573         EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20574                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20575                    rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20576         AdvanceIT();
20577         return;
20578       }
20579     }
20580   } else {
20581     // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20582     if (encoded_dt.IsValid() &&
20583         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20584          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20585           (rm.GetLane() <= 1)))) {
20586       if (cond.Is(al)) {
20587         EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20588                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20589                 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20590         return;
20591       }
20592     }
20593   }
20594   Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20595 }
20596 
vmls(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)20597 void Assembler::vmls(
20598     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20599   VIXL_ASSERT(AllowAssembler());
20600   CheckIT(cond);
20601   Dt_size_10 encoded_dt(dt);
20602   if (IsUsingT32()) {
20603     // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20604     if (dt.Is(F32)) {
20605       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20606         EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20607                    rm.Encode(5, 0));
20608         AdvanceIT();
20609         return;
20610       }
20611     }
20612     // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20613     if (dt.Is(F64)) {
20614       EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20615                  rm.Encode(5, 0));
20616       AdvanceIT();
20617       return;
20618     }
20619     // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20620     if (encoded_dt.IsValid()) {
20621       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20622         EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
20623                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20624         AdvanceIT();
20625         return;
20626       }
20627     }
20628   } else {
20629     // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20630     if (dt.Is(F32)) {
20631       if (cond.Is(al)) {
20632         EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20633                 rm.Encode(5, 0));
20634         return;
20635       }
20636     }
20637     // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20638     if (dt.Is(F64) && cond.IsNotNever()) {
20639       EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20640               rn.Encode(7, 16) | rm.Encode(5, 0));
20641       return;
20642     }
20643     // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20644     if (encoded_dt.IsValid()) {
20645       if (cond.Is(al)) {
20646         EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
20647                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20648         return;
20649       }
20650     }
20651   }
20652   Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20653 }
20654 
vmls(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)20655 void Assembler::vmls(
20656     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20657   VIXL_ASSERT(AllowAssembler());
20658   CheckIT(cond);
20659   Dt_size_10 encoded_dt(dt);
20660   if (IsUsingT32()) {
20661     // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20662     if (dt.Is(F32)) {
20663       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20664         EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20665                    rm.Encode(5, 0));
20666         AdvanceIT();
20667         return;
20668       }
20669     }
20670     // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20671     if (encoded_dt.IsValid()) {
20672       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20673         EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
20674                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20675         AdvanceIT();
20676         return;
20677       }
20678     }
20679   } else {
20680     // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20681     if (dt.Is(F32)) {
20682       if (cond.Is(al)) {
20683         EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20684                 rm.Encode(5, 0));
20685         return;
20686       }
20687     }
20688     // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20689     if (encoded_dt.IsValid()) {
20690       if (cond.Is(al)) {
20691         EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
20692                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20693         return;
20694       }
20695     }
20696   }
20697   Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20698 }
20699 
vmls(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)20700 void Assembler::vmls(
20701     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20702   VIXL_ASSERT(AllowAssembler());
20703   CheckIT(cond);
20704   if (IsUsingT32()) {
20705     // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20706     if (dt.Is(F32)) {
20707       EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20708                  rm.Encode(5, 0));
20709       AdvanceIT();
20710       return;
20711     }
20712   } else {
20713     // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20714     if (dt.Is(F32) && cond.IsNotNever()) {
20715       EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20716               rn.Encode(7, 16) | rm.Encode(5, 0));
20717       return;
20718     }
20719   }
20720   Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20721 }
20722 
vmlsl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegisterLane rm)20723 void Assembler::vmlsl(
20724     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
20725   VIXL_ASSERT(AllowAssembler());
20726   CheckIT(cond);
20727   Dt_size_11 encoded_dt(dt);
20728   if (IsUsingT32()) {
20729     // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20730     if (encoded_dt.IsValid() &&
20731         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20732          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20733           (rm.GetLane() <= 1)))) {
20734       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20735         EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
20736                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20737                    rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20738         AdvanceIT();
20739         return;
20740       }
20741     }
20742   } else {
20743     // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20744     if (encoded_dt.IsValid() &&
20745         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20746          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20747           (rm.GetLane() <= 1)))) {
20748       if (cond.Is(al)) {
20749         EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
20750                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20751                 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20752         return;
20753       }
20754     }
20755   }
20756   Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20757 }
20758 
vmlsl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)20759 void Assembler::vmlsl(
20760     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
20761   VIXL_ASSERT(AllowAssembler());
20762   CheckIT(cond);
20763   Dt_size_12 encoded_dt(dt);
20764   if (IsUsingT32()) {
20765     // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20766     if (encoded_dt.IsValid()) {
20767       if (cond.Is(al) || AllowStronglyDiscouraged()) {
20768         EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
20769                    (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20770                    rn.Encode(7, 16) | rm.Encode(5, 0));
20771         AdvanceIT();
20772         return;
20773       }
20774     }
20775   } else {
20776     // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20777     if (encoded_dt.IsValid()) {
20778       if (cond.Is(al)) {
20779         EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
20780                 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20781                 rn.Encode(7, 16) | rm.Encode(5, 0));
20782         return;
20783       }
20784     }
20785   }
20786   Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20787 }
20788 
vmov(Condition cond,Register rt,SRegister rn)20789 void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
20790   VIXL_ASSERT(AllowAssembler());
20791   CheckIT(cond);
20792   if (IsUsingT32()) {
20793     // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
20794     if ((!rt.IsPC() || AllowUnpredictable())) {
20795       EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
20796       AdvanceIT();
20797       return;
20798     }
20799   } else {
20800     // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
20801     if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
20802       EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20803               rn.Encode(7, 16));
20804       return;
20805     }
20806   }
20807   Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
20808 }
20809 
vmov(Condition cond,SRegister rn,Register rt)20810 void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
20811   VIXL_ASSERT(AllowAssembler());
20812   CheckIT(cond);
20813   if (IsUsingT32()) {
20814     // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
20815     if ((!rt.IsPC() || AllowUnpredictable())) {
20816       EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
20817       AdvanceIT();
20818       return;
20819     }
20820   } else {
20821     // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
20822     if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
20823       EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
20824               (rt.GetCode() << 12));
20825       return;
20826     }
20827   }
20828   Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
20829 }
20830 
vmov(Condition cond,Register rt,Register rt2,DRegister rm)20831 void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
20832   VIXL_ASSERT(AllowAssembler());
20833   CheckIT(cond);
20834   if (IsUsingT32()) {
20835     // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
20836     if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20837       EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20838                  rm.Encode(5, 0));
20839       AdvanceIT();
20840       return;
20841     }
20842   } else {
20843     // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
20844     if (cond.IsNotNever() &&
20845         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20846       EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20847               (rt2.GetCode() << 16) | rm.Encode(5, 0));
20848       return;
20849     }
20850   }
20851   Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
20852 }
20853 
vmov(Condition cond,DRegister rm,Register rt,Register rt2)20854 void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
20855   VIXL_ASSERT(AllowAssembler());
20856   CheckIT(cond);
20857   if (IsUsingT32()) {
20858     // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
20859     if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20860       EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20861                  (rt2.GetCode() << 16));
20862       AdvanceIT();
20863       return;
20864     }
20865   } else {
20866     // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
20867     if (cond.IsNotNever() &&
20868         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20869       EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20870               (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20871       return;
20872     }
20873   }
20874   Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
20875 }
20876 
vmov(Condition cond,Register rt,Register rt2,SRegister rm,SRegister rm1)20877 void Assembler::vmov(
20878     Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
20879   VIXL_ASSERT(AllowAssembler());
20880   CheckIT(cond);
20881   if (IsUsingT32()) {
20882     // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
20883     if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20884         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20885       EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20886                  rm.Encode(5, 0));
20887       AdvanceIT();
20888       return;
20889     }
20890   } else {
20891     // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
20892     if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20893         cond.IsNotNever() &&
20894         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20895       EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20896               (rt2.GetCode() << 16) | rm.Encode(5, 0));
20897       return;
20898     }
20899   }
20900   Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
20901 }
20902 
vmov(Condition cond,SRegister rm,SRegister rm1,Register rt,Register rt2)20903 void Assembler::vmov(
20904     Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
20905   VIXL_ASSERT(AllowAssembler());
20906   CheckIT(cond);
20907   if (IsUsingT32()) {
20908     // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
20909     if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20910         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20911       EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20912                  (rt2.GetCode() << 16));
20913       AdvanceIT();
20914       return;
20915     }
20916   } else {
20917     // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
20918     if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20919         cond.IsNotNever() &&
20920         ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20921       EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20922               (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20923       return;
20924     }
20925   }
20926   Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
20927 }
20928 
vmov(Condition cond,DataType dt,DRegisterLane rd,Register rt)20929 void Assembler::vmov(Condition cond,
20930                      DataType dt,
20931                      DRegisterLane rd,
20932                      Register rt) {
20933   VIXL_ASSERT(AllowAssembler());
20934   CheckIT(cond);
20935   Dt_opc1_opc2_1 encoded_dt(dt, rd);
20936   if (IsUsingT32()) {
20937     // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
20938     if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
20939       EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20940                  ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
20941                  rd.Encode(7, 16) | (rt.GetCode() << 12));
20942       AdvanceIT();
20943       return;
20944     }
20945   } else {
20946     // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
20947     if (encoded_dt.IsValid() && cond.IsNotNever() &&
20948         (!rt.IsPC() || AllowUnpredictable())) {
20949       EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
20950               ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20951               ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
20952               (rt.GetCode() << 12));
20953       return;
20954     }
20955   }
20956   Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
20957 }
20958 
vmov(Condition cond,DataType dt,DRegister rd,const DOperand & operand)20959 void Assembler::vmov(Condition cond,
20960                      DataType dt,
20961                      DRegister rd,
20962                      const DOperand& operand) {
20963   VIXL_ASSERT(AllowAssembler());
20964   CheckIT(cond);
20965   if (operand.IsImmediate()) {
20966     ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
20967     if (IsUsingT32()) {
20968       // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20969       if (encoded_dt.IsValid()) {
20970         if (cond.Is(al) || AllowStronglyDiscouraged()) {
20971           EmitT32_32(
20972               0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20973               ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20974               rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20975               ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20976               ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20977           AdvanceIT();
20978           return;
20979         }
20980       }
20981     } else {
20982       // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20983       if (encoded_dt.IsValid()) {
20984         if (cond.Is(al)) {
20985           EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20986                   ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20987                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20988                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20989                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20990           return;
20991         }
20992       }
20993     }
20994   }
20995   if (operand.IsImmediate()) {
20996     ImmediateVFP vfp(operand.GetNeonImmediate());
20997     if (IsUsingT32()) {
20998       // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
20999       if (dt.Is(F64) && vfp.IsValid()) {
21000         EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
21001                    (vfp.GetEncodingValue() & 0xf) |
21002                    ((vfp.GetEncodingValue() & 0xf0) << 12));
21003         AdvanceIT();
21004         return;
21005       }
21006     } else {
21007       // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
21008       if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
21009         EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21010                 (vfp.GetEncodingValue() & 0xf) |
21011                 ((vfp.GetEncodingValue() & 0xf0) << 12));
21012         return;
21013       }
21014     }
21015   }
21016   if (operand.IsRegister()) {
21017     DRegister rm = operand.GetRegister();
21018     if (IsUsingT32()) {
21019       // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21020       if (dt.Is(F64)) {
21021         EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21022         AdvanceIT();
21023         return;
21024       }
21025       // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21026       if (!dt.Is(F64)) {
21027         if (cond.Is(al) || AllowStronglyDiscouraged()) {
21028           EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21029                      rm.Encode(5, 0));
21030           AdvanceIT();
21031           return;
21032         }
21033       }
21034     } else {
21035       // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21036       if (dt.Is(F64) && cond.IsNotNever()) {
21037         EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21038                 rm.Encode(5, 0));
21039         return;
21040       }
21041       // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21042       if (!dt.Is(F64)) {
21043         if (cond.Is(al)) {
21044           EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21045                   rm.Encode(5, 0));
21046           return;
21047         }
21048       }
21049     }
21050   }
21051   Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21052 }
21053 
vmov(Condition cond,DataType dt,QRegister rd,const QOperand & operand)21054 void Assembler::vmov(Condition cond,
21055                      DataType dt,
21056                      QRegister rd,
21057                      const QOperand& operand) {
21058   VIXL_ASSERT(AllowAssembler());
21059   CheckIT(cond);
21060   if (operand.IsImmediate()) {
21061     ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
21062     if (IsUsingT32()) {
21063       // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21064       if (encoded_dt.IsValid()) {
21065         if (cond.Is(al) || AllowStronglyDiscouraged()) {
21066           EmitT32_32(
21067               0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21068               ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21069               rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21070               ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21071               ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21072           AdvanceIT();
21073           return;
21074         }
21075       }
21076     } else {
21077       // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21078       if (encoded_dt.IsValid()) {
21079         if (cond.Is(al)) {
21080           EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21081                   ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21082                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21083                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21084                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21085           return;
21086         }
21087       }
21088     }
21089   }
21090   if (operand.IsRegister()) {
21091     QRegister rm = operand.GetRegister();
21092     if (IsUsingT32()) {
21093       // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21094       if (!dt.Is(F64)) {
21095         if (cond.Is(al) || AllowStronglyDiscouraged()) {
21096           EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21097                      rm.Encode(5, 0));
21098           AdvanceIT();
21099           return;
21100         }
21101       }
21102     } else {
21103       // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21104       if (!dt.Is(F64)) {
21105         if (cond.Is(al)) {
21106           EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21107                   rm.Encode(5, 0));
21108           return;
21109         }
21110       }
21111     }
21112   }
21113   Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21114 }
21115 
vmov(Condition cond,DataType dt,SRegister rd,const SOperand & operand)21116 void Assembler::vmov(Condition cond,
21117                      DataType dt,
21118                      SRegister rd,
21119                      const SOperand& operand) {
21120   VIXL_ASSERT(AllowAssembler());
21121   CheckIT(cond);
21122   if (operand.IsImmediate()) {
21123     ImmediateVFP vfp(operand.GetNeonImmediate());
21124     if (IsUsingT32()) {
21125       // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
21126       if (dt.Is(F32) && vfp.IsValid()) {
21127         EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
21128                    (vfp.GetEncodingValue() & 0xf) |
21129                    ((vfp.GetEncodingValue() & 0xf0) << 12));
21130         AdvanceIT();
21131         return;
21132       }
21133     } else {
21134       // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
21135       if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
21136         EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21137                 (vfp.GetEncodingValue() & 0xf) |
21138                 ((vfp.GetEncodingValue() & 0xf0) << 12));
21139         return;
21140       }
21141     }
21142   }
21143   if (operand.IsRegister()) {
21144     SRegister rm = operand.GetRegister();
21145     if (IsUsingT32()) {
21146       // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21147       if (dt.Is(F32)) {
21148         EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21149         AdvanceIT();
21150         return;
21151       }
21152     } else {
21153       // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21154       if (dt.Is(F32) && cond.IsNotNever()) {
21155         EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21156                 rm.Encode(5, 0));
21157         return;
21158       }
21159     }
21160   }
21161   Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21162 }
21163 
vmov(Condition cond,DataType dt,Register rt,DRegisterLane rn)21164 void Assembler::vmov(Condition cond,
21165                      DataType dt,
21166                      Register rt,
21167                      DRegisterLane rn) {
21168   VIXL_ASSERT(AllowAssembler());
21169   CheckIT(cond);
21170   Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
21171   if (IsUsingT32()) {
21172     // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
21173     if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
21174       EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21175                  ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21176                  ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21177                  (rt.GetCode() << 12) | rn.Encode(7, 16));
21178       AdvanceIT();
21179       return;
21180     }
21181   } else {
21182     // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
21183     if (encoded_dt.IsValid() && cond.IsNotNever() &&
21184         (!rt.IsPC() || AllowUnpredictable())) {
21185       EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
21186               ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21187               ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21188               ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21189               (rt.GetCode() << 12) | rn.Encode(7, 16));
21190       return;
21191     }
21192   }
21193   Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
21194 }
21195 
vmovl(Condition cond,DataType dt,QRegister rd,DRegister rm)21196 void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
21197   VIXL_ASSERT(AllowAssembler());
21198   CheckIT(cond);
21199   Dt_U_imm3H_1 encoded_dt(dt);
21200   if (IsUsingT32()) {
21201     // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
21202     if (encoded_dt.IsValid()) {
21203       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21204         EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21205                    ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
21206                    rd.Encode(22, 12) | rm.Encode(5, 0));
21207         AdvanceIT();
21208         return;
21209       }
21210     }
21211   } else {
21212     // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
21213     if (encoded_dt.IsValid()) {
21214       if (cond.Is(al)) {
21215         EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21216                 ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
21217                 rd.Encode(22, 12) | rm.Encode(5, 0));
21218         return;
21219       }
21220     }
21221   }
21222   Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
21223 }
21224 
vmovn(Condition cond,DataType dt,DRegister rd,QRegister rm)21225 void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
21226   VIXL_ASSERT(AllowAssembler());
21227   CheckIT(cond);
21228   Dt_size_3 encoded_dt(dt);
21229   if (IsUsingT32()) {
21230     // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21231     if (encoded_dt.IsValid()) {
21232       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21233         EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
21234                    rd.Encode(22, 12) | rm.Encode(5, 0));
21235         AdvanceIT();
21236         return;
21237       }
21238     }
21239   } else {
21240     // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21241     if (encoded_dt.IsValid()) {
21242       if (cond.Is(al)) {
21243         EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
21244                 rd.Encode(22, 12) | rm.Encode(5, 0));
21245         return;
21246       }
21247     }
21248   }
21249   Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
21250 }
21251 
vmrs(Condition cond,RegisterOrAPSR_nzcv rt,SpecialFPRegister spec_reg)21252 void Assembler::vmrs(Condition cond,
21253                      RegisterOrAPSR_nzcv rt,
21254                      SpecialFPRegister spec_reg) {
21255   VIXL_ASSERT(AllowAssembler());
21256   CheckIT(cond);
21257   if (IsUsingT32()) {
21258     // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
21259     EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
21260     AdvanceIT();
21261     return;
21262   } else {
21263     // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
21264     if (cond.IsNotNever()) {
21265       EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
21266               (spec_reg.GetReg() << 16));
21267       return;
21268     }
21269   }
21270   Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
21271 }
21272 
vmsr(Condition cond,SpecialFPRegister spec_reg,Register rt)21273 void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
21274   VIXL_ASSERT(AllowAssembler());
21275   CheckIT(cond);
21276   if (IsUsingT32()) {
21277     // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
21278     if ((!rt.IsPC() || AllowUnpredictable())) {
21279       EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) |
21280                  (rt.GetCode() << 12));
21281       AdvanceIT();
21282       return;
21283     }
21284   } else {
21285     // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
21286     if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
21287       EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
21288               (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
21289       return;
21290     }
21291   }
21292   Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
21293 }
21294 
vmul(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister dm,unsigned index)21295 void Assembler::vmul(Condition cond,
21296                      DataType dt,
21297                      DRegister rd,
21298                      DRegister rn,
21299                      DRegister dm,
21300                      unsigned index) {
21301   VIXL_ASSERT(AllowAssembler());
21302   CheckIT(cond);
21303   Dt_F_size_3 encoded_dt(dt);
21304   if (IsUsingT32()) {
21305     // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
21306     if (encoded_dt.IsValid() &&
21307         ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21308          (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21309       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21310         uint32_t shift = 4;
21311         if (dt.Is(I16)) {
21312           shift = 3;
21313         }
21314         uint32_t mvm = dm.GetCode() | index << shift;
21315         EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21316                    ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21317                    rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21318                    ((mvm & 0x10) << 1));
21319         AdvanceIT();
21320         return;
21321       }
21322     }
21323   } else {
21324     // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
21325     if (encoded_dt.IsValid() &&
21326         ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21327          (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21328       if (cond.Is(al)) {
21329         uint32_t shift = 4;
21330         if (dt.Is(I16)) {
21331           shift = 3;
21332         }
21333         uint32_t mvm = dm.GetCode() | index << shift;
21334         EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21335                 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21336                 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21337                 ((mvm & 0x10) << 1));
21338         return;
21339       }
21340     }
21341   }
21342   Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21343 }
21344 
vmul(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegister dm,unsigned index)21345 void Assembler::vmul(Condition cond,
21346                      DataType dt,
21347                      QRegister rd,
21348                      QRegister rn,
21349                      DRegister dm,
21350                      unsigned index) {
21351   VIXL_ASSERT(AllowAssembler());
21352   CheckIT(cond);
21353   Dt_F_size_3 encoded_dt(dt);
21354   if (IsUsingT32()) {
21355     // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
21356     if (encoded_dt.IsValid() &&
21357         ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21358          (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21359       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21360         uint32_t shift = 4;
21361         if (dt.Is(I16)) {
21362           shift = 3;
21363         }
21364         uint32_t mvm = dm.GetCode() | index << shift;
21365         EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21366                    ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21367                    rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21368                    ((mvm & 0x10) << 1));
21369         AdvanceIT();
21370         return;
21371       }
21372     }
21373   } else {
21374     // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
21375     if (encoded_dt.IsValid() &&
21376         ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21377          (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21378       if (cond.Is(al)) {
21379         uint32_t shift = 4;
21380         if (dt.Is(I16)) {
21381           shift = 3;
21382         }
21383         uint32_t mvm = dm.GetCode() | index << shift;
21384         EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21385                 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21386                 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21387                 ((mvm & 0x10) << 1));
21388         return;
21389       }
21390     }
21391   }
21392   Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21393 }
21394 
vmul(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)21395 void Assembler::vmul(
21396     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21397   VIXL_ASSERT(AllowAssembler());
21398   CheckIT(cond);
21399   Dt_op_size_1 encoded_dt(dt);
21400   if (IsUsingT32()) {
21401     // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21402     if (dt.Is(F32)) {
21403       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21404         EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21405                    rm.Encode(5, 0));
21406         AdvanceIT();
21407         return;
21408       }
21409     }
21410     // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
21411     if (dt.Is(F64)) {
21412       EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21413                  rm.Encode(5, 0));
21414       AdvanceIT();
21415       return;
21416     }
21417     // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21418     if (encoded_dt.IsValid()) {
21419       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21420         EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21421                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21422                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21423         AdvanceIT();
21424         return;
21425       }
21426     }
21427   } else {
21428     // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21429     if (dt.Is(F32)) {
21430       if (cond.Is(al)) {
21431         EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21432                 rm.Encode(5, 0));
21433         return;
21434       }
21435     }
21436     // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
21437     if (dt.Is(F64) && cond.IsNotNever()) {
21438       EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21439               rn.Encode(7, 16) | rm.Encode(5, 0));
21440       return;
21441     }
21442     // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21443     if (encoded_dt.IsValid()) {
21444       if (cond.Is(al)) {
21445         EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21446                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21447                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21448         return;
21449       }
21450     }
21451   }
21452   Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21453 }
21454 
vmul(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)21455 void Assembler::vmul(
21456     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21457   VIXL_ASSERT(AllowAssembler());
21458   CheckIT(cond);
21459   Dt_op_size_1 encoded_dt(dt);
21460   if (IsUsingT32()) {
21461     // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
21462     if (dt.Is(F32)) {
21463       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21464         EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21465                    rm.Encode(5, 0));
21466         AdvanceIT();
21467         return;
21468       }
21469     }
21470     // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21471     if (encoded_dt.IsValid()) {
21472       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21473         EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21474                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21475                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21476         AdvanceIT();
21477         return;
21478       }
21479     }
21480   } else {
21481     // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
21482     if (dt.Is(F32)) {
21483       if (cond.Is(al)) {
21484         EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21485                 rm.Encode(5, 0));
21486         return;
21487       }
21488     }
21489     // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21490     if (encoded_dt.IsValid()) {
21491       if (cond.Is(al)) {
21492         EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21493                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21494                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21495         return;
21496       }
21497     }
21498   }
21499   Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21500 }
21501 
vmul(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)21502 void Assembler::vmul(
21503     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21504   VIXL_ASSERT(AllowAssembler());
21505   CheckIT(cond);
21506   if (IsUsingT32()) {
21507     // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
21508     if (dt.Is(F32)) {
21509       EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21510                  rm.Encode(5, 0));
21511       AdvanceIT();
21512       return;
21513     }
21514   } else {
21515     // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
21516     if (dt.Is(F32) && cond.IsNotNever()) {
21517       EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21518               rn.Encode(7, 16) | rm.Encode(5, 0));
21519       return;
21520     }
21521   }
21522   Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21523 }
21524 
vmull(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister dm,unsigned index)21525 void Assembler::vmull(Condition cond,
21526                       DataType dt,
21527                       QRegister rd,
21528                       DRegister rn,
21529                       DRegister dm,
21530                       unsigned index) {
21531   VIXL_ASSERT(AllowAssembler());
21532   CheckIT(cond);
21533   Dt_U_size_2 encoded_dt(dt);
21534   if (IsUsingT32()) {
21535     // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
21536     if (encoded_dt.IsValid() &&
21537         (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
21538          (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21539           (dm.GetCode() <= 15)))) {
21540       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21541         uint32_t shift = 4;
21542         if (dt.Is(S16) || dt.Is(U16)) {
21543           shift = 3;
21544         }
21545         uint32_t mvm = dm.GetCode() | index << shift;
21546         EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21547                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21548                    rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21549                    ((mvm & 0x10) << 1));
21550         AdvanceIT();
21551         return;
21552       }
21553     }
21554   } else {
21555     // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
21556     if (encoded_dt.IsValid() &&
21557         (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
21558          (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21559           (dm.GetCode() <= 15)))) {
21560       if (cond.Is(al)) {
21561         uint32_t shift = 4;
21562         if (dt.Is(S16) || dt.Is(U16)) {
21563           shift = 3;
21564         }
21565         uint32_t mvm = dm.GetCode() | index << shift;
21566         EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21567                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21568                 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21569                 ((mvm & 0x10) << 1));
21570         return;
21571       }
21572     }
21573   }
21574   Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
21575 }
21576 
vmull(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)21577 void Assembler::vmull(
21578     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21579   VIXL_ASSERT(AllowAssembler());
21580   CheckIT(cond);
21581   Dt_op_U_size_1 encoded_dt(dt);
21582   if (IsUsingT32()) {
21583     // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21584     if (encoded_dt.IsValid()) {
21585       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21586         EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21587                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21588                    ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21589                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21590         AdvanceIT();
21591         return;
21592       }
21593     }
21594   } else {
21595     // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21596     if (encoded_dt.IsValid()) {
21597       if (cond.Is(al)) {
21598         EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21599                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21600                 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21601                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21602         return;
21603       }
21604     }
21605   }
21606   Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
21607 }
21608 
vmvn(Condition cond,DataType dt,DRegister rd,const DOperand & operand)21609 void Assembler::vmvn(Condition cond,
21610                      DataType dt,
21611                      DRegister rd,
21612                      const DOperand& operand) {
21613   VIXL_ASSERT(AllowAssembler());
21614   CheckIT(cond);
21615   if (operand.IsImmediate()) {
21616     ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
21617     if (IsUsingT32()) {
21618       // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
21619       if (encoded_dt.IsValid()) {
21620         if (cond.Is(al) || AllowStronglyDiscouraged()) {
21621           EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
21622                      rd.Encode(22, 12) |
21623                      (encoded_dt.GetEncodedImmediate() & 0xf) |
21624                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21625                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21626           AdvanceIT();
21627           return;
21628         }
21629       }
21630     } else {
21631       // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
21632       if (encoded_dt.IsValid()) {
21633         if (cond.Is(al)) {
21634           EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
21635                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21636                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21637                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21638           return;
21639         }
21640       }
21641     }
21642   }
21643   if (operand.IsRegister()) {
21644     DRegister rm = operand.GetRegister();
21645     USE(dt);
21646     if (IsUsingT32()) {
21647       // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21648       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21649         EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21650         AdvanceIT();
21651         return;
21652       }
21653     } else {
21654       // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21655       if (cond.Is(al)) {
21656         EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21657         return;
21658       }
21659     }
21660   }
21661   Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21662 }
21663 
vmvn(Condition cond,DataType dt,QRegister rd,const QOperand & operand)21664 void Assembler::vmvn(Condition cond,
21665                      DataType dt,
21666                      QRegister rd,
21667                      const QOperand& operand) {
21668   VIXL_ASSERT(AllowAssembler());
21669   CheckIT(cond);
21670   if (operand.IsImmediate()) {
21671     ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
21672     if (IsUsingT32()) {
21673       // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21674       if (encoded_dt.IsValid()) {
21675         if (cond.Is(al) || AllowStronglyDiscouraged()) {
21676           EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
21677                      rd.Encode(22, 12) |
21678                      (encoded_dt.GetEncodedImmediate() & 0xf) |
21679                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21680                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21681           AdvanceIT();
21682           return;
21683         }
21684       }
21685     } else {
21686       // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21687       if (encoded_dt.IsValid()) {
21688         if (cond.Is(al)) {
21689           EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
21690                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21691                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21692                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21693           return;
21694         }
21695       }
21696     }
21697   }
21698   if (operand.IsRegister()) {
21699     QRegister rm = operand.GetRegister();
21700     USE(dt);
21701     if (IsUsingT32()) {
21702       // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21703       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21704         EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21705         AdvanceIT();
21706         return;
21707       }
21708     } else {
21709       // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21710       if (cond.Is(al)) {
21711         EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21712         return;
21713       }
21714     }
21715   }
21716   Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21717 }
21718 
vneg(Condition cond,DataType dt,DRegister rd,DRegister rm)21719 void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
21720   VIXL_ASSERT(AllowAssembler());
21721   CheckIT(cond);
21722   Dt_F_size_1 encoded_dt(dt);
21723   if (IsUsingT32()) {
21724     // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21725     if (encoded_dt.IsValid()) {
21726       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21727         EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21728                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21729                    rd.Encode(22, 12) | rm.Encode(5, 0));
21730         AdvanceIT();
21731         return;
21732       }
21733     }
21734     // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21735     if (dt.Is(F64)) {
21736       EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21737       AdvanceIT();
21738       return;
21739     }
21740   } else {
21741     // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21742     if (encoded_dt.IsValid()) {
21743       if (cond.Is(al)) {
21744         EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21745                 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21746                 rd.Encode(22, 12) | rm.Encode(5, 0));
21747         return;
21748       }
21749     }
21750     // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21751     if (dt.Is(F64) && cond.IsNotNever()) {
21752       EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21753               rm.Encode(5, 0));
21754       return;
21755     }
21756   }
21757   Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21758 }
21759 
vneg(Condition cond,DataType dt,QRegister rd,QRegister rm)21760 void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
21761   VIXL_ASSERT(AllowAssembler());
21762   CheckIT(cond);
21763   Dt_F_size_1 encoded_dt(dt);
21764   if (IsUsingT32()) {
21765     // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21766     if (encoded_dt.IsValid()) {
21767       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21768         EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21769                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21770                    rd.Encode(22, 12) | rm.Encode(5, 0));
21771         AdvanceIT();
21772         return;
21773       }
21774     }
21775   } else {
21776     // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21777     if (encoded_dt.IsValid()) {
21778       if (cond.Is(al)) {
21779         EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21780                 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21781                 rd.Encode(22, 12) | rm.Encode(5, 0));
21782         return;
21783       }
21784     }
21785   }
21786   Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21787 }
21788 
vneg(Condition cond,DataType dt,SRegister rd,SRegister rm)21789 void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
21790   VIXL_ASSERT(AllowAssembler());
21791   CheckIT(cond);
21792   if (IsUsingT32()) {
21793     // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21794     if (dt.Is(F32)) {
21795       EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21796       AdvanceIT();
21797       return;
21798     }
21799   } else {
21800     // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21801     if (dt.Is(F32) && cond.IsNotNever()) {
21802       EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21803               rm.Encode(5, 0));
21804       return;
21805     }
21806   }
21807   Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21808 }
21809 
vnmla(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)21810 void Assembler::vnmla(
21811     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21812   VIXL_ASSERT(AllowAssembler());
21813   CheckIT(cond);
21814   if (IsUsingT32()) {
21815     // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21816     if (dt.Is(F32)) {
21817       EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21818                  rm.Encode(5, 0));
21819       AdvanceIT();
21820       return;
21821     }
21822   } else {
21823     // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21824     if (dt.Is(F32) && cond.IsNotNever()) {
21825       EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21826               rn.Encode(7, 16) | rm.Encode(5, 0));
21827       return;
21828     }
21829   }
21830   Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21831 }
21832 
vnmla(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)21833 void Assembler::vnmla(
21834     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21835   VIXL_ASSERT(AllowAssembler());
21836   CheckIT(cond);
21837   if (IsUsingT32()) {
21838     // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21839     if (dt.Is(F64)) {
21840       EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21841                  rm.Encode(5, 0));
21842       AdvanceIT();
21843       return;
21844     }
21845   } else {
21846     // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21847     if (dt.Is(F64) && cond.IsNotNever()) {
21848       EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21849               rn.Encode(7, 16) | rm.Encode(5, 0));
21850       return;
21851     }
21852   }
21853   Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21854 }
21855 
vnmls(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)21856 void Assembler::vnmls(
21857     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21858   VIXL_ASSERT(AllowAssembler());
21859   CheckIT(cond);
21860   if (IsUsingT32()) {
21861     // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21862     if (dt.Is(F32)) {
21863       EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21864                  rm.Encode(5, 0));
21865       AdvanceIT();
21866       return;
21867     }
21868   } else {
21869     // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21870     if (dt.Is(F32) && cond.IsNotNever()) {
21871       EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21872               rn.Encode(7, 16) | rm.Encode(5, 0));
21873       return;
21874     }
21875   }
21876   Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21877 }
21878 
vnmls(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)21879 void Assembler::vnmls(
21880     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21881   VIXL_ASSERT(AllowAssembler());
21882   CheckIT(cond);
21883   if (IsUsingT32()) {
21884     // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21885     if (dt.Is(F64)) {
21886       EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21887                  rm.Encode(5, 0));
21888       AdvanceIT();
21889       return;
21890     }
21891   } else {
21892     // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21893     if (dt.Is(F64) && cond.IsNotNever()) {
21894       EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21895               rn.Encode(7, 16) | rm.Encode(5, 0));
21896       return;
21897     }
21898   }
21899   Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21900 }
21901 
vnmul(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)21902 void Assembler::vnmul(
21903     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21904   VIXL_ASSERT(AllowAssembler());
21905   CheckIT(cond);
21906   if (IsUsingT32()) {
21907     // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
21908     if (dt.Is(F32)) {
21909       EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21910                  rm.Encode(5, 0));
21911       AdvanceIT();
21912       return;
21913     }
21914   } else {
21915     // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
21916     if (dt.Is(F32) && cond.IsNotNever()) {
21917       EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21918               rn.Encode(7, 16) | rm.Encode(5, 0));
21919       return;
21920     }
21921   }
21922   Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21923 }
21924 
vnmul(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)21925 void Assembler::vnmul(
21926     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21927   VIXL_ASSERT(AllowAssembler());
21928   CheckIT(cond);
21929   if (IsUsingT32()) {
21930     // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
21931     if (dt.Is(F64)) {
21932       EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21933                  rm.Encode(5, 0));
21934       AdvanceIT();
21935       return;
21936     }
21937   } else {
21938     // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
21939     if (dt.Is(F64) && cond.IsNotNever()) {
21940       EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21941               rn.Encode(7, 16) | rm.Encode(5, 0));
21942       return;
21943     }
21944   }
21945   Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21946 }
21947 
vorn(Condition cond,DataType dt,DRegister rd,DRegister rn,const DOperand & operand)21948 void Assembler::vorn(Condition cond,
21949                      DataType dt,
21950                      DRegister rd,
21951                      DRegister rn,
21952                      const DOperand& operand) {
21953   VIXL_ASSERT(AllowAssembler());
21954   CheckIT(cond);
21955   if (operand.IsImmediate()) {
21956     ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
21957     if (IsUsingT32()) {
21958       // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
21959       if (encoded_dt.IsValid() && rd.Is(rn)) {
21960         if (cond.Is(al) || AllowStronglyDiscouraged()) {
21961           EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
21962                      rd.Encode(22, 12) |
21963                      (encoded_dt.GetEncodedImmediate() & 0xf) |
21964                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21965                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21966           AdvanceIT();
21967           return;
21968         }
21969       }
21970     } else {
21971       // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
21972       if (encoded_dt.IsValid() && rd.Is(rn)) {
21973         if (cond.Is(al)) {
21974           EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
21975                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21976                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21977                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21978           return;
21979         }
21980       }
21981     }
21982   }
21983   if (operand.IsRegister()) {
21984     DRegister rm = operand.GetRegister();
21985     USE(dt);
21986     if (IsUsingT32()) {
21987       // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
21988       if (cond.Is(al) || AllowStronglyDiscouraged()) {
21989         EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21990                    rm.Encode(5, 0));
21991         AdvanceIT();
21992         return;
21993       }
21994     } else {
21995       // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
21996       if (cond.Is(al)) {
21997         EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21998                 rm.Encode(5, 0));
21999         return;
22000       }
22001     }
22002   }
22003   Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
22004 }
22005 
vorn(Condition cond,DataType dt,QRegister rd,QRegister rn,const QOperand & operand)22006 void Assembler::vorn(Condition cond,
22007                      DataType dt,
22008                      QRegister rd,
22009                      QRegister rn,
22010                      const QOperand& operand) {
22011   VIXL_ASSERT(AllowAssembler());
22012   CheckIT(cond);
22013   if (operand.IsImmediate()) {
22014     ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
22015     if (IsUsingT32()) {
22016       // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22017       if (encoded_dt.IsValid() && rd.Is(rn)) {
22018         if (cond.Is(al) || AllowStronglyDiscouraged()) {
22019           EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22020                      rd.Encode(22, 12) |
22021                      (encoded_dt.GetEncodedImmediate() & 0xf) |
22022                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22023                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22024           AdvanceIT();
22025           return;
22026         }
22027       }
22028     } else {
22029       // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22030       if (encoded_dt.IsValid() && rd.Is(rn)) {
22031         if (cond.Is(al)) {
22032           EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22033                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22034                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22035                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22036           return;
22037         }
22038       }
22039     }
22040   }
22041   if (operand.IsRegister()) {
22042     QRegister rm = operand.GetRegister();
22043     USE(dt);
22044     if (IsUsingT32()) {
22045       // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22046       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22047         EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22048                    rm.Encode(5, 0));
22049         AdvanceIT();
22050         return;
22051       }
22052     } else {
22053       // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22054       if (cond.Is(al)) {
22055         EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22056                 rm.Encode(5, 0));
22057         return;
22058       }
22059     }
22060   }
22061   Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
22062 }
22063 
vorr(Condition cond,DataType dt,DRegister rd,DRegister rn,const DOperand & operand)22064 void Assembler::vorr(Condition cond,
22065                      DataType dt,
22066                      DRegister rd,
22067                      DRegister rn,
22068                      const DOperand& operand) {
22069   VIXL_ASSERT(AllowAssembler());
22070   CheckIT(cond);
22071   if (operand.IsRegister()) {
22072     DRegister rm = operand.GetRegister();
22073     USE(dt);
22074     if (IsUsingT32()) {
22075       // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
22076       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22077         EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22078                    rm.Encode(5, 0));
22079         AdvanceIT();
22080         return;
22081       }
22082     } else {
22083       // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
22084       if (cond.Is(al)) {
22085         EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22086                 rm.Encode(5, 0));
22087         return;
22088       }
22089     }
22090   }
22091   if (operand.IsImmediate()) {
22092     ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
22093     if (IsUsingT32()) {
22094       // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
22095       if (encoded_dt.IsValid() && rd.Is(rn)) {
22096         if (cond.Is(al) || AllowStronglyDiscouraged()) {
22097           EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
22098                      rd.Encode(22, 12) |
22099                      (encoded_dt.GetEncodedImmediate() & 0xf) |
22100                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22101                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22102           AdvanceIT();
22103           return;
22104         }
22105       }
22106     } else {
22107       // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
22108       if (encoded_dt.IsValid() && rd.Is(rn)) {
22109         if (cond.Is(al)) {
22110           EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
22111                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22112                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22113                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22114           return;
22115         }
22116       }
22117     }
22118   }
22119   Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22120 }
22121 
vorr(Condition cond,DataType dt,QRegister rd,QRegister rn,const QOperand & operand)22122 void Assembler::vorr(Condition cond,
22123                      DataType dt,
22124                      QRegister rd,
22125                      QRegister rn,
22126                      const QOperand& operand) {
22127   VIXL_ASSERT(AllowAssembler());
22128   CheckIT(cond);
22129   if (operand.IsRegister()) {
22130     QRegister rm = operand.GetRegister();
22131     USE(dt);
22132     if (IsUsingT32()) {
22133       // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22134       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22135         EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22136                    rm.Encode(5, 0));
22137         AdvanceIT();
22138         return;
22139       }
22140     } else {
22141       // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22142       if (cond.Is(al)) {
22143         EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22144                 rm.Encode(5, 0));
22145         return;
22146       }
22147     }
22148   }
22149   if (operand.IsImmediate()) {
22150     ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
22151     if (IsUsingT32()) {
22152       // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22153       if (encoded_dt.IsValid() && rd.Is(rn)) {
22154         if (cond.Is(al) || AllowStronglyDiscouraged()) {
22155           EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22156                      rd.Encode(22, 12) |
22157                      (encoded_dt.GetEncodedImmediate() & 0xf) |
22158                      ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22159                      ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22160           AdvanceIT();
22161           return;
22162         }
22163       }
22164     } else {
22165       // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22166       if (encoded_dt.IsValid() && rd.Is(rn)) {
22167         if (cond.Is(al)) {
22168           EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22169                   rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22170                   ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22171                   ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22172           return;
22173         }
22174       }
22175     }
22176   }
22177   Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22178 }
22179 
vpadal(Condition cond,DataType dt,DRegister rd,DRegister rm)22180 void Assembler::vpadal(Condition cond,
22181                        DataType dt,
22182                        DRegister rd,
22183                        DRegister rm) {
22184   VIXL_ASSERT(AllowAssembler());
22185   CheckIT(cond);
22186   Dt_op_size_2 encoded_dt(dt);
22187   if (IsUsingT32()) {
22188     // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22189     if (encoded_dt.IsValid()) {
22190       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22191         EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22192                    ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22193                    rd.Encode(22, 12) | rm.Encode(5, 0));
22194         AdvanceIT();
22195         return;
22196       }
22197     }
22198   } else {
22199     // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22200     if (encoded_dt.IsValid()) {
22201       if (cond.Is(al)) {
22202         EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22203                 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22204                 rd.Encode(22, 12) | rm.Encode(5, 0));
22205         return;
22206       }
22207     }
22208   }
22209   Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22210 }
22211 
vpadal(Condition cond,DataType dt,QRegister rd,QRegister rm)22212 void Assembler::vpadal(Condition cond,
22213                        DataType dt,
22214                        QRegister rd,
22215                        QRegister rm) {
22216   VIXL_ASSERT(AllowAssembler());
22217   CheckIT(cond);
22218   Dt_op_size_2 encoded_dt(dt);
22219   if (IsUsingT32()) {
22220     // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22221     if (encoded_dt.IsValid()) {
22222       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22223         EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22224                    ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22225                    rd.Encode(22, 12) | rm.Encode(5, 0));
22226         AdvanceIT();
22227         return;
22228       }
22229     }
22230   } else {
22231     // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22232     if (encoded_dt.IsValid()) {
22233       if (cond.Is(al)) {
22234         EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22235                 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22236                 rd.Encode(22, 12) | rm.Encode(5, 0));
22237         return;
22238       }
22239     }
22240   }
22241   Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22242 }
22243 
vpadd(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)22244 void Assembler::vpadd(
22245     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22246   VIXL_ASSERT(AllowAssembler());
22247   CheckIT(cond);
22248   Dt_size_4 encoded_dt(dt);
22249   if (IsUsingT32()) {
22250     // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22251     if (dt.Is(F32)) {
22252       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22253         EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22254                    rm.Encode(5, 0));
22255         AdvanceIT();
22256         return;
22257       }
22258     }
22259     // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22260     if (encoded_dt.IsValid()) {
22261       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22262         EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
22263                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22264         AdvanceIT();
22265         return;
22266       }
22267     }
22268   } else {
22269     // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22270     if (dt.Is(F32)) {
22271       if (cond.Is(al)) {
22272         EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22273                 rm.Encode(5, 0));
22274         return;
22275       }
22276     }
22277     // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22278     if (encoded_dt.IsValid()) {
22279       if (cond.Is(al)) {
22280         EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
22281                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22282         return;
22283       }
22284     }
22285   }
22286   Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
22287 }
22288 
vpaddl(Condition cond,DataType dt,DRegister rd,DRegister rm)22289 void Assembler::vpaddl(Condition cond,
22290                        DataType dt,
22291                        DRegister rd,
22292                        DRegister rm) {
22293   VIXL_ASSERT(AllowAssembler());
22294   CheckIT(cond);
22295   Dt_op_size_2 encoded_dt(dt);
22296   if (IsUsingT32()) {
22297     // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22298     if (encoded_dt.IsValid()) {
22299       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22300         EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22301                    ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22302                    rd.Encode(22, 12) | rm.Encode(5, 0));
22303         AdvanceIT();
22304         return;
22305       }
22306     }
22307   } else {
22308     // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22309     if (encoded_dt.IsValid()) {
22310       if (cond.Is(al)) {
22311         EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22312                 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22313                 rd.Encode(22, 12) | rm.Encode(5, 0));
22314         return;
22315       }
22316     }
22317   }
22318   Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22319 }
22320 
vpaddl(Condition cond,DataType dt,QRegister rd,QRegister rm)22321 void Assembler::vpaddl(Condition cond,
22322                        DataType dt,
22323                        QRegister rd,
22324                        QRegister rm) {
22325   VIXL_ASSERT(AllowAssembler());
22326   CheckIT(cond);
22327   Dt_op_size_2 encoded_dt(dt);
22328   if (IsUsingT32()) {
22329     // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22330     if (encoded_dt.IsValid()) {
22331       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22332         EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22333                    ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22334                    rd.Encode(22, 12) | rm.Encode(5, 0));
22335         AdvanceIT();
22336         return;
22337       }
22338     }
22339   } else {
22340     // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22341     if (encoded_dt.IsValid()) {
22342       if (cond.Is(al)) {
22343         EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22344                 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22345                 rd.Encode(22, 12) | rm.Encode(5, 0));
22346         return;
22347       }
22348     }
22349   }
22350   Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22351 }
22352 
vpmax(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)22353 void Assembler::vpmax(
22354     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22355   VIXL_ASSERT(AllowAssembler());
22356   CheckIT(cond);
22357   Dt_U_size_1 encoded_dt(dt);
22358   if (IsUsingT32()) {
22359     // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22360     if (dt.Is(F32)) {
22361       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22362         EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22363                    rm.Encode(5, 0));
22364         AdvanceIT();
22365         return;
22366       }
22367     }
22368     // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22369     if (encoded_dt.IsValid()) {
22370       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22371         EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22372                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22373                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22374         AdvanceIT();
22375         return;
22376       }
22377     }
22378   } else {
22379     // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22380     if (dt.Is(F32)) {
22381       if (cond.Is(al)) {
22382         EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22383                 rm.Encode(5, 0));
22384         return;
22385       }
22386     }
22387     // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22388     if (encoded_dt.IsValid()) {
22389       if (cond.Is(al)) {
22390         EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22391                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22392                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22393         return;
22394       }
22395     }
22396   }
22397   Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
22398 }
22399 
vpmin(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)22400 void Assembler::vpmin(
22401     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22402   VIXL_ASSERT(AllowAssembler());
22403   CheckIT(cond);
22404   Dt_U_size_1 encoded_dt(dt);
22405   if (IsUsingT32()) {
22406     // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22407     if (dt.Is(F32)) {
22408       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22409         EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22410                    rm.Encode(5, 0));
22411         AdvanceIT();
22412         return;
22413       }
22414     }
22415     // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22416     if (encoded_dt.IsValid()) {
22417       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22418         EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22419                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22420                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22421         AdvanceIT();
22422         return;
22423       }
22424     }
22425   } else {
22426     // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22427     if (dt.Is(F32)) {
22428       if (cond.Is(al)) {
22429         EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22430                 rm.Encode(5, 0));
22431         return;
22432       }
22433     }
22434     // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22435     if (encoded_dt.IsValid()) {
22436       if (cond.Is(al)) {
22437         EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22438                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22439                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22440         return;
22441       }
22442     }
22443   }
22444   Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
22445 }
22446 
vpop(Condition cond,DataType dt,DRegisterList dreglist)22447 void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
22448   VIXL_ASSERT(AllowAssembler());
22449   CheckIT(cond);
22450   USE(dt);
22451   if (IsUsingT32()) {
22452     // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
22453     if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
22454       const DRegister& dreg = dreglist.GetFirstDRegister();
22455       unsigned len = dreglist.GetLength() * 2;
22456       EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
22457       AdvanceIT();
22458       return;
22459     }
22460   } else {
22461     // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
22462     if (cond.IsNotNever() &&
22463         ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
22464       const DRegister& dreg = dreglist.GetFirstDRegister();
22465       unsigned len = dreglist.GetLength() * 2;
22466       EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22467               (len & 0xff));
22468       return;
22469     }
22470   }
22471   Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
22472 }
22473 
vpop(Condition cond,DataType dt,SRegisterList sreglist)22474 void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
22475   VIXL_ASSERT(AllowAssembler());
22476   CheckIT(cond);
22477   USE(dt);
22478   if (IsUsingT32()) {
22479     // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
22480     const SRegister& sreg = sreglist.GetFirstSRegister();
22481     unsigned len = sreglist.GetLength();
22482     EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
22483     AdvanceIT();
22484     return;
22485   } else {
22486     // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
22487     if (cond.IsNotNever()) {
22488       const SRegister& sreg = sreglist.GetFirstSRegister();
22489       unsigned len = sreglist.GetLength();
22490       EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22491               (len & 0xff));
22492       return;
22493     }
22494   }
22495   Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
22496 }
22497 
vpush(Condition cond,DataType dt,DRegisterList dreglist)22498 void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
22499   VIXL_ASSERT(AllowAssembler());
22500   CheckIT(cond);
22501   USE(dt);
22502   if (IsUsingT32()) {
22503     // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
22504     if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
22505       const DRegister& dreg = dreglist.GetFirstDRegister();
22506       unsigned len = dreglist.GetLength() * 2;
22507       EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
22508       AdvanceIT();
22509       return;
22510     }
22511   } else {
22512     // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
22513     if (cond.IsNotNever() &&
22514         ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
22515       const DRegister& dreg = dreglist.GetFirstDRegister();
22516       unsigned len = dreglist.GetLength() * 2;
22517       EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22518               (len & 0xff));
22519       return;
22520     }
22521   }
22522   Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
22523 }
22524 
vpush(Condition cond,DataType dt,SRegisterList sreglist)22525 void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
22526   VIXL_ASSERT(AllowAssembler());
22527   CheckIT(cond);
22528   USE(dt);
22529   if (IsUsingT32()) {
22530     // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
22531     const SRegister& sreg = sreglist.GetFirstSRegister();
22532     unsigned len = sreglist.GetLength();
22533     EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
22534     AdvanceIT();
22535     return;
22536   } else {
22537     // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
22538     if (cond.IsNotNever()) {
22539       const SRegister& sreg = sreglist.GetFirstSRegister();
22540       unsigned len = sreglist.GetLength();
22541       EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22542               (len & 0xff));
22543       return;
22544     }
22545   }
22546   Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
22547 }
22548 
vqabs(Condition cond,DataType dt,DRegister rd,DRegister rm)22549 void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
22550   VIXL_ASSERT(AllowAssembler());
22551   CheckIT(cond);
22552   Dt_size_5 encoded_dt(dt);
22553   if (IsUsingT32()) {
22554     // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22555     if (encoded_dt.IsValid()) {
22556       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22557         EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
22558                    rd.Encode(22, 12) | rm.Encode(5, 0));
22559         AdvanceIT();
22560         return;
22561       }
22562     }
22563   } else {
22564     // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22565     if (encoded_dt.IsValid()) {
22566       if (cond.Is(al)) {
22567         EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
22568                 rd.Encode(22, 12) | rm.Encode(5, 0));
22569         return;
22570       }
22571     }
22572   }
22573   Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22574 }
22575 
vqabs(Condition cond,DataType dt,QRegister rd,QRegister rm)22576 void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
22577   VIXL_ASSERT(AllowAssembler());
22578   CheckIT(cond);
22579   Dt_size_5 encoded_dt(dt);
22580   if (IsUsingT32()) {
22581     // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22582     if (encoded_dt.IsValid()) {
22583       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22584         EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
22585                    rd.Encode(22, 12) | rm.Encode(5, 0));
22586         AdvanceIT();
22587         return;
22588       }
22589     }
22590   } else {
22591     // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22592     if (encoded_dt.IsValid()) {
22593       if (cond.Is(al)) {
22594         EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
22595                 rd.Encode(22, 12) | rm.Encode(5, 0));
22596         return;
22597       }
22598     }
22599   }
22600   Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22601 }
22602 
vqadd(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)22603 void Assembler::vqadd(
22604     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22605   VIXL_ASSERT(AllowAssembler());
22606   CheckIT(cond);
22607   Dt_U_size_3 encoded_dt(dt);
22608   if (IsUsingT32()) {
22609     // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22610     if (encoded_dt.IsValid()) {
22611       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22612         EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22613                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22614                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22615         AdvanceIT();
22616         return;
22617       }
22618     }
22619   } else {
22620     // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22621     if (encoded_dt.IsValid()) {
22622       if (cond.Is(al)) {
22623         EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22624                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22625                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22626         return;
22627       }
22628     }
22629   }
22630   Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22631 }
22632 
vqadd(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)22633 void Assembler::vqadd(
22634     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22635   VIXL_ASSERT(AllowAssembler());
22636   CheckIT(cond);
22637   Dt_U_size_3 encoded_dt(dt);
22638   if (IsUsingT32()) {
22639     // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22640     if (encoded_dt.IsValid()) {
22641       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22642         EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22643                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22644                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22645         AdvanceIT();
22646         return;
22647       }
22648     }
22649   } else {
22650     // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22651     if (encoded_dt.IsValid()) {
22652       if (cond.Is(al)) {
22653         EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22654                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22655                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22656         return;
22657       }
22658     }
22659   }
22660   Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22661 }
22662 
vqdmlal(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)22663 void Assembler::vqdmlal(
22664     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
22665   VIXL_ASSERT(AllowAssembler());
22666   CheckIT(cond);
22667   Dt_size_13 encoded_dt(dt);
22668   if (IsUsingT32()) {
22669     // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22670     if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22671       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22672         EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
22673                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22674         AdvanceIT();
22675         return;
22676       }
22677     }
22678   } else {
22679     // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22680     if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22681       if (cond.Is(al)) {
22682         EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
22683                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22684         return;
22685       }
22686     }
22687   }
22688   Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
22689 }
22690 
vqdmlal(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister dm,unsigned index)22691 void Assembler::vqdmlal(Condition cond,
22692                         DataType dt,
22693                         QRegister rd,
22694                         DRegister rn,
22695                         DRegister dm,
22696                         unsigned index) {
22697   VIXL_ASSERT(AllowAssembler());
22698   CheckIT(cond);
22699   Dt_size_13 encoded_dt(dt);
22700   if (IsUsingT32()) {
22701     // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22702     if (encoded_dt.IsValid() &&
22703         ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22704          (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22705         (dt.Is(S16) || dt.Is(S32))) {
22706       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22707         uint32_t shift = 4;
22708         if (dt.Is(S16)) {
22709           shift = 3;
22710         }
22711         uint32_t mvm = dm.GetCode() | index << shift;
22712         EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
22713                    rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22714                    ((mvm & 0x10) << 1));
22715         AdvanceIT();
22716         return;
22717       }
22718     }
22719   } else {
22720     // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22721     if (encoded_dt.IsValid() &&
22722         ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22723          (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22724         (dt.Is(S16) || dt.Is(S32))) {
22725       if (cond.Is(al)) {
22726         uint32_t shift = 4;
22727         if (dt.Is(S16)) {
22728           shift = 3;
22729         }
22730         uint32_t mvm = dm.GetCode() | index << shift;
22731         EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
22732                 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22733                 ((mvm & 0x10) << 1));
22734         return;
22735       }
22736     }
22737   }
22738   Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
22739 }
22740 
vqdmlsl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)22741 void Assembler::vqdmlsl(
22742     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
22743   VIXL_ASSERT(AllowAssembler());
22744   CheckIT(cond);
22745   Dt_size_13 encoded_dt(dt);
22746   if (IsUsingT32()) {
22747     // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22748     if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22749       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22750         EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
22751                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22752         AdvanceIT();
22753         return;
22754       }
22755     }
22756   } else {
22757     // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22758     if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22759       if (cond.Is(al)) {
22760         EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
22761                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22762         return;
22763       }
22764     }
22765   }
22766   Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
22767 }
22768 
vqdmlsl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister dm,unsigned index)22769 void Assembler::vqdmlsl(Condition cond,
22770                         DataType dt,
22771                         QRegister rd,
22772                         DRegister rn,
22773                         DRegister dm,
22774                         unsigned index) {
22775   VIXL_ASSERT(AllowAssembler());
22776   CheckIT(cond);
22777   Dt_size_13 encoded_dt(dt);
22778   if (IsUsingT32()) {
22779     // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22780     if (encoded_dt.IsValid() &&
22781         ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22782          (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22783         (dt.Is(S16) || dt.Is(S32))) {
22784       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22785         uint32_t shift = 4;
22786         if (dt.Is(S16)) {
22787           shift = 3;
22788         }
22789         uint32_t mvm = dm.GetCode() | index << shift;
22790         EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
22791                    rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22792                    ((mvm & 0x10) << 1));
22793         AdvanceIT();
22794         return;
22795       }
22796     }
22797   } else {
22798     // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22799     if (encoded_dt.IsValid() &&
22800         ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22801          (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22802         (dt.Is(S16) || dt.Is(S32))) {
22803       if (cond.Is(al)) {
22804         uint32_t shift = 4;
22805         if (dt.Is(S16)) {
22806           shift = 3;
22807         }
22808         uint32_t mvm = dm.GetCode() | index << shift;
22809         EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
22810                 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22811                 ((mvm & 0x10) << 1));
22812         return;
22813       }
22814     }
22815   }
22816   Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
22817 }
22818 
vqdmulh(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)22819 void Assembler::vqdmulh(
22820     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22821   VIXL_ASSERT(AllowAssembler());
22822   CheckIT(cond);
22823   Dt_size_13 encoded_dt(dt);
22824   if (IsUsingT32()) {
22825     // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22826     if (encoded_dt.IsValid()) {
22827       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22828         EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
22829                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22830         AdvanceIT();
22831         return;
22832       }
22833     }
22834   } else {
22835     // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22836     if (encoded_dt.IsValid()) {
22837       if (cond.Is(al)) {
22838         EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
22839                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22840         return;
22841       }
22842     }
22843   }
22844   Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22845 }
22846 
vqdmulh(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)22847 void Assembler::vqdmulh(
22848     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22849   VIXL_ASSERT(AllowAssembler());
22850   CheckIT(cond);
22851   Dt_size_13 encoded_dt(dt);
22852   if (IsUsingT32()) {
22853     // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22854     if (encoded_dt.IsValid()) {
22855       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22856         EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
22857                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22858         AdvanceIT();
22859         return;
22860       }
22861     }
22862   } else {
22863     // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22864     if (encoded_dt.IsValid()) {
22865       if (cond.Is(al)) {
22866         EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
22867                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22868         return;
22869       }
22870     }
22871   }
22872   Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22873 }
22874 
vqdmulh(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegisterLane rm)22875 void Assembler::vqdmulh(
22876     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
22877   VIXL_ASSERT(AllowAssembler());
22878   CheckIT(cond);
22879   Dt_size_13 encoded_dt(dt);
22880   if (IsUsingT32()) {
22881     // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
22882     if (encoded_dt.IsValid() &&
22883         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22884          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22885           (rm.GetLane() <= 1))) &&
22886         (dt.Is(S16) || dt.Is(S32))) {
22887       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22888         EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
22889                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22890         AdvanceIT();
22891         return;
22892       }
22893     }
22894   } else {
22895     // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
22896     if (encoded_dt.IsValid() &&
22897         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22898          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22899           (rm.GetLane() <= 1))) &&
22900         (dt.Is(S16) || dt.Is(S32))) {
22901       if (cond.Is(al)) {
22902         EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
22903                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22904         return;
22905       }
22906     }
22907   }
22908   Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22909 }
22910 
vqdmulh(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegisterLane rm)22911 void Assembler::vqdmulh(
22912     Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
22913   VIXL_ASSERT(AllowAssembler());
22914   CheckIT(cond);
22915   Dt_size_13 encoded_dt(dt);
22916   if (IsUsingT32()) {
22917     // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
22918     if (encoded_dt.IsValid() &&
22919         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22920          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22921           (rm.GetLane() <= 1))) &&
22922         (dt.Is(S16) || dt.Is(S32))) {
22923       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22924         EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
22925                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22926         AdvanceIT();
22927         return;
22928       }
22929     }
22930   } else {
22931     // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
22932     if (encoded_dt.IsValid() &&
22933         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22934          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22935           (rm.GetLane() <= 1))) &&
22936         (dt.Is(S16) || dt.Is(S32))) {
22937       if (cond.Is(al)) {
22938         EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
22939                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22940         return;
22941       }
22942     }
22943   }
22944   Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22945 }
22946 
vqdmull(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)22947 void Assembler::vqdmull(
22948     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
22949   VIXL_ASSERT(AllowAssembler());
22950   CheckIT(cond);
22951   Dt_size_13 encoded_dt(dt);
22952   if (IsUsingT32()) {
22953     // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22954     if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22955       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22956         EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
22957                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22958         AdvanceIT();
22959         return;
22960       }
22961     }
22962   } else {
22963     // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22964     if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22965       if (cond.Is(al)) {
22966         EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
22967                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22968         return;
22969       }
22970     }
22971   }
22972   Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22973 }
22974 
vqdmull(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegisterLane rm)22975 void Assembler::vqdmull(
22976     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
22977   VIXL_ASSERT(AllowAssembler());
22978   CheckIT(cond);
22979   Dt_size_13 encoded_dt(dt);
22980   if (IsUsingT32()) {
22981     // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
22982     if (encoded_dt.IsValid() &&
22983         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22984          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22985           (rm.GetLane() <= 1))) &&
22986         (dt.Is(S16) || dt.Is(S32))) {
22987       if (cond.Is(al) || AllowStronglyDiscouraged()) {
22988         EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
22989                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22990         AdvanceIT();
22991         return;
22992       }
22993     }
22994   } else {
22995     // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
22996     if (encoded_dt.IsValid() &&
22997         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22998          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22999           (rm.GetLane() <= 1))) &&
23000         (dt.Is(S16) || dt.Is(S32))) {
23001       if (cond.Is(al)) {
23002         EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
23003                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23004         return;
23005       }
23006     }
23007   }
23008   Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
23009 }
23010 
vqmovn(Condition cond,DataType dt,DRegister rd,QRegister rm)23011 void Assembler::vqmovn(Condition cond,
23012                        DataType dt,
23013                        DRegister rd,
23014                        QRegister rm) {
23015   VIXL_ASSERT(AllowAssembler());
23016   CheckIT(cond);
23017   Dt_op_size_3 encoded_dt(dt);
23018   if (IsUsingT32()) {
23019     // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
23020     if (encoded_dt.IsValid()) {
23021       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23022         EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23023                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23024                    rd.Encode(22, 12) | rm.Encode(5, 0));
23025         AdvanceIT();
23026         return;
23027       }
23028     }
23029   } else {
23030     // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
23031     if (encoded_dt.IsValid()) {
23032       if (cond.Is(al)) {
23033         EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23034                 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23035                 rd.Encode(22, 12) | rm.Encode(5, 0));
23036         return;
23037       }
23038     }
23039   }
23040   Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
23041 }
23042 
vqmovun(Condition cond,DataType dt,DRegister rd,QRegister rm)23043 void Assembler::vqmovun(Condition cond,
23044                         DataType dt,
23045                         DRegister rd,
23046                         QRegister rm) {
23047   VIXL_ASSERT(AllowAssembler());
23048   CheckIT(cond);
23049   Dt_size_14 encoded_dt(dt);
23050   if (IsUsingT32()) {
23051     // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
23052     if (encoded_dt.IsValid()) {
23053       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23054         EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
23055                    rd.Encode(22, 12) | rm.Encode(5, 0));
23056         AdvanceIT();
23057         return;
23058       }
23059     }
23060   } else {
23061     // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
23062     if (encoded_dt.IsValid()) {
23063       if (cond.Is(al)) {
23064         EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
23065                 rd.Encode(22, 12) | rm.Encode(5, 0));
23066         return;
23067       }
23068     }
23069   }
23070   Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
23071 }
23072 
vqneg(Condition cond,DataType dt,DRegister rd,DRegister rm)23073 void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
23074   VIXL_ASSERT(AllowAssembler());
23075   CheckIT(cond);
23076   Dt_size_5 encoded_dt(dt);
23077   if (IsUsingT32()) {
23078     // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23079     if (encoded_dt.IsValid()) {
23080       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23081         EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
23082                    rd.Encode(22, 12) | rm.Encode(5, 0));
23083         AdvanceIT();
23084         return;
23085       }
23086     }
23087   } else {
23088     // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23089     if (encoded_dt.IsValid()) {
23090       if (cond.Is(al)) {
23091         EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
23092                 rd.Encode(22, 12) | rm.Encode(5, 0));
23093         return;
23094       }
23095     }
23096   }
23097   Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23098 }
23099 
vqneg(Condition cond,DataType dt,QRegister rd,QRegister rm)23100 void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
23101   VIXL_ASSERT(AllowAssembler());
23102   CheckIT(cond);
23103   Dt_size_5 encoded_dt(dt);
23104   if (IsUsingT32()) {
23105     // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23106     if (encoded_dt.IsValid()) {
23107       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23108         EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
23109                    rd.Encode(22, 12) | rm.Encode(5, 0));
23110         AdvanceIT();
23111         return;
23112       }
23113     }
23114   } else {
23115     // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23116     if (encoded_dt.IsValid()) {
23117       if (cond.Is(al)) {
23118         EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
23119                 rd.Encode(22, 12) | rm.Encode(5, 0));
23120         return;
23121       }
23122     }
23123   }
23124   Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23125 }
23126 
vqrdmulh(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)23127 void Assembler::vqrdmulh(
23128     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23129   VIXL_ASSERT(AllowAssembler());
23130   CheckIT(cond);
23131   Dt_size_13 encoded_dt(dt);
23132   if (IsUsingT32()) {
23133     // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23134     if (encoded_dt.IsValid()) {
23135       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23136         EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
23137                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23138         AdvanceIT();
23139         return;
23140       }
23141     }
23142   } else {
23143     // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23144     if (encoded_dt.IsValid()) {
23145       if (cond.Is(al)) {
23146         EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
23147                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23148         return;
23149       }
23150     }
23151   }
23152   Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23153 }
23154 
vqrdmulh(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)23155 void Assembler::vqrdmulh(
23156     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23157   VIXL_ASSERT(AllowAssembler());
23158   CheckIT(cond);
23159   Dt_size_13 encoded_dt(dt);
23160   if (IsUsingT32()) {
23161     // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23162     if (encoded_dt.IsValid()) {
23163       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23164         EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
23165                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23166         AdvanceIT();
23167         return;
23168       }
23169     }
23170   } else {
23171     // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23172     if (encoded_dt.IsValid()) {
23173       if (cond.Is(al)) {
23174         EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
23175                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23176         return;
23177       }
23178     }
23179   }
23180   Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23181 }
23182 
vqrdmulh(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegisterLane rm)23183 void Assembler::vqrdmulh(
23184     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
23185   VIXL_ASSERT(AllowAssembler());
23186   CheckIT(cond);
23187   Dt_size_13 encoded_dt(dt);
23188   if (IsUsingT32()) {
23189     // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
23190     if (encoded_dt.IsValid() &&
23191         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23192          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23193           (rm.GetLane() <= 1))) &&
23194         (dt.Is(S16) || dt.Is(S32))) {
23195       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23196         EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
23197                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23198         AdvanceIT();
23199         return;
23200       }
23201     }
23202   } else {
23203     // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
23204     if (encoded_dt.IsValid() &&
23205         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23206          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23207           (rm.GetLane() <= 1))) &&
23208         (dt.Is(S16) || dt.Is(S32))) {
23209       if (cond.Is(al)) {
23210         EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
23211                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23212         return;
23213       }
23214     }
23215   }
23216   Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23217 }
23218 
vqrdmulh(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegisterLane rm)23219 void Assembler::vqrdmulh(
23220     Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
23221   VIXL_ASSERT(AllowAssembler());
23222   CheckIT(cond);
23223   Dt_size_13 encoded_dt(dt);
23224   if (IsUsingT32()) {
23225     // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
23226     if (encoded_dt.IsValid() &&
23227         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23228          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23229           (rm.GetLane() <= 1))) &&
23230         (dt.Is(S16) || dt.Is(S32))) {
23231       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23232         EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
23233                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23234         AdvanceIT();
23235         return;
23236       }
23237     }
23238   } else {
23239     // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
23240     if (encoded_dt.IsValid() &&
23241         (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23242          ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23243           (rm.GetLane() <= 1))) &&
23244         (dt.Is(S16) || dt.Is(S32))) {
23245       if (cond.Is(al)) {
23246         EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
23247                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23248         return;
23249       }
23250     }
23251   }
23252   Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23253 }
23254 
vqrshl(Condition cond,DataType dt,DRegister rd,DRegister rm,DRegister rn)23255 void Assembler::vqrshl(
23256     Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
23257   VIXL_ASSERT(AllowAssembler());
23258   CheckIT(cond);
23259   Dt_U_size_3 encoded_dt(dt);
23260   if (IsUsingT32()) {
23261     // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23262     if (encoded_dt.IsValid()) {
23263       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23264         EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23265                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23266                    rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23267         AdvanceIT();
23268         return;
23269       }
23270     }
23271   } else {
23272     // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23273     if (encoded_dt.IsValid()) {
23274       if (cond.Is(al)) {
23275         EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23276                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23277                 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23278         return;
23279       }
23280     }
23281   }
23282   Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23283 }
23284 
vqrshl(Condition cond,DataType dt,QRegister rd,QRegister rm,QRegister rn)23285 void Assembler::vqrshl(
23286     Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
23287   VIXL_ASSERT(AllowAssembler());
23288   CheckIT(cond);
23289   Dt_U_size_3 encoded_dt(dt);
23290   if (IsUsingT32()) {
23291     // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23292     if (encoded_dt.IsValid()) {
23293       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23294         EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23295                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23296                    rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23297         AdvanceIT();
23298         return;
23299       }
23300     }
23301   } else {
23302     // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23303     if (encoded_dt.IsValid()) {
23304       if (cond.Is(al)) {
23305         EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23306                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23307                 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23308         return;
23309       }
23310     }
23311   }
23312   Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23313 }
23314 
vqrshrn(Condition cond,DataType dt,DRegister rd,QRegister rm,const QOperand & operand)23315 void Assembler::vqrshrn(Condition cond,
23316                         DataType dt,
23317                         DRegister rd,
23318                         QRegister rm,
23319                         const QOperand& operand) {
23320   VIXL_ASSERT(AllowAssembler());
23321   CheckIT(cond);
23322   if (operand.IsImmediate()) {
23323     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23324       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23325       Dt_op_size_3 encoded_dt(dt);
23326       Dt_imm6_1 encoded_dt_2(dt);
23327       if (IsUsingT32()) {
23328         // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23329         if (encoded_dt.IsValid() && (imm == 0)) {
23330           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23331             EmitT32_32(0xffb20280U |
23332                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23333                        ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23334                        rd.Encode(22, 12) | rm.Encode(5, 0));
23335             AdvanceIT();
23336             return;
23337           }
23338         }
23339         // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23340         if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23341           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23342             uint32_t imm6 = dt.GetSize() / 2 - imm;
23343             EmitT32_32(0xef800950U |
23344                        (encoded_dt_2.GetTypeEncodingValue() << 28) |
23345                        ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23346                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23347             AdvanceIT();
23348             return;
23349           }
23350         }
23351       } else {
23352         // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23353         if (encoded_dt.IsValid() && (imm == 0)) {
23354           if (cond.Is(al)) {
23355             EmitA32(0xf3b20280U |
23356                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23357                     ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23358                     rd.Encode(22, 12) | rm.Encode(5, 0));
23359             return;
23360           }
23361         }
23362         // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23363         if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23364           if (cond.Is(al)) {
23365             uint32_t imm6 = dt.GetSize() / 2 - imm;
23366             EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23367                     ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23368                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23369             return;
23370           }
23371         }
23372       }
23373     }
23374   }
23375   Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
23376 }
23377 
vqrshrun(Condition cond,DataType dt,DRegister rd,QRegister rm,const QOperand & operand)23378 void Assembler::vqrshrun(Condition cond,
23379                          DataType dt,
23380                          DRegister rd,
23381                          QRegister rm,
23382                          const QOperand& operand) {
23383   VIXL_ASSERT(AllowAssembler());
23384   CheckIT(cond);
23385   if (operand.IsImmediate()) {
23386     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23387       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23388       Dt_imm6_2 encoded_dt(dt);
23389       Dt_size_14 encoded_dt_2(dt);
23390       if (IsUsingT32()) {
23391         // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23392         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23393           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23394             uint32_t imm6 = dt.GetSize() / 2 - imm;
23395             EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
23396                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23397                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23398             AdvanceIT();
23399             return;
23400           }
23401         }
23402         // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23403         if (encoded_dt_2.IsValid() && (imm == 0)) {
23404           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23405             EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23406                        rd.Encode(22, 12) | rm.Encode(5, 0));
23407             AdvanceIT();
23408             return;
23409           }
23410         }
23411       } else {
23412         // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23413         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23414           if (cond.Is(al)) {
23415             uint32_t imm6 = dt.GetSize() / 2 - imm;
23416             EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
23417                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23418                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23419             return;
23420           }
23421         }
23422         // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23423         if (encoded_dt_2.IsValid() && (imm == 0)) {
23424           if (cond.Is(al)) {
23425             EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23426                     rd.Encode(22, 12) | rm.Encode(5, 0));
23427             return;
23428           }
23429         }
23430       }
23431     }
23432   }
23433   Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
23434 }
23435 
vqshl(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)23436 void Assembler::vqshl(Condition cond,
23437                       DataType dt,
23438                       DRegister rd,
23439                       DRegister rm,
23440                       const DOperand& operand) {
23441   VIXL_ASSERT(AllowAssembler());
23442   CheckIT(cond);
23443   if (operand.IsRegister()) {
23444     DRegister rn = operand.GetRegister();
23445     Dt_U_size_3 encoded_dt(dt);
23446     if (IsUsingT32()) {
23447       // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23448       if (encoded_dt.IsValid()) {
23449         if (cond.Is(al) || AllowStronglyDiscouraged()) {
23450           EmitT32_32(0xef000410U |
23451                      ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23452                      ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23453                      rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23454           AdvanceIT();
23455           return;
23456         }
23457       }
23458     } else {
23459       // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23460       if (encoded_dt.IsValid()) {
23461         if (cond.Is(al)) {
23462           EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23463                   ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23464                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23465           return;
23466         }
23467       }
23468     }
23469   }
23470   if (operand.IsImmediate()) {
23471     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23472       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23473       Dt_L_imm6_1 encoded_dt(dt);
23474       if (IsUsingT32()) {
23475         // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23476         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23477           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23478             uint32_t imm6 = imm;
23479             EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
23480                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23481                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23482                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23483             AdvanceIT();
23484             return;
23485           }
23486         }
23487       } else {
23488         // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23489         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23490           if (cond.Is(al)) {
23491             uint32_t imm6 = imm;
23492             EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
23493                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23494                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23495                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23496             return;
23497           }
23498         }
23499       }
23500     }
23501   }
23502   Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23503 }
23504 
vqshl(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)23505 void Assembler::vqshl(Condition cond,
23506                       DataType dt,
23507                       QRegister rd,
23508                       QRegister rm,
23509                       const QOperand& operand) {
23510   VIXL_ASSERT(AllowAssembler());
23511   CheckIT(cond);
23512   if (operand.IsRegister()) {
23513     QRegister rn = operand.GetRegister();
23514     Dt_U_size_3 encoded_dt(dt);
23515     if (IsUsingT32()) {
23516       // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23517       if (encoded_dt.IsValid()) {
23518         if (cond.Is(al) || AllowStronglyDiscouraged()) {
23519           EmitT32_32(0xef000450U |
23520                      ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23521                      ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23522                      rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23523           AdvanceIT();
23524           return;
23525         }
23526       }
23527     } else {
23528       // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23529       if (encoded_dt.IsValid()) {
23530         if (cond.Is(al)) {
23531           EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23532                   ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23533                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23534           return;
23535         }
23536       }
23537     }
23538   }
23539   if (operand.IsImmediate()) {
23540     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23541       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23542       Dt_L_imm6_1 encoded_dt(dt);
23543       if (IsUsingT32()) {
23544         // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23545         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23546           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23547             uint32_t imm6 = imm;
23548             EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
23549                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23550                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23551                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23552             AdvanceIT();
23553             return;
23554           }
23555         }
23556       } else {
23557         // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23558         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23559           if (cond.Is(al)) {
23560             uint32_t imm6 = imm;
23561             EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
23562                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23563                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23564                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23565             return;
23566           }
23567         }
23568       }
23569     }
23570   }
23571   Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23572 }
23573 
vqshlu(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)23574 void Assembler::vqshlu(Condition cond,
23575                        DataType dt,
23576                        DRegister rd,
23577                        DRegister rm,
23578                        const DOperand& operand) {
23579   VIXL_ASSERT(AllowAssembler());
23580   CheckIT(cond);
23581   if (operand.IsImmediate()) {
23582     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23583       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23584       Dt_L_imm6_2 encoded_dt(dt);
23585       if (IsUsingT32()) {
23586         // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23587         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23588           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23589             uint32_t imm6 = imm;
23590             EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
23591                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23592                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23593                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23594             AdvanceIT();
23595             return;
23596           }
23597         }
23598       } else {
23599         // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23600         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23601           if (cond.Is(al)) {
23602             uint32_t imm6 = imm;
23603             EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
23604                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23605                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23606                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23607             return;
23608           }
23609         }
23610       }
23611     }
23612   }
23613   Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23614 }
23615 
vqshlu(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)23616 void Assembler::vqshlu(Condition cond,
23617                        DataType dt,
23618                        QRegister rd,
23619                        QRegister rm,
23620                        const QOperand& operand) {
23621   VIXL_ASSERT(AllowAssembler());
23622   CheckIT(cond);
23623   if (operand.IsImmediate()) {
23624     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23625       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23626       Dt_L_imm6_2 encoded_dt(dt);
23627       if (IsUsingT32()) {
23628         // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23629         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23630           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23631             uint32_t imm6 = imm;
23632             EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
23633                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23634                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23635                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23636             AdvanceIT();
23637             return;
23638           }
23639         }
23640       } else {
23641         // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23642         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23643           if (cond.Is(al)) {
23644             uint32_t imm6 = imm;
23645             EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
23646                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23647                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23648                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23649             return;
23650           }
23651         }
23652       }
23653     }
23654   }
23655   Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23656 }
23657 
vqshrn(Condition cond,DataType dt,DRegister rd,QRegister rm,const QOperand & operand)23658 void Assembler::vqshrn(Condition cond,
23659                        DataType dt,
23660                        DRegister rd,
23661                        QRegister rm,
23662                        const QOperand& operand) {
23663   VIXL_ASSERT(AllowAssembler());
23664   CheckIT(cond);
23665   if (operand.IsImmediate()) {
23666     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23667       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23668       Dt_op_size_3 encoded_dt(dt);
23669       Dt_imm6_1 encoded_dt_2(dt);
23670       if (IsUsingT32()) {
23671         // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23672         if (encoded_dt.IsValid() && (imm == 0)) {
23673           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23674             EmitT32_32(0xffb20280U |
23675                        ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23676                        ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23677                        rd.Encode(22, 12) | rm.Encode(5, 0));
23678             AdvanceIT();
23679             return;
23680           }
23681         }
23682         // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23683         if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23684           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23685             uint32_t imm6 = dt.GetSize() / 2 - imm;
23686             EmitT32_32(0xef800910U |
23687                        (encoded_dt_2.GetTypeEncodingValue() << 28) |
23688                        ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23689                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23690             AdvanceIT();
23691             return;
23692           }
23693         }
23694       } else {
23695         // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23696         if (encoded_dt.IsValid() && (imm == 0)) {
23697           if (cond.Is(al)) {
23698             EmitA32(0xf3b20280U |
23699                     ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23700                     ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23701                     rd.Encode(22, 12) | rm.Encode(5, 0));
23702             return;
23703           }
23704         }
23705         // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23706         if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23707           if (cond.Is(al)) {
23708             uint32_t imm6 = dt.GetSize() / 2 - imm;
23709             EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23710                     ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23711                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23712             return;
23713           }
23714         }
23715       }
23716     }
23717   }
23718   Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
23719 }
23720 
vqshrun(Condition cond,DataType dt,DRegister rd,QRegister rm,const QOperand & operand)23721 void Assembler::vqshrun(Condition cond,
23722                         DataType dt,
23723                         DRegister rd,
23724                         QRegister rm,
23725                         const QOperand& operand) {
23726   VIXL_ASSERT(AllowAssembler());
23727   CheckIT(cond);
23728   if (operand.IsImmediate()) {
23729     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23730       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23731       Dt_imm6_2 encoded_dt(dt);
23732       Dt_size_14 encoded_dt_2(dt);
23733       if (IsUsingT32()) {
23734         // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23735         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23736           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23737             uint32_t imm6 = dt.GetSize() / 2 - imm;
23738             EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
23739                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23740                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23741             AdvanceIT();
23742             return;
23743           }
23744         }
23745         // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23746         if (encoded_dt_2.IsValid() && (imm == 0)) {
23747           if (cond.Is(al) || AllowStronglyDiscouraged()) {
23748             EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23749                        rd.Encode(22, 12) | rm.Encode(5, 0));
23750             AdvanceIT();
23751             return;
23752           }
23753         }
23754       } else {
23755         // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23756         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23757           if (cond.Is(al)) {
23758             uint32_t imm6 = dt.GetSize() / 2 - imm;
23759             EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
23760                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23761                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23762             return;
23763           }
23764         }
23765         // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23766         if (encoded_dt_2.IsValid() && (imm == 0)) {
23767           if (cond.Is(al)) {
23768             EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23769                     rd.Encode(22, 12) | rm.Encode(5, 0));
23770             return;
23771           }
23772         }
23773       }
23774     }
23775   }
23776   Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
23777 }
23778 
vqsub(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)23779 void Assembler::vqsub(
23780     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23781   VIXL_ASSERT(AllowAssembler());
23782   CheckIT(cond);
23783   Dt_U_size_3 encoded_dt(dt);
23784   if (IsUsingT32()) {
23785     // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23786     if (encoded_dt.IsValid()) {
23787       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23788         EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23789                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23790                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23791         AdvanceIT();
23792         return;
23793       }
23794     }
23795   } else {
23796     // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23797     if (encoded_dt.IsValid()) {
23798       if (cond.Is(al)) {
23799         EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23800                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23801                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23802         return;
23803       }
23804     }
23805   }
23806   Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23807 }
23808 
vqsub(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)23809 void Assembler::vqsub(
23810     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23811   VIXL_ASSERT(AllowAssembler());
23812   CheckIT(cond);
23813   Dt_U_size_3 encoded_dt(dt);
23814   if (IsUsingT32()) {
23815     // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23816     if (encoded_dt.IsValid()) {
23817       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23818         EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23819                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23820                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23821         AdvanceIT();
23822         return;
23823       }
23824     }
23825   } else {
23826     // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23827     if (encoded_dt.IsValid()) {
23828       if (cond.Is(al)) {
23829         EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23830                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23831                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23832         return;
23833       }
23834     }
23835   }
23836   Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23837 }
23838 
vraddhn(Condition cond,DataType dt,DRegister rd,QRegister rn,QRegister rm)23839 void Assembler::vraddhn(
23840     Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
23841   VIXL_ASSERT(AllowAssembler());
23842   CheckIT(cond);
23843   Dt_size_3 encoded_dt(dt);
23844   if (IsUsingT32()) {
23845     // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23846     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23847       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23848         EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
23849                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23850         AdvanceIT();
23851         return;
23852       }
23853     }
23854   } else {
23855     // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23856     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23857       if (cond.Is(al)) {
23858         EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
23859                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23860         return;
23861       }
23862     }
23863   }
23864   Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
23865 }
23866 
vrecpe(Condition cond,DataType dt,DRegister rd,DRegister rm)23867 void Assembler::vrecpe(Condition cond,
23868                        DataType dt,
23869                        DRegister rd,
23870                        DRegister rm) {
23871   VIXL_ASSERT(AllowAssembler());
23872   CheckIT(cond);
23873   Dt_F_size_4 encoded_dt(dt);
23874   if (IsUsingT32()) {
23875     // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23876     if (encoded_dt.IsValid()) {
23877       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23878         EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23879                    ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23880                    rd.Encode(22, 12) | rm.Encode(5, 0));
23881         AdvanceIT();
23882         return;
23883       }
23884     }
23885   } else {
23886     // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23887     if (encoded_dt.IsValid()) {
23888       if (cond.Is(al)) {
23889         EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23890                 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23891                 rd.Encode(22, 12) | rm.Encode(5, 0));
23892         return;
23893       }
23894     }
23895   }
23896   Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23897 }
23898 
vrecpe(Condition cond,DataType dt,QRegister rd,QRegister rm)23899 void Assembler::vrecpe(Condition cond,
23900                        DataType dt,
23901                        QRegister rd,
23902                        QRegister rm) {
23903   VIXL_ASSERT(AllowAssembler());
23904   CheckIT(cond);
23905   Dt_F_size_4 encoded_dt(dt);
23906   if (IsUsingT32()) {
23907     // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23908     if (encoded_dt.IsValid()) {
23909       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23910         EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23911                    ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23912                    rd.Encode(22, 12) | rm.Encode(5, 0));
23913         AdvanceIT();
23914         return;
23915       }
23916     }
23917   } else {
23918     // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23919     if (encoded_dt.IsValid()) {
23920       if (cond.Is(al)) {
23921         EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23922                 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23923                 rd.Encode(22, 12) | rm.Encode(5, 0));
23924         return;
23925       }
23926     }
23927   }
23928   Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23929 }
23930 
vrecps(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)23931 void Assembler::vrecps(
23932     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23933   VIXL_ASSERT(AllowAssembler());
23934   CheckIT(cond);
23935   if (IsUsingT32()) {
23936     // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23937     if (dt.Is(F32)) {
23938       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23939         EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23940                    rm.Encode(5, 0));
23941         AdvanceIT();
23942         return;
23943       }
23944     }
23945   } else {
23946     // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23947     if (dt.Is(F32)) {
23948       if (cond.Is(al)) {
23949         EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23950                 rm.Encode(5, 0));
23951         return;
23952       }
23953     }
23954   }
23955   Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23956 }
23957 
vrecps(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)23958 void Assembler::vrecps(
23959     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23960   VIXL_ASSERT(AllowAssembler());
23961   CheckIT(cond);
23962   if (IsUsingT32()) {
23963     // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23964     if (dt.Is(F32)) {
23965       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23966         EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23967                    rm.Encode(5, 0));
23968         AdvanceIT();
23969         return;
23970       }
23971     }
23972   } else {
23973     // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23974     if (dt.Is(F32)) {
23975       if (cond.Is(al)) {
23976         EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23977                 rm.Encode(5, 0));
23978         return;
23979       }
23980     }
23981   }
23982   Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23983 }
23984 
vrev16(Condition cond,DataType dt,DRegister rd,DRegister rm)23985 void Assembler::vrev16(Condition cond,
23986                        DataType dt,
23987                        DRegister rd,
23988                        DRegister rm) {
23989   VIXL_ASSERT(AllowAssembler());
23990   CheckIT(cond);
23991   Dt_size_1 encoded_dt(dt);
23992   if (IsUsingT32()) {
23993     // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23994     if (encoded_dt.IsValid()) {
23995       if (cond.Is(al) || AllowStronglyDiscouraged()) {
23996         EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
23997                    rd.Encode(22, 12) | rm.Encode(5, 0));
23998         AdvanceIT();
23999         return;
24000       }
24001     }
24002   } else {
24003     // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24004     if (encoded_dt.IsValid()) {
24005       if (cond.Is(al)) {
24006         EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
24007                 rd.Encode(22, 12) | rm.Encode(5, 0));
24008         return;
24009       }
24010     }
24011   }
24012   Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
24013 }
24014 
vrev16(Condition cond,DataType dt,QRegister rd,QRegister rm)24015 void Assembler::vrev16(Condition cond,
24016                        DataType dt,
24017                        QRegister rd,
24018                        QRegister rm) {
24019   VIXL_ASSERT(AllowAssembler());
24020   CheckIT(cond);
24021   Dt_size_1 encoded_dt(dt);
24022   if (IsUsingT32()) {
24023     // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24024     if (encoded_dt.IsValid()) {
24025       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24026         EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
24027                    rd.Encode(22, 12) | rm.Encode(5, 0));
24028         AdvanceIT();
24029         return;
24030       }
24031     }
24032   } else {
24033     // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24034     if (encoded_dt.IsValid()) {
24035       if (cond.Is(al)) {
24036         EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
24037                 rd.Encode(22, 12) | rm.Encode(5, 0));
24038         return;
24039       }
24040     }
24041   }
24042   Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
24043 }
24044 
vrev32(Condition cond,DataType dt,DRegister rd,DRegister rm)24045 void Assembler::vrev32(Condition cond,
24046                        DataType dt,
24047                        DRegister rd,
24048                        DRegister rm) {
24049   VIXL_ASSERT(AllowAssembler());
24050   CheckIT(cond);
24051   Dt_size_15 encoded_dt(dt);
24052   if (IsUsingT32()) {
24053     // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24054     if (encoded_dt.IsValid()) {
24055       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24056         EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
24057                    rd.Encode(22, 12) | rm.Encode(5, 0));
24058         AdvanceIT();
24059         return;
24060       }
24061     }
24062   } else {
24063     // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24064     if (encoded_dt.IsValid()) {
24065       if (cond.Is(al)) {
24066         EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
24067                 rd.Encode(22, 12) | rm.Encode(5, 0));
24068         return;
24069       }
24070     }
24071   }
24072   Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24073 }
24074 
vrev32(Condition cond,DataType dt,QRegister rd,QRegister rm)24075 void Assembler::vrev32(Condition cond,
24076                        DataType dt,
24077                        QRegister rd,
24078                        QRegister rm) {
24079   VIXL_ASSERT(AllowAssembler());
24080   CheckIT(cond);
24081   Dt_size_15 encoded_dt(dt);
24082   if (IsUsingT32()) {
24083     // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24084     if (encoded_dt.IsValid()) {
24085       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24086         EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
24087                    rd.Encode(22, 12) | rm.Encode(5, 0));
24088         AdvanceIT();
24089         return;
24090       }
24091     }
24092   } else {
24093     // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24094     if (encoded_dt.IsValid()) {
24095       if (cond.Is(al)) {
24096         EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
24097                 rd.Encode(22, 12) | rm.Encode(5, 0));
24098         return;
24099       }
24100     }
24101   }
24102   Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24103 }
24104 
vrev64(Condition cond,DataType dt,DRegister rd,DRegister rm)24105 void Assembler::vrev64(Condition cond,
24106                        DataType dt,
24107                        DRegister rd,
24108                        DRegister rm) {
24109   VIXL_ASSERT(AllowAssembler());
24110   CheckIT(cond);
24111   Dt_size_7 encoded_dt(dt);
24112   if (IsUsingT32()) {
24113     // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24114     if (encoded_dt.IsValid()) {
24115       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24116         EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
24117                    rd.Encode(22, 12) | rm.Encode(5, 0));
24118         AdvanceIT();
24119         return;
24120       }
24121     }
24122   } else {
24123     // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24124     if (encoded_dt.IsValid()) {
24125       if (cond.Is(al)) {
24126         EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
24127                 rd.Encode(22, 12) | rm.Encode(5, 0));
24128         return;
24129       }
24130     }
24131   }
24132   Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24133 }
24134 
vrev64(Condition cond,DataType dt,QRegister rd,QRegister rm)24135 void Assembler::vrev64(Condition cond,
24136                        DataType dt,
24137                        QRegister rd,
24138                        QRegister rm) {
24139   VIXL_ASSERT(AllowAssembler());
24140   CheckIT(cond);
24141   Dt_size_7 encoded_dt(dt);
24142   if (IsUsingT32()) {
24143     // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24144     if (encoded_dt.IsValid()) {
24145       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24146         EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
24147                    rd.Encode(22, 12) | rm.Encode(5, 0));
24148         AdvanceIT();
24149         return;
24150       }
24151     }
24152   } else {
24153     // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24154     if (encoded_dt.IsValid()) {
24155       if (cond.Is(al)) {
24156         EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
24157                 rd.Encode(22, 12) | rm.Encode(5, 0));
24158         return;
24159       }
24160     }
24161   }
24162   Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24163 }
24164 
vrhadd(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)24165 void Assembler::vrhadd(
24166     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
24167   VIXL_ASSERT(AllowAssembler());
24168   CheckIT(cond);
24169   Dt_U_size_1 encoded_dt(dt);
24170   if (IsUsingT32()) {
24171     // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
24172     if (encoded_dt.IsValid()) {
24173       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24174         EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24175                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24176                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24177         AdvanceIT();
24178         return;
24179       }
24180     }
24181   } else {
24182     // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
24183     if (encoded_dt.IsValid()) {
24184       if (cond.Is(al)) {
24185         EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24186                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24187                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24188         return;
24189       }
24190     }
24191   }
24192   Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24193 }
24194 
vrhadd(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)24195 void Assembler::vrhadd(
24196     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
24197   VIXL_ASSERT(AllowAssembler());
24198   CheckIT(cond);
24199   Dt_U_size_1 encoded_dt(dt);
24200   if (IsUsingT32()) {
24201     // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
24202     if (encoded_dt.IsValid()) {
24203       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24204         EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24205                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24206                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24207         AdvanceIT();
24208         return;
24209       }
24210     }
24211   } else {
24212     // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
24213     if (encoded_dt.IsValid()) {
24214       if (cond.Is(al)) {
24215         EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24216                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24217                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24218         return;
24219       }
24220     }
24221   }
24222   Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24223 }
24224 
vrinta(DataType dt,DRegister rd,DRegister rm)24225 void Assembler::vrinta(DataType dt, DRegister rd, DRegister rm) {
24226   VIXL_ASSERT(AllowAssembler());
24227   CheckIT(al);
24228   Dt_size_16 encoded_dt(dt);
24229   if (IsUsingT32()) {
24230     // VRINTA{<q>}.<dt> <Dd>, <Dm> ; T1
24231     if (encoded_dt.IsValid()) {
24232       EmitT32_32(0xffb20500U | (encoded_dt.GetEncodingValue() << 18) |
24233                  rd.Encode(22, 12) | rm.Encode(5, 0));
24234       AdvanceIT();
24235       return;
24236     }
24237     // VRINTA{<q>}.F64 <Dd>, <Dm> ; T1
24238     if (dt.Is(F64)) {
24239       EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24240       AdvanceIT();
24241       return;
24242     }
24243   } else {
24244     // VRINTA{<q>}.<dt> <Dd>, <Dm> ; A1
24245     if (encoded_dt.IsValid()) {
24246       EmitA32(0xf3b20500U | (encoded_dt.GetEncodingValue() << 18) |
24247               rd.Encode(22, 12) | rm.Encode(5, 0));
24248       return;
24249     }
24250     // VRINTA{<q>}.F64 <Dd>, <Dm> ; A1
24251     if (dt.Is(F64)) {
24252       EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24253       return;
24254     }
24255   }
24256   Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
24257 }
24258 
vrinta(DataType dt,QRegister rd,QRegister rm)24259 void Assembler::vrinta(DataType dt, QRegister rd, QRegister rm) {
24260   VIXL_ASSERT(AllowAssembler());
24261   CheckIT(al);
24262   Dt_size_16 encoded_dt(dt);
24263   if (IsUsingT32()) {
24264     // VRINTA{<q>}.<dt> <Qd>, <Qm> ; T1
24265     if (encoded_dt.IsValid()) {
24266       EmitT32_32(0xffb20540U | (encoded_dt.GetEncodingValue() << 18) |
24267                  rd.Encode(22, 12) | rm.Encode(5, 0));
24268       AdvanceIT();
24269       return;
24270     }
24271   } else {
24272     // VRINTA{<q>}.<dt> <Qd>, <Qm> ; A1
24273     if (encoded_dt.IsValid()) {
24274       EmitA32(0xf3b20540U | (encoded_dt.GetEncodingValue() << 18) |
24275               rd.Encode(22, 12) | rm.Encode(5, 0));
24276       return;
24277     }
24278   }
24279   Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
24280 }
24281 
vrinta(DataType dt,SRegister rd,SRegister rm)24282 void Assembler::vrinta(DataType dt, SRegister rd, SRegister rm) {
24283   VIXL_ASSERT(AllowAssembler());
24284   CheckIT(al);
24285   if (IsUsingT32()) {
24286     // VRINTA{<q>}.F32 <Sd>, <Sm> ; T1
24287     if (dt.Is(F32)) {
24288       EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24289       AdvanceIT();
24290       return;
24291     }
24292   } else {
24293     // VRINTA{<q>}.F32 <Sd>, <Sm> ; A1
24294     if (dt.Is(F32)) {
24295       EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24296       return;
24297     }
24298   }
24299   Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
24300 }
24301 
vrintm(DataType dt,DRegister rd,DRegister rm)24302 void Assembler::vrintm(DataType dt, DRegister rd, DRegister rm) {
24303   VIXL_ASSERT(AllowAssembler());
24304   CheckIT(al);
24305   Dt_size_16 encoded_dt(dt);
24306   if (IsUsingT32()) {
24307     // VRINTM{<q>}.<dt> <Dd>, <Dm> ; T1
24308     if (encoded_dt.IsValid()) {
24309       EmitT32_32(0xffb20680U | (encoded_dt.GetEncodingValue() << 18) |
24310                  rd.Encode(22, 12) | rm.Encode(5, 0));
24311       AdvanceIT();
24312       return;
24313     }
24314     // VRINTM{<q>}.F64 <Dd>, <Dm> ; T1
24315     if (dt.Is(F64)) {
24316       EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24317       AdvanceIT();
24318       return;
24319     }
24320   } else {
24321     // VRINTM{<q>}.<dt> <Dd>, <Dm> ; A1
24322     if (encoded_dt.IsValid()) {
24323       EmitA32(0xf3b20680U | (encoded_dt.GetEncodingValue() << 18) |
24324               rd.Encode(22, 12) | rm.Encode(5, 0));
24325       return;
24326     }
24327     // VRINTM{<q>}.F64 <Dd>, <Dm> ; A1
24328     if (dt.Is(F64)) {
24329       EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24330       return;
24331     }
24332   }
24333   Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
24334 }
24335 
vrintm(DataType dt,QRegister rd,QRegister rm)24336 void Assembler::vrintm(DataType dt, QRegister rd, QRegister rm) {
24337   VIXL_ASSERT(AllowAssembler());
24338   CheckIT(al);
24339   Dt_size_16 encoded_dt(dt);
24340   if (IsUsingT32()) {
24341     // VRINTM{<q>}.<dt> <Qd>, <Qm> ; T1
24342     if (encoded_dt.IsValid()) {
24343       EmitT32_32(0xffb206c0U | (encoded_dt.GetEncodingValue() << 18) |
24344                  rd.Encode(22, 12) | rm.Encode(5, 0));
24345       AdvanceIT();
24346       return;
24347     }
24348   } else {
24349     // VRINTM{<q>}.<dt> <Qd>, <Qm> ; A1
24350     if (encoded_dt.IsValid()) {
24351       EmitA32(0xf3b206c0U | (encoded_dt.GetEncodingValue() << 18) |
24352               rd.Encode(22, 12) | rm.Encode(5, 0));
24353       return;
24354     }
24355   }
24356   Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
24357 }
24358 
vrintm(DataType dt,SRegister rd,SRegister rm)24359 void Assembler::vrintm(DataType dt, SRegister rd, SRegister rm) {
24360   VIXL_ASSERT(AllowAssembler());
24361   CheckIT(al);
24362   if (IsUsingT32()) {
24363     // VRINTM{<q>}.F32 <Sd>, <Sm> ; T1
24364     if (dt.Is(F32)) {
24365       EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24366       AdvanceIT();
24367       return;
24368     }
24369   } else {
24370     // VRINTM{<q>}.F32 <Sd>, <Sm> ; A1
24371     if (dt.Is(F32)) {
24372       EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24373       return;
24374     }
24375   }
24376   Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
24377 }
24378 
vrintn(DataType dt,DRegister rd,DRegister rm)24379 void Assembler::vrintn(DataType dt, DRegister rd, DRegister rm) {
24380   VIXL_ASSERT(AllowAssembler());
24381   CheckIT(al);
24382   Dt_size_16 encoded_dt(dt);
24383   if (IsUsingT32()) {
24384     // VRINTN{<q>}.<dt> <Dd>, <Dm> ; T1
24385     if (encoded_dt.IsValid()) {
24386       EmitT32_32(0xffb20400U | (encoded_dt.GetEncodingValue() << 18) |
24387                  rd.Encode(22, 12) | rm.Encode(5, 0));
24388       AdvanceIT();
24389       return;
24390     }
24391     // VRINTN{<q>}.F64 <Dd>, <Dm> ; T1
24392     if (dt.Is(F64)) {
24393       EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24394       AdvanceIT();
24395       return;
24396     }
24397   } else {
24398     // VRINTN{<q>}.<dt> <Dd>, <Dm> ; A1
24399     if (encoded_dt.IsValid()) {
24400       EmitA32(0xf3b20400U | (encoded_dt.GetEncodingValue() << 18) |
24401               rd.Encode(22, 12) | rm.Encode(5, 0));
24402       return;
24403     }
24404     // VRINTN{<q>}.F64 <Dd>, <Dm> ; A1
24405     if (dt.Is(F64)) {
24406       EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24407       return;
24408     }
24409   }
24410   Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
24411 }
24412 
vrintn(DataType dt,QRegister rd,QRegister rm)24413 void Assembler::vrintn(DataType dt, QRegister rd, QRegister rm) {
24414   VIXL_ASSERT(AllowAssembler());
24415   CheckIT(al);
24416   Dt_size_16 encoded_dt(dt);
24417   if (IsUsingT32()) {
24418     // VRINTN{<q>}.<dt> <Qd>, <Qm> ; T1
24419     if (encoded_dt.IsValid()) {
24420       EmitT32_32(0xffb20440U | (encoded_dt.GetEncodingValue() << 18) |
24421                  rd.Encode(22, 12) | rm.Encode(5, 0));
24422       AdvanceIT();
24423       return;
24424     }
24425   } else {
24426     // VRINTN{<q>}.<dt> <Qd>, <Qm> ; A1
24427     if (encoded_dt.IsValid()) {
24428       EmitA32(0xf3b20440U | (encoded_dt.GetEncodingValue() << 18) |
24429               rd.Encode(22, 12) | rm.Encode(5, 0));
24430       return;
24431     }
24432   }
24433   Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
24434 }
24435 
vrintn(DataType dt,SRegister rd,SRegister rm)24436 void Assembler::vrintn(DataType dt, SRegister rd, SRegister rm) {
24437   VIXL_ASSERT(AllowAssembler());
24438   CheckIT(al);
24439   if (IsUsingT32()) {
24440     // VRINTN{<q>}.F32 <Sd>, <Sm> ; T1
24441     if (dt.Is(F32)) {
24442       EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24443       AdvanceIT();
24444       return;
24445     }
24446   } else {
24447     // VRINTN{<q>}.F32 <Sd>, <Sm> ; A1
24448     if (dt.Is(F32)) {
24449       EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24450       return;
24451     }
24452   }
24453   Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
24454 }
24455 
vrintp(DataType dt,DRegister rd,DRegister rm)24456 void Assembler::vrintp(DataType dt, DRegister rd, DRegister rm) {
24457   VIXL_ASSERT(AllowAssembler());
24458   CheckIT(al);
24459   Dt_size_16 encoded_dt(dt);
24460   if (IsUsingT32()) {
24461     // VRINTP{<q>}.<dt> <Dd>, <Dm> ; T1
24462     if (encoded_dt.IsValid()) {
24463       EmitT32_32(0xffb20780U | (encoded_dt.GetEncodingValue() << 18) |
24464                  rd.Encode(22, 12) | rm.Encode(5, 0));
24465       AdvanceIT();
24466       return;
24467     }
24468     // VRINTP{<q>}.F64 <Dd>, <Dm> ; T1
24469     if (dt.Is(F64)) {
24470       EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24471       AdvanceIT();
24472       return;
24473     }
24474   } else {
24475     // VRINTP{<q>}.<dt> <Dd>, <Dm> ; A1
24476     if (encoded_dt.IsValid()) {
24477       EmitA32(0xf3b20780U | (encoded_dt.GetEncodingValue() << 18) |
24478               rd.Encode(22, 12) | rm.Encode(5, 0));
24479       return;
24480     }
24481     // VRINTP{<q>}.F64 <Dd>, <Dm> ; A1
24482     if (dt.Is(F64)) {
24483       EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24484       return;
24485     }
24486   }
24487   Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
24488 }
24489 
vrintp(DataType dt,QRegister rd,QRegister rm)24490 void Assembler::vrintp(DataType dt, QRegister rd, QRegister rm) {
24491   VIXL_ASSERT(AllowAssembler());
24492   CheckIT(al);
24493   Dt_size_16 encoded_dt(dt);
24494   if (IsUsingT32()) {
24495     // VRINTP{<q>}.<dt> <Qd>, <Qm> ; T1
24496     if (encoded_dt.IsValid()) {
24497       EmitT32_32(0xffb207c0U | (encoded_dt.GetEncodingValue() << 18) |
24498                  rd.Encode(22, 12) | rm.Encode(5, 0));
24499       AdvanceIT();
24500       return;
24501     }
24502   } else {
24503     // VRINTP{<q>}.<dt> <Qd>, <Qm> ; A1
24504     if (encoded_dt.IsValid()) {
24505       EmitA32(0xf3b207c0U | (encoded_dt.GetEncodingValue() << 18) |
24506               rd.Encode(22, 12) | rm.Encode(5, 0));
24507       return;
24508     }
24509   }
24510   Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
24511 }
24512 
vrintp(DataType dt,SRegister rd,SRegister rm)24513 void Assembler::vrintp(DataType dt, SRegister rd, SRegister rm) {
24514   VIXL_ASSERT(AllowAssembler());
24515   CheckIT(al);
24516   if (IsUsingT32()) {
24517     // VRINTP{<q>}.F32 <Sd>, <Sm> ; T1
24518     if (dt.Is(F32)) {
24519       EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24520       AdvanceIT();
24521       return;
24522     }
24523   } else {
24524     // VRINTP{<q>}.F32 <Sd>, <Sm> ; A1
24525     if (dt.Is(F32)) {
24526       EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24527       return;
24528     }
24529   }
24530   Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
24531 }
24532 
vrintr(Condition cond,DataType dt,SRegister rd,SRegister rm)24533 void Assembler::vrintr(Condition cond,
24534                        DataType dt,
24535                        SRegister rd,
24536                        SRegister rm) {
24537   VIXL_ASSERT(AllowAssembler());
24538   CheckIT(cond);
24539   if (IsUsingT32()) {
24540     // VRINTR{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24541     if (dt.Is(F32)) {
24542       EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24543       AdvanceIT();
24544       return;
24545     }
24546   } else {
24547     // VRINTR{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24548     if (dt.Is(F32) && cond.IsNotNever()) {
24549       EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24550               rm.Encode(5, 0));
24551       return;
24552     }
24553   }
24554   Delegate(kVrintr, &Assembler::vrintr, cond, dt, rd, rm);
24555 }
24556 
vrintr(Condition cond,DataType dt,DRegister rd,DRegister rm)24557 void Assembler::vrintr(Condition cond,
24558                        DataType dt,
24559                        DRegister rd,
24560                        DRegister rm) {
24561   VIXL_ASSERT(AllowAssembler());
24562   CheckIT(cond);
24563   if (IsUsingT32()) {
24564     // VRINTR{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24565     if (dt.Is(F64)) {
24566       EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24567       AdvanceIT();
24568       return;
24569     }
24570   } else {
24571     // VRINTR{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24572     if (dt.Is(F64) && cond.IsNotNever()) {
24573       EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24574               rm.Encode(5, 0));
24575       return;
24576     }
24577   }
24578   Delegate(kVrintr, &Assembler::vrintr, cond, dt, rd, rm);
24579 }
24580 
vrintx(Condition cond,DataType dt,DRegister rd,DRegister rm)24581 void Assembler::vrintx(Condition cond,
24582                        DataType dt,
24583                        DRegister rd,
24584                        DRegister rm) {
24585   VIXL_ASSERT(AllowAssembler());
24586   CheckIT(cond);
24587   Dt_size_16 encoded_dt(dt);
24588   if (IsUsingT32()) {
24589     // VRINTX{<q>}.<dt> <Dd>, <Dm> ; T1
24590     if (encoded_dt.IsValid()) {
24591       EmitT32_32(0xffb20480U | (encoded_dt.GetEncodingValue() << 18) |
24592                  rd.Encode(22, 12) | rm.Encode(5, 0));
24593       AdvanceIT();
24594       return;
24595     }
24596     // VRINTX{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24597     if (dt.Is(F64)) {
24598       EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24599       AdvanceIT();
24600       return;
24601     }
24602   } else {
24603     // VRINTX{<q>}.<dt> <Dd>, <Dm> ; A1
24604     if (encoded_dt.IsValid()) {
24605       EmitA32(0xf3b20480U | (encoded_dt.GetEncodingValue() << 18) |
24606               rd.Encode(22, 12) | rm.Encode(5, 0));
24607       return;
24608     }
24609     // VRINTX{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24610     if (dt.Is(F64) && cond.IsNotNever()) {
24611       EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24612               rm.Encode(5, 0));
24613       return;
24614     }
24615   }
24616   Delegate(kVrintx, &Assembler::vrintx, cond, dt, rd, rm);
24617 }
24618 
vrintx(DataType dt,QRegister rd,QRegister rm)24619 void Assembler::vrintx(DataType dt, QRegister rd, QRegister rm) {
24620   VIXL_ASSERT(AllowAssembler());
24621   CheckIT(al);
24622   Dt_size_16 encoded_dt(dt);
24623   if (IsUsingT32()) {
24624     // VRINTX{<q>}.<dt> <Qd>, <Qm> ; T1
24625     if (encoded_dt.IsValid()) {
24626       EmitT32_32(0xffb204c0U | (encoded_dt.GetEncodingValue() << 18) |
24627                  rd.Encode(22, 12) | rm.Encode(5, 0));
24628       AdvanceIT();
24629       return;
24630     }
24631   } else {
24632     // VRINTX{<q>}.<dt> <Qd>, <Qm> ; A1
24633     if (encoded_dt.IsValid()) {
24634       EmitA32(0xf3b204c0U | (encoded_dt.GetEncodingValue() << 18) |
24635               rd.Encode(22, 12) | rm.Encode(5, 0));
24636       return;
24637     }
24638   }
24639   Delegate(kVrintx, &Assembler::vrintx, dt, rd, rm);
24640 }
24641 
vrintx(Condition cond,DataType dt,SRegister rd,SRegister rm)24642 void Assembler::vrintx(Condition cond,
24643                        DataType dt,
24644                        SRegister rd,
24645                        SRegister rm) {
24646   VIXL_ASSERT(AllowAssembler());
24647   CheckIT(cond);
24648   if (IsUsingT32()) {
24649     // VRINTX{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24650     if (dt.Is(F32)) {
24651       EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24652       AdvanceIT();
24653       return;
24654     }
24655   } else {
24656     // VRINTX{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24657     if (dt.Is(F32) && cond.IsNotNever()) {
24658       EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24659               rm.Encode(5, 0));
24660       return;
24661     }
24662   }
24663   Delegate(kVrintx, &Assembler::vrintx, cond, dt, rd, rm);
24664 }
24665 
vrintz(Condition cond,DataType dt,DRegister rd,DRegister rm)24666 void Assembler::vrintz(Condition cond,
24667                        DataType dt,
24668                        DRegister rd,
24669                        DRegister rm) {
24670   VIXL_ASSERT(AllowAssembler());
24671   CheckIT(cond);
24672   Dt_size_16 encoded_dt(dt);
24673   if (IsUsingT32()) {
24674     // VRINTZ{<q>}.<dt> <Dd>, <Dm> ; T1
24675     if (encoded_dt.IsValid()) {
24676       EmitT32_32(0xffb20580U | (encoded_dt.GetEncodingValue() << 18) |
24677                  rd.Encode(22, 12) | rm.Encode(5, 0));
24678       AdvanceIT();
24679       return;
24680     }
24681     // VRINTZ{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24682     if (dt.Is(F64)) {
24683       EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24684       AdvanceIT();
24685       return;
24686     }
24687   } else {
24688     // VRINTZ{<q>}.<dt> <Dd>, <Dm> ; A1
24689     if (encoded_dt.IsValid()) {
24690       EmitA32(0xf3b20580U | (encoded_dt.GetEncodingValue() << 18) |
24691               rd.Encode(22, 12) | rm.Encode(5, 0));
24692       return;
24693     }
24694     // VRINTZ{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24695     if (dt.Is(F64) && cond.IsNotNever()) {
24696       EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24697               rm.Encode(5, 0));
24698       return;
24699     }
24700   }
24701   Delegate(kVrintz, &Assembler::vrintz, cond, dt, rd, rm);
24702 }
24703 
vrintz(DataType dt,QRegister rd,QRegister rm)24704 void Assembler::vrintz(DataType dt, QRegister rd, QRegister rm) {
24705   VIXL_ASSERT(AllowAssembler());
24706   CheckIT(al);
24707   Dt_size_16 encoded_dt(dt);
24708   if (IsUsingT32()) {
24709     // VRINTZ{<q>}.<dt> <Qd>, <Qm> ; T1
24710     if (encoded_dt.IsValid()) {
24711       EmitT32_32(0xffb205c0U | (encoded_dt.GetEncodingValue() << 18) |
24712                  rd.Encode(22, 12) | rm.Encode(5, 0));
24713       AdvanceIT();
24714       return;
24715     }
24716   } else {
24717     // VRINTZ{<q>}.<dt> <Qd>, <Qm> ; A1
24718     if (encoded_dt.IsValid()) {
24719       EmitA32(0xf3b205c0U | (encoded_dt.GetEncodingValue() << 18) |
24720               rd.Encode(22, 12) | rm.Encode(5, 0));
24721       return;
24722     }
24723   }
24724   Delegate(kVrintz, &Assembler::vrintz, dt, rd, rm);
24725 }
24726 
vrintz(Condition cond,DataType dt,SRegister rd,SRegister rm)24727 void Assembler::vrintz(Condition cond,
24728                        DataType dt,
24729                        SRegister rd,
24730                        SRegister rm) {
24731   VIXL_ASSERT(AllowAssembler());
24732   CheckIT(cond);
24733   if (IsUsingT32()) {
24734     // VRINTZ{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24735     if (dt.Is(F32)) {
24736       EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24737       AdvanceIT();
24738       return;
24739     }
24740   } else {
24741     // VRINTZ{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24742     if (dt.Is(F32) && cond.IsNotNever()) {
24743       EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24744               rm.Encode(5, 0));
24745       return;
24746     }
24747   }
24748   Delegate(kVrintz, &Assembler::vrintz, cond, dt, rd, rm);
24749 }
24750 
vrshl(Condition cond,DataType dt,DRegister rd,DRegister rm,DRegister rn)24751 void Assembler::vrshl(
24752     Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
24753   VIXL_ASSERT(AllowAssembler());
24754   CheckIT(cond);
24755   Dt_U_size_3 encoded_dt(dt);
24756   if (IsUsingT32()) {
24757     // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24758     if (encoded_dt.IsValid()) {
24759       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24760         EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24761                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24762                    rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24763         AdvanceIT();
24764         return;
24765       }
24766     }
24767   } else {
24768     // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24769     if (encoded_dt.IsValid()) {
24770       if (cond.Is(al)) {
24771         EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24772                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24773                 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24774         return;
24775       }
24776     }
24777   }
24778   Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24779 }
24780 
vrshl(Condition cond,DataType dt,QRegister rd,QRegister rm,QRegister rn)24781 void Assembler::vrshl(
24782     Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
24783   VIXL_ASSERT(AllowAssembler());
24784   CheckIT(cond);
24785   Dt_U_size_3 encoded_dt(dt);
24786   if (IsUsingT32()) {
24787     // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24788     if (encoded_dt.IsValid()) {
24789       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24790         EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24791                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24792                    rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24793         AdvanceIT();
24794         return;
24795       }
24796     }
24797   } else {
24798     // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24799     if (encoded_dt.IsValid()) {
24800       if (cond.Is(al)) {
24801         EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24802                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24803                 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24804         return;
24805       }
24806     }
24807   }
24808   Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24809 }
24810 
vrshr(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)24811 void Assembler::vrshr(Condition cond,
24812                       DataType dt,
24813                       DRegister rd,
24814                       DRegister rm,
24815                       const DOperand& operand) {
24816   VIXL_ASSERT(AllowAssembler());
24817   CheckIT(cond);
24818   if (operand.IsImmediate()) {
24819     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24820       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24821       Dt_L_imm6_1 encoded_dt(dt);
24822       if (IsUsingT32()) {
24823         // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24824         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24825           if (cond.Is(al) || AllowStronglyDiscouraged()) {
24826             uint32_t imm6 = dt.GetSize() - imm;
24827             EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
24828                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24829                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24830                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24831             AdvanceIT();
24832             return;
24833           }
24834         }
24835         // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24836         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24837           if (cond.Is(al) || AllowStronglyDiscouraged()) {
24838             EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24839                        rm.Encode(5, 0));
24840             AdvanceIT();
24841             return;
24842           }
24843         }
24844       } else {
24845         // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24846         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24847           if (cond.Is(al)) {
24848             uint32_t imm6 = dt.GetSize() - imm;
24849             EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
24850                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24851                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24852                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24853             return;
24854           }
24855         }
24856         // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24857         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24858           if (cond.Is(al)) {
24859             EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24860                     rm.Encode(5, 0));
24861             return;
24862           }
24863         }
24864       }
24865     }
24866   }
24867   Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24868 }
24869 
vrshr(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)24870 void Assembler::vrshr(Condition cond,
24871                       DataType dt,
24872                       QRegister rd,
24873                       QRegister rm,
24874                       const QOperand& operand) {
24875   VIXL_ASSERT(AllowAssembler());
24876   CheckIT(cond);
24877   if (operand.IsImmediate()) {
24878     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24879       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24880       Dt_L_imm6_1 encoded_dt(dt);
24881       if (IsUsingT32()) {
24882         // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24883         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24884           if (cond.Is(al) || AllowStronglyDiscouraged()) {
24885             uint32_t imm6 = dt.GetSize() - imm;
24886             EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
24887                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24888                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24889                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24890             AdvanceIT();
24891             return;
24892           }
24893         }
24894         // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24895         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24896           if (cond.Is(al) || AllowStronglyDiscouraged()) {
24897             EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24898                        rm.Encode(5, 0));
24899             AdvanceIT();
24900             return;
24901           }
24902         }
24903       } else {
24904         // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24905         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24906           if (cond.Is(al)) {
24907             uint32_t imm6 = dt.GetSize() - imm;
24908             EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
24909                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24910                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24911                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24912             return;
24913           }
24914         }
24915         // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24916         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24917           if (cond.Is(al)) {
24918             EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24919                     rm.Encode(5, 0));
24920             return;
24921           }
24922         }
24923       }
24924     }
24925   }
24926   Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24927 }
24928 
vrshrn(Condition cond,DataType dt,DRegister rd,QRegister rm,const QOperand & operand)24929 void Assembler::vrshrn(Condition cond,
24930                        DataType dt,
24931                        DRegister rd,
24932                        QRegister rm,
24933                        const QOperand& operand) {
24934   VIXL_ASSERT(AllowAssembler());
24935   CheckIT(cond);
24936   if (operand.IsImmediate()) {
24937     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24938       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24939       Dt_imm6_3 encoded_dt(dt);
24940       Dt_size_3 encoded_dt_2(dt);
24941       if (IsUsingT32()) {
24942         // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24943         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24944           if (cond.Is(al) || AllowStronglyDiscouraged()) {
24945             uint32_t imm6 = dt.GetSize() / 2 - imm;
24946             EmitT32_32(0xef800850U |
24947                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24948                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24949             AdvanceIT();
24950             return;
24951           }
24952         }
24953         // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24954         if (encoded_dt_2.IsValid() && (imm == 0)) {
24955           if (cond.Is(al) || AllowStronglyDiscouraged()) {
24956             EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24957                        rd.Encode(22, 12) | rm.Encode(5, 0));
24958             AdvanceIT();
24959             return;
24960           }
24961         }
24962       } else {
24963         // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24964         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24965           if (cond.Is(al)) {
24966             uint32_t imm6 = dt.GetSize() / 2 - imm;
24967             EmitA32(0xf2800850U |
24968                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24969                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24970             return;
24971           }
24972         }
24973         // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24974         if (encoded_dt_2.IsValid() && (imm == 0)) {
24975           if (cond.Is(al)) {
24976             EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24977                     rd.Encode(22, 12) | rm.Encode(5, 0));
24978             return;
24979           }
24980         }
24981       }
24982     }
24983   }
24984   Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
24985 }
24986 
vrsqrte(Condition cond,DataType dt,DRegister rd,DRegister rm)24987 void Assembler::vrsqrte(Condition cond,
24988                         DataType dt,
24989                         DRegister rd,
24990                         DRegister rm) {
24991   VIXL_ASSERT(AllowAssembler());
24992   CheckIT(cond);
24993   Dt_F_size_4 encoded_dt(dt);
24994   if (IsUsingT32()) {
24995     // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24996     if (encoded_dt.IsValid()) {
24997       if (cond.Is(al) || AllowStronglyDiscouraged()) {
24998         EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24999                    ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25000                    rd.Encode(22, 12) | rm.Encode(5, 0));
25001         AdvanceIT();
25002         return;
25003       }
25004     }
25005   } else {
25006     // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
25007     if (encoded_dt.IsValid()) {
25008       if (cond.Is(al)) {
25009         EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
25010                 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25011                 rd.Encode(22, 12) | rm.Encode(5, 0));
25012         return;
25013       }
25014     }
25015   }
25016   Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
25017 }
25018 
vrsqrte(Condition cond,DataType dt,QRegister rd,QRegister rm)25019 void Assembler::vrsqrte(Condition cond,
25020                         DataType dt,
25021                         QRegister rd,
25022                         QRegister rm) {
25023   VIXL_ASSERT(AllowAssembler());
25024   CheckIT(cond);
25025   Dt_F_size_4 encoded_dt(dt);
25026   if (IsUsingT32()) {
25027     // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
25028     if (encoded_dt.IsValid()) {
25029       if (cond.Is(al) || AllowStronglyDiscouraged()) {
25030         EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
25031                    ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25032                    rd.Encode(22, 12) | rm.Encode(5, 0));
25033         AdvanceIT();
25034         return;
25035       }
25036     }
25037   } else {
25038     // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
25039     if (encoded_dt.IsValid()) {
25040       if (cond.Is(al)) {
25041         EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
25042                 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25043                 rd.Encode(22, 12) | rm.Encode(5, 0));
25044         return;
25045       }
25046     }
25047   }
25048   Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
25049 }
25050 
vrsqrts(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)25051 void Assembler::vrsqrts(
25052     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25053   VIXL_ASSERT(AllowAssembler());
25054   CheckIT(cond);
25055   if (IsUsingT32()) {
25056     // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
25057     if (dt.Is(F32)) {
25058       if (cond.Is(al) || AllowStronglyDiscouraged()) {
25059         EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25060                    rm.Encode(5, 0));
25061         AdvanceIT();
25062         return;
25063       }
25064     }
25065   } else {
25066     // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
25067     if (dt.Is(F32)) {
25068       if (cond.Is(al)) {
25069         EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25070                 rm.Encode(5, 0));
25071         return;
25072       }
25073     }
25074   }
25075   Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
25076 }
25077 
vrsqrts(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)25078 void Assembler::vrsqrts(
25079     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
25080   VIXL_ASSERT(AllowAssembler());
25081   CheckIT(cond);
25082   if (IsUsingT32()) {
25083     // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
25084     if (dt.Is(F32)) {
25085       if (cond.Is(al) || AllowStronglyDiscouraged()) {
25086         EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25087                    rm.Encode(5, 0));
25088         AdvanceIT();
25089         return;
25090       }
25091     }
25092   } else {
25093     // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
25094     if (dt.Is(F32)) {
25095       if (cond.Is(al)) {
25096         EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25097                 rm.Encode(5, 0));
25098         return;
25099       }
25100     }
25101   }
25102   Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
25103 }
25104 
vrsra(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)25105 void Assembler::vrsra(Condition cond,
25106                       DataType dt,
25107                       DRegister rd,
25108                       DRegister rm,
25109                       const DOperand& operand) {
25110   VIXL_ASSERT(AllowAssembler());
25111   CheckIT(cond);
25112   if (operand.IsImmediate()) {
25113     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25114       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25115       Dt_L_imm6_1 encoded_dt(dt);
25116       if (IsUsingT32()) {
25117         // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25118         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25119           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25120             uint32_t imm6 = dt.GetSize() - imm;
25121             EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
25122                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25123                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25124                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25125             AdvanceIT();
25126             return;
25127           }
25128         }
25129       } else {
25130         // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25131         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25132           if (cond.Is(al)) {
25133             uint32_t imm6 = dt.GetSize() - imm;
25134             EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
25135                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25136                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25137                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25138             return;
25139           }
25140         }
25141       }
25142     }
25143   }
25144   Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25145 }
25146 
vrsra(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)25147 void Assembler::vrsra(Condition cond,
25148                       DataType dt,
25149                       QRegister rd,
25150                       QRegister rm,
25151                       const QOperand& operand) {
25152   VIXL_ASSERT(AllowAssembler());
25153   CheckIT(cond);
25154   if (operand.IsImmediate()) {
25155     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25156       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25157       Dt_L_imm6_1 encoded_dt(dt);
25158       if (IsUsingT32()) {
25159         // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25160         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25161           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25162             uint32_t imm6 = dt.GetSize() - imm;
25163             EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
25164                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25165                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25166                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25167             AdvanceIT();
25168             return;
25169           }
25170         }
25171       } else {
25172         // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25173         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25174           if (cond.Is(al)) {
25175             uint32_t imm6 = dt.GetSize() - imm;
25176             EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
25177                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25178                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25179                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25180             return;
25181           }
25182         }
25183       }
25184     }
25185   }
25186   Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25187 }
25188 
vrsubhn(Condition cond,DataType dt,DRegister rd,QRegister rn,QRegister rm)25189 void Assembler::vrsubhn(
25190     Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
25191   VIXL_ASSERT(AllowAssembler());
25192   CheckIT(cond);
25193   Dt_size_3 encoded_dt(dt);
25194   if (IsUsingT32()) {
25195     // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
25196     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25197       if (cond.Is(al) || AllowStronglyDiscouraged()) {
25198         EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
25199                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25200         AdvanceIT();
25201         return;
25202       }
25203     }
25204   } else {
25205     // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
25206     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25207       if (cond.Is(al)) {
25208         EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
25209                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25210         return;
25211       }
25212     }
25213   }
25214   Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
25215 }
25216 
vseleq(DataType dt,DRegister rd,DRegister rn,DRegister rm)25217 void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25218   VIXL_ASSERT(AllowAssembler());
25219   CheckIT(al);
25220   if (IsUsingT32()) {
25221     // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
25222     if (OutsideITBlock() && dt.Is(F64)) {
25223       EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25224                  rm.Encode(5, 0));
25225       AdvanceIT();
25226       return;
25227     }
25228   } else {
25229     // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
25230     if (dt.Is(F64)) {
25231       EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25232               rm.Encode(5, 0));
25233       return;
25234     }
25235   }
25236   Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25237 }
25238 
vseleq(DataType dt,SRegister rd,SRegister rn,SRegister rm)25239 void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25240   VIXL_ASSERT(AllowAssembler());
25241   CheckIT(al);
25242   if (IsUsingT32()) {
25243     // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
25244     if (OutsideITBlock() && dt.Is(F32)) {
25245       EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25246                  rm.Encode(5, 0));
25247       AdvanceIT();
25248       return;
25249     }
25250   } else {
25251     // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
25252     if (dt.Is(F32)) {
25253       EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25254               rm.Encode(5, 0));
25255       return;
25256     }
25257   }
25258   Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25259 }
25260 
vselge(DataType dt,DRegister rd,DRegister rn,DRegister rm)25261 void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25262   VIXL_ASSERT(AllowAssembler());
25263   CheckIT(al);
25264   if (IsUsingT32()) {
25265     // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
25266     if (OutsideITBlock() && dt.Is(F64)) {
25267       EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25268                  rm.Encode(5, 0));
25269       AdvanceIT();
25270       return;
25271     }
25272   } else {
25273     // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
25274     if (dt.Is(F64)) {
25275       EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25276               rm.Encode(5, 0));
25277       return;
25278     }
25279   }
25280   Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25281 }
25282 
vselge(DataType dt,SRegister rd,SRegister rn,SRegister rm)25283 void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25284   VIXL_ASSERT(AllowAssembler());
25285   CheckIT(al);
25286   if (IsUsingT32()) {
25287     // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
25288     if (OutsideITBlock() && dt.Is(F32)) {
25289       EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25290                  rm.Encode(5, 0));
25291       AdvanceIT();
25292       return;
25293     }
25294   } else {
25295     // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
25296     if (dt.Is(F32)) {
25297       EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25298               rm.Encode(5, 0));
25299       return;
25300     }
25301   }
25302   Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25303 }
25304 
vselgt(DataType dt,DRegister rd,DRegister rn,DRegister rm)25305 void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25306   VIXL_ASSERT(AllowAssembler());
25307   CheckIT(al);
25308   if (IsUsingT32()) {
25309     // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
25310     if (OutsideITBlock() && dt.Is(F64)) {
25311       EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25312                  rm.Encode(5, 0));
25313       AdvanceIT();
25314       return;
25315     }
25316   } else {
25317     // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
25318     if (dt.Is(F64)) {
25319       EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25320               rm.Encode(5, 0));
25321       return;
25322     }
25323   }
25324   Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25325 }
25326 
vselgt(DataType dt,SRegister rd,SRegister rn,SRegister rm)25327 void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25328   VIXL_ASSERT(AllowAssembler());
25329   CheckIT(al);
25330   if (IsUsingT32()) {
25331     // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
25332     if (OutsideITBlock() && dt.Is(F32)) {
25333       EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25334                  rm.Encode(5, 0));
25335       AdvanceIT();
25336       return;
25337     }
25338   } else {
25339     // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
25340     if (dt.Is(F32)) {
25341       EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25342               rm.Encode(5, 0));
25343       return;
25344     }
25345   }
25346   Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25347 }
25348 
vselvs(DataType dt,DRegister rd,DRegister rn,DRegister rm)25349 void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25350   VIXL_ASSERT(AllowAssembler());
25351   CheckIT(al);
25352   if (IsUsingT32()) {
25353     // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
25354     if (OutsideITBlock() && dt.Is(F64)) {
25355       EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25356                  rm.Encode(5, 0));
25357       AdvanceIT();
25358       return;
25359     }
25360   } else {
25361     // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
25362     if (dt.Is(F64)) {
25363       EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25364               rm.Encode(5, 0));
25365       return;
25366     }
25367   }
25368   Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25369 }
25370 
vselvs(DataType dt,SRegister rd,SRegister rn,SRegister rm)25371 void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25372   VIXL_ASSERT(AllowAssembler());
25373   CheckIT(al);
25374   if (IsUsingT32()) {
25375     // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
25376     if (OutsideITBlock() && dt.Is(F32)) {
25377       EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25378                  rm.Encode(5, 0));
25379       AdvanceIT();
25380       return;
25381     }
25382   } else {
25383     // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
25384     if (dt.Is(F32)) {
25385       EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25386               rm.Encode(5, 0));
25387       return;
25388     }
25389   }
25390   Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25391 }
25392 
vshl(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)25393 void Assembler::vshl(Condition cond,
25394                      DataType dt,
25395                      DRegister rd,
25396                      DRegister rm,
25397                      const DOperand& operand) {
25398   VIXL_ASSERT(AllowAssembler());
25399   CheckIT(cond);
25400   if (operand.IsImmediate()) {
25401     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25402       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25403       Dt_L_imm6_3 encoded_dt(dt);
25404       if (IsUsingT32()) {
25405         // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
25406         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25407           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25408             uint32_t imm6 = imm;
25409             EmitT32_32(0xef800510U |
25410                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25411                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25412                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25413             AdvanceIT();
25414             return;
25415           }
25416         }
25417       } else {
25418         // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
25419         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25420           if (cond.Is(al)) {
25421             uint32_t imm6 = imm;
25422             EmitA32(0xf2800510U |
25423                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25424                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25425                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25426             return;
25427           }
25428         }
25429       }
25430     }
25431   }
25432   if (operand.IsRegister()) {
25433     DRegister rn = operand.GetRegister();
25434     Dt_U_size_3 encoded_dt(dt);
25435     if (IsUsingT32()) {
25436       // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
25437       if (encoded_dt.IsValid()) {
25438         if (cond.Is(al) || AllowStronglyDiscouraged()) {
25439           EmitT32_32(0xef000400U |
25440                      ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25441                      ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25442                      rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25443           AdvanceIT();
25444           return;
25445         }
25446       }
25447     } else {
25448       // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
25449       if (encoded_dt.IsValid()) {
25450         if (cond.Is(al)) {
25451           EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25452                   ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25453                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25454           return;
25455         }
25456       }
25457     }
25458   }
25459   Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25460 }
25461 
vshl(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)25462 void Assembler::vshl(Condition cond,
25463                      DataType dt,
25464                      QRegister rd,
25465                      QRegister rm,
25466                      const QOperand& operand) {
25467   VIXL_ASSERT(AllowAssembler());
25468   CheckIT(cond);
25469   if (operand.IsImmediate()) {
25470     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25471       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25472       Dt_L_imm6_3 encoded_dt(dt);
25473       if (IsUsingT32()) {
25474         // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
25475         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25476           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25477             uint32_t imm6 = imm;
25478             EmitT32_32(0xef800550U |
25479                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25480                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25481                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25482             AdvanceIT();
25483             return;
25484           }
25485         }
25486       } else {
25487         // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
25488         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25489           if (cond.Is(al)) {
25490             uint32_t imm6 = imm;
25491             EmitA32(0xf2800550U |
25492                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25493                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25494                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25495             return;
25496           }
25497         }
25498       }
25499     }
25500   }
25501   if (operand.IsRegister()) {
25502     QRegister rn = operand.GetRegister();
25503     Dt_U_size_3 encoded_dt(dt);
25504     if (IsUsingT32()) {
25505       // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
25506       if (encoded_dt.IsValid()) {
25507         if (cond.Is(al) || AllowStronglyDiscouraged()) {
25508           EmitT32_32(0xef000440U |
25509                      ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25510                      ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25511                      rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25512           AdvanceIT();
25513           return;
25514         }
25515       }
25516     } else {
25517       // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
25518       if (encoded_dt.IsValid()) {
25519         if (cond.Is(al)) {
25520           EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25521                   ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25522                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25523           return;
25524         }
25525       }
25526     }
25527   }
25528   Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25529 }
25530 
vshll(Condition cond,DataType dt,QRegister rd,DRegister rm,const DOperand & operand)25531 void Assembler::vshll(Condition cond,
25532                       DataType dt,
25533                       QRegister rd,
25534                       DRegister rm,
25535                       const DOperand& operand) {
25536   VIXL_ASSERT(AllowAssembler());
25537   CheckIT(cond);
25538   if (operand.IsImmediate()) {
25539     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25540       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25541       Dt_imm6_4 encoded_dt(dt);
25542       Dt_size_17 encoded_dt_2(dt);
25543       if (IsUsingT32()) {
25544         // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
25545         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25546           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25547             uint32_t imm6 = dt.GetSize() + imm;
25548             EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
25549                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25550                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25551             AdvanceIT();
25552             return;
25553           }
25554         }
25555         // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
25556         if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25557           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25558             EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25559                        rd.Encode(22, 12) | rm.Encode(5, 0));
25560             AdvanceIT();
25561             return;
25562           }
25563         }
25564       } else {
25565         // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
25566         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25567           if (cond.Is(al)) {
25568             uint32_t imm6 = dt.GetSize() + imm;
25569             EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
25570                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25571                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25572             return;
25573           }
25574         }
25575         // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
25576         if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25577           if (cond.Is(al)) {
25578             EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25579                     rd.Encode(22, 12) | rm.Encode(5, 0));
25580             return;
25581           }
25582         }
25583       }
25584     }
25585   }
25586   Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
25587 }
25588 
vshr(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)25589 void Assembler::vshr(Condition cond,
25590                      DataType dt,
25591                      DRegister rd,
25592                      DRegister rm,
25593                      const DOperand& operand) {
25594   VIXL_ASSERT(AllowAssembler());
25595   CheckIT(cond);
25596   if (operand.IsImmediate()) {
25597     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25598       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25599       Dt_L_imm6_1 encoded_dt(dt);
25600       if (IsUsingT32()) {
25601         // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25602         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25603           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25604             uint32_t imm6 = dt.GetSize() - imm;
25605             EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
25606                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25607                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25608                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25609             AdvanceIT();
25610             return;
25611           }
25612         }
25613         // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
25614         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25615           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25616             EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25617                        rm.Encode(5, 0));
25618             AdvanceIT();
25619             return;
25620           }
25621         }
25622       } else {
25623         // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25624         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25625           if (cond.Is(al)) {
25626             uint32_t imm6 = dt.GetSize() - imm;
25627             EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
25628                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25629                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25630                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25631             return;
25632           }
25633         }
25634         // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
25635         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25636           if (cond.Is(al)) {
25637             EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25638                     rm.Encode(5, 0));
25639             return;
25640           }
25641         }
25642       }
25643     }
25644   }
25645   Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25646 }
25647 
vshr(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)25648 void Assembler::vshr(Condition cond,
25649                      DataType dt,
25650                      QRegister rd,
25651                      QRegister rm,
25652                      const QOperand& operand) {
25653   VIXL_ASSERT(AllowAssembler());
25654   CheckIT(cond);
25655   if (operand.IsImmediate()) {
25656     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25657       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25658       Dt_L_imm6_1 encoded_dt(dt);
25659       if (IsUsingT32()) {
25660         // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25661         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25662           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25663             uint32_t imm6 = dt.GetSize() - imm;
25664             EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
25665                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25666                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25667                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25668             AdvanceIT();
25669             return;
25670           }
25671         }
25672         // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
25673         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25674           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25675             EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25676                        rm.Encode(5, 0));
25677             AdvanceIT();
25678             return;
25679           }
25680         }
25681       } else {
25682         // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25683         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25684           if (cond.Is(al)) {
25685             uint32_t imm6 = dt.GetSize() - imm;
25686             EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
25687                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25688                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25689                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25690             return;
25691           }
25692         }
25693         // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
25694         if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25695           if (cond.Is(al)) {
25696             EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25697                     rm.Encode(5, 0));
25698             return;
25699           }
25700         }
25701       }
25702     }
25703   }
25704   Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25705 }
25706 
vshrn(Condition cond,DataType dt,DRegister rd,QRegister rm,const QOperand & operand)25707 void Assembler::vshrn(Condition cond,
25708                       DataType dt,
25709                       DRegister rd,
25710                       QRegister rm,
25711                       const QOperand& operand) {
25712   VIXL_ASSERT(AllowAssembler());
25713   CheckIT(cond);
25714   if (operand.IsImmediate()) {
25715     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25716       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25717       Dt_imm6_3 encoded_dt(dt);
25718       Dt_size_3 encoded_dt_2(dt);
25719       if (IsUsingT32()) {
25720         // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
25721         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25722           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25723             uint32_t imm6 = dt.GetSize() / 2 - imm;
25724             EmitT32_32(0xef800810U |
25725                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25726                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25727             AdvanceIT();
25728             return;
25729           }
25730         }
25731         // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
25732         if (encoded_dt_2.IsValid() && (imm == 0)) {
25733           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25734             EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25735                        rd.Encode(22, 12) | rm.Encode(5, 0));
25736             AdvanceIT();
25737             return;
25738           }
25739         }
25740       } else {
25741         // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
25742         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25743           if (cond.Is(al)) {
25744             uint32_t imm6 = dt.GetSize() / 2 - imm;
25745             EmitA32(0xf2800810U |
25746                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25747                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25748             return;
25749           }
25750         }
25751         // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
25752         if (encoded_dt_2.IsValid() && (imm == 0)) {
25753           if (cond.Is(al)) {
25754             EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25755                     rd.Encode(22, 12) | rm.Encode(5, 0));
25756             return;
25757           }
25758         }
25759       }
25760     }
25761   }
25762   Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
25763 }
25764 
vsli(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)25765 void Assembler::vsli(Condition cond,
25766                      DataType dt,
25767                      DRegister rd,
25768                      DRegister rm,
25769                      const DOperand& operand) {
25770   VIXL_ASSERT(AllowAssembler());
25771   CheckIT(cond);
25772   if (operand.IsImmediate()) {
25773     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25774       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25775       Dt_L_imm6_4 encoded_dt(dt);
25776       if (IsUsingT32()) {
25777         // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25778         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25779           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25780             uint32_t imm6 = imm;
25781             EmitT32_32(0xff800510U |
25782                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25783                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25784                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25785             AdvanceIT();
25786             return;
25787           }
25788         }
25789       } else {
25790         // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25791         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25792           if (cond.Is(al)) {
25793             uint32_t imm6 = imm;
25794             EmitA32(0xf3800510U |
25795                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25796                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25797                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25798             return;
25799           }
25800         }
25801       }
25802     }
25803   }
25804   Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25805 }
25806 
vsli(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)25807 void Assembler::vsli(Condition cond,
25808                      DataType dt,
25809                      QRegister rd,
25810                      QRegister rm,
25811                      const QOperand& operand) {
25812   VIXL_ASSERT(AllowAssembler());
25813   CheckIT(cond);
25814   if (operand.IsImmediate()) {
25815     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25816       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25817       Dt_L_imm6_4 encoded_dt(dt);
25818       if (IsUsingT32()) {
25819         // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25820         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25821           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25822             uint32_t imm6 = imm;
25823             EmitT32_32(0xff800550U |
25824                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25825                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25826                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25827             AdvanceIT();
25828             return;
25829           }
25830         }
25831       } else {
25832         // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25833         if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25834           if (cond.Is(al)) {
25835             uint32_t imm6 = imm;
25836             EmitA32(0xf3800550U |
25837                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25838                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25839                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25840             return;
25841           }
25842         }
25843       }
25844     }
25845   }
25846   Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25847 }
25848 
vsqrt(Condition cond,DataType dt,SRegister rd,SRegister rm)25849 void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
25850   VIXL_ASSERT(AllowAssembler());
25851   CheckIT(cond);
25852   if (IsUsingT32()) {
25853     // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
25854     if (dt.Is(F32)) {
25855       EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25856       AdvanceIT();
25857       return;
25858     }
25859   } else {
25860     // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
25861     if (dt.Is(F32) && cond.IsNotNever()) {
25862       EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25863               rm.Encode(5, 0));
25864       return;
25865     }
25866   }
25867   Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25868 }
25869 
vsqrt(Condition cond,DataType dt,DRegister rd,DRegister rm)25870 void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
25871   VIXL_ASSERT(AllowAssembler());
25872   CheckIT(cond);
25873   if (IsUsingT32()) {
25874     // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
25875     if (dt.Is(F64)) {
25876       EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25877       AdvanceIT();
25878       return;
25879     }
25880   } else {
25881     // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
25882     if (dt.Is(F64) && cond.IsNotNever()) {
25883       EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25884               rm.Encode(5, 0));
25885       return;
25886     }
25887   }
25888   Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25889 }
25890 
vsra(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)25891 void Assembler::vsra(Condition cond,
25892                      DataType dt,
25893                      DRegister rd,
25894                      DRegister rm,
25895                      const DOperand& operand) {
25896   VIXL_ASSERT(AllowAssembler());
25897   CheckIT(cond);
25898   if (operand.IsImmediate()) {
25899     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25900       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25901       Dt_L_imm6_1 encoded_dt(dt);
25902       if (IsUsingT32()) {
25903         // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25904         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25905           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25906             uint32_t imm6 = dt.GetSize() - imm;
25907             EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
25908                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25909                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25910                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25911             AdvanceIT();
25912             return;
25913           }
25914         }
25915       } else {
25916         // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25917         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25918           if (cond.Is(al)) {
25919             uint32_t imm6 = dt.GetSize() - imm;
25920             EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
25921                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25922                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25923                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25924             return;
25925           }
25926         }
25927       }
25928     }
25929   }
25930   Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25931 }
25932 
vsra(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)25933 void Assembler::vsra(Condition cond,
25934                      DataType dt,
25935                      QRegister rd,
25936                      QRegister rm,
25937                      const QOperand& operand) {
25938   VIXL_ASSERT(AllowAssembler());
25939   CheckIT(cond);
25940   if (operand.IsImmediate()) {
25941     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25942       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25943       Dt_L_imm6_1 encoded_dt(dt);
25944       if (IsUsingT32()) {
25945         // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25946         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25947           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25948             uint32_t imm6 = dt.GetSize() - imm;
25949             EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
25950                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25951                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25952                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25953             AdvanceIT();
25954             return;
25955           }
25956         }
25957       } else {
25958         // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25959         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25960           if (cond.Is(al)) {
25961             uint32_t imm6 = dt.GetSize() - imm;
25962             EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
25963                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25964                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25965                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25966             return;
25967           }
25968         }
25969       }
25970     }
25971   }
25972   Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25973 }
25974 
vsri(Condition cond,DataType dt,DRegister rd,DRegister rm,const DOperand & operand)25975 void Assembler::vsri(Condition cond,
25976                      DataType dt,
25977                      DRegister rd,
25978                      DRegister rm,
25979                      const DOperand& operand) {
25980   VIXL_ASSERT(AllowAssembler());
25981   CheckIT(cond);
25982   if (operand.IsImmediate()) {
25983     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25984       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25985       Dt_L_imm6_4 encoded_dt(dt);
25986       if (IsUsingT32()) {
25987         // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25988         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25989           if (cond.Is(al) || AllowStronglyDiscouraged()) {
25990             uint32_t imm6 = dt.GetSize() - imm;
25991             EmitT32_32(0xff800410U |
25992                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25993                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25994                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25995             AdvanceIT();
25996             return;
25997           }
25998         }
25999       } else {
26000         // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
26001         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
26002           if (cond.Is(al)) {
26003             uint32_t imm6 = dt.GetSize() - imm;
26004             EmitA32(0xf3800410U |
26005                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
26006                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
26007                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
26008             return;
26009           }
26010         }
26011       }
26012     }
26013   }
26014   Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
26015 }
26016 
vsri(Condition cond,DataType dt,QRegister rd,QRegister rm,const QOperand & operand)26017 void Assembler::vsri(Condition cond,
26018                      DataType dt,
26019                      QRegister rd,
26020                      QRegister rm,
26021                      const QOperand& operand) {
26022   VIXL_ASSERT(AllowAssembler());
26023   CheckIT(cond);
26024   if (operand.IsImmediate()) {
26025     if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
26026       uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
26027       Dt_L_imm6_4 encoded_dt(dt);
26028       if (IsUsingT32()) {
26029         // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
26030         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
26031           if (cond.Is(al) || AllowStronglyDiscouraged()) {
26032             uint32_t imm6 = dt.GetSize() - imm;
26033             EmitT32_32(0xff800450U |
26034                        ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
26035                        ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
26036                        rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
26037             AdvanceIT();
26038             return;
26039           }
26040         }
26041       } else {
26042         // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
26043         if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
26044           if (cond.Is(al)) {
26045             uint32_t imm6 = dt.GetSize() - imm;
26046             EmitA32(0xf3800450U |
26047                     ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
26048                     ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
26049                     rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
26050             return;
26051           }
26052         }
26053       }
26054     }
26055   }
26056   Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
26057 }
26058 
vst1(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)26059 void Assembler::vst1(Condition cond,
26060                      DataType dt,
26061                      const NeonRegisterList& nreglist,
26062                      const AlignedMemOperand& operand) {
26063   VIXL_ASSERT(AllowAssembler());
26064   CheckIT(cond);
26065   if (operand.IsImmediateZero()) {
26066     Register rn = operand.GetBaseRegister();
26067     Alignment align = operand.GetAlignment();
26068     Dt_size_6 encoded_dt(dt);
26069     Dt_size_7 encoded_dt_2(dt);
26070     Align_align_5 encoded_align_1(align, nreglist);
26071     Align_index_align_1 encoded_align_2(align, nreglist, dt);
26072     if (IsUsingT32()) {
26073       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26074       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26075           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26076           operand.IsOffset() && encoded_align_1.IsValid() &&
26077           (!rn.IsPC() || AllowUnpredictable())) {
26078         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26079           const DRegister& first = nreglist.GetFirstDRegister();
26080           uint32_t len_encoding;
26081           switch (nreglist.GetLength()) {
26082             default:
26083               VIXL_UNREACHABLE_OR_FALLTHROUGH();
26084             case 1:
26085               len_encoding = 0x7;
26086               break;
26087             case 2:
26088               len_encoding = 0xa;
26089               break;
26090             case 3:
26091               len_encoding = 0x6;
26092               break;
26093             case 4:
26094               len_encoding = 0x2;
26095               break;
26096           }
26097           EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26098                      (encoded_align_1.GetEncodingValue() << 4) |
26099                      first.Encode(22, 12) | (len_encoding << 8) |
26100                      (rn.GetCode() << 16));
26101           AdvanceIT();
26102           return;
26103         }
26104       }
26105       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26106       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26107           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26108           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26109           (!rn.IsPC() || AllowUnpredictable())) {
26110         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26111           const DRegister& first = nreglist.GetFirstDRegister();
26112           uint32_t len_encoding;
26113           switch (nreglist.GetLength()) {
26114             default:
26115               VIXL_UNREACHABLE_OR_FALLTHROUGH();
26116             case 1:
26117               len_encoding = 0x7;
26118               break;
26119             case 2:
26120               len_encoding = 0xa;
26121               break;
26122             case 3:
26123               len_encoding = 0x6;
26124               break;
26125             case 4:
26126               len_encoding = 0x2;
26127               break;
26128           }
26129           EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26130                      (encoded_align_1.GetEncodingValue() << 4) |
26131                      first.Encode(22, 12) | (len_encoding << 8) |
26132                      (rn.GetCode() << 16));
26133           AdvanceIT();
26134           return;
26135         }
26136       }
26137       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26138       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26139           (nreglist.GetLength() == 1) && operand.IsOffset() &&
26140           encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26141         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26142           const DRegister& first = nreglist.GetFirstDRegister();
26143           EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26144                      (encoded_align_2.GetEncodingValue() << 4) |
26145                      first.Encode(22, 12) | (rn.GetCode() << 16));
26146           AdvanceIT();
26147           return;
26148         }
26149       }
26150       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26151       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26152           (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
26153           encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26154         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26155           const DRegister& first = nreglist.GetFirstDRegister();
26156           EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26157                      (encoded_align_2.GetEncodingValue() << 4) |
26158                      first.Encode(22, 12) | (rn.GetCode() << 16));
26159           AdvanceIT();
26160           return;
26161         }
26162       }
26163     } else {
26164       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26165       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26166           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26167           operand.IsOffset() && encoded_align_1.IsValid() &&
26168           (!rn.IsPC() || AllowUnpredictable())) {
26169         if (cond.Is(al)) {
26170           const DRegister& first = nreglist.GetFirstDRegister();
26171           uint32_t len_encoding;
26172           switch (nreglist.GetLength()) {
26173             default:
26174               VIXL_UNREACHABLE_OR_FALLTHROUGH();
26175             case 1:
26176               len_encoding = 0x7;
26177               break;
26178             case 2:
26179               len_encoding = 0xa;
26180               break;
26181             case 3:
26182               len_encoding = 0x6;
26183               break;
26184             case 4:
26185               len_encoding = 0x2;
26186               break;
26187           }
26188           EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26189                   (encoded_align_1.GetEncodingValue() << 4) |
26190                   first.Encode(22, 12) | (len_encoding << 8) |
26191                   (rn.GetCode() << 16));
26192           return;
26193         }
26194       }
26195       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26196       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26197           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26198           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26199           (!rn.IsPC() || AllowUnpredictable())) {
26200         if (cond.Is(al)) {
26201           const DRegister& first = nreglist.GetFirstDRegister();
26202           uint32_t len_encoding;
26203           switch (nreglist.GetLength()) {
26204             default:
26205               VIXL_UNREACHABLE_OR_FALLTHROUGH();
26206             case 1:
26207               len_encoding = 0x7;
26208               break;
26209             case 2:
26210               len_encoding = 0xa;
26211               break;
26212             case 3:
26213               len_encoding = 0x6;
26214               break;
26215             case 4:
26216               len_encoding = 0x2;
26217               break;
26218           }
26219           EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26220                   (encoded_align_1.GetEncodingValue() << 4) |
26221                   first.Encode(22, 12) | (len_encoding << 8) |
26222                   (rn.GetCode() << 16));
26223           return;
26224         }
26225       }
26226       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26227       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26228           (nreglist.GetLength() == 1) && operand.IsOffset() &&
26229           encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26230         if (cond.Is(al)) {
26231           const DRegister& first = nreglist.GetFirstDRegister();
26232           EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26233                   (encoded_align_2.GetEncodingValue() << 4) |
26234                   first.Encode(22, 12) | (rn.GetCode() << 16));
26235           return;
26236         }
26237       }
26238       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26239       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26240           (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
26241           encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26242         if (cond.Is(al)) {
26243           const DRegister& first = nreglist.GetFirstDRegister();
26244           EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26245                   (encoded_align_2.GetEncodingValue() << 4) |
26246                   first.Encode(22, 12) | (rn.GetCode() << 16));
26247           return;
26248         }
26249       }
26250     }
26251   }
26252   if (operand.IsPlainRegister()) {
26253     Register rn = operand.GetBaseRegister();
26254     Alignment align = operand.GetAlignment();
26255     Register rm = operand.GetOffsetRegister();
26256     Dt_size_6 encoded_dt(dt);
26257     Dt_size_7 encoded_dt_2(dt);
26258     Align_align_5 encoded_align_1(align, nreglist);
26259     Align_index_align_1 encoded_align_2(align, nreglist, dt);
26260     if (IsUsingT32()) {
26261       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26262       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26263           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26264           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26265         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26266           const DRegister& first = nreglist.GetFirstDRegister();
26267           uint32_t len_encoding;
26268           switch (nreglist.GetLength()) {
26269             default:
26270               VIXL_UNREACHABLE_OR_FALLTHROUGH();
26271             case 1:
26272               len_encoding = 0x7;
26273               break;
26274             case 2:
26275               len_encoding = 0xa;
26276               break;
26277             case 3:
26278               len_encoding = 0x6;
26279               break;
26280             case 4:
26281               len_encoding = 0x2;
26282               break;
26283           }
26284           EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26285                      (encoded_align_1.GetEncodingValue() << 4) |
26286                      first.Encode(22, 12) | (len_encoding << 8) |
26287                      (rn.GetCode() << 16) | rm.GetCode());
26288           AdvanceIT();
26289           return;
26290         }
26291       }
26292       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26293       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26294           (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26295           (!rn.IsPC() || AllowUnpredictable())) {
26296         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26297           const DRegister& first = nreglist.GetFirstDRegister();
26298           EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26299                      (encoded_align_2.GetEncodingValue() << 4) |
26300                      first.Encode(22, 12) | (rn.GetCode() << 16) |
26301                      rm.GetCode());
26302           AdvanceIT();
26303           return;
26304         }
26305       }
26306     } else {
26307       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26308       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26309           (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26310           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26311         if (cond.Is(al)) {
26312           const DRegister& first = nreglist.GetFirstDRegister();
26313           uint32_t len_encoding;
26314           switch (nreglist.GetLength()) {
26315             default:
26316               VIXL_UNREACHABLE_OR_FALLTHROUGH();
26317             case 1:
26318               len_encoding = 0x7;
26319               break;
26320             case 2:
26321               len_encoding = 0xa;
26322               break;
26323             case 3:
26324               len_encoding = 0x6;
26325               break;
26326             case 4:
26327               len_encoding = 0x2;
26328               break;
26329           }
26330           EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26331                   (encoded_align_1.GetEncodingValue() << 4) |
26332                   first.Encode(22, 12) | (len_encoding << 8) |
26333                   (rn.GetCode() << 16) | rm.GetCode());
26334           return;
26335         }
26336       }
26337       // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26338       if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26339           (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26340           (!rn.IsPC() || AllowUnpredictable())) {
26341         if (cond.Is(al)) {
26342           const DRegister& first = nreglist.GetFirstDRegister();
26343           EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26344                   (encoded_align_2.GetEncodingValue() << 4) |
26345                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26346           return;
26347         }
26348       }
26349     }
26350   }
26351   Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
26352 }
26353 
vst2(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)26354 void Assembler::vst2(Condition cond,
26355                      DataType dt,
26356                      const NeonRegisterList& nreglist,
26357                      const AlignedMemOperand& operand) {
26358   VIXL_ASSERT(AllowAssembler());
26359   CheckIT(cond);
26360   if (operand.IsImmediateZero()) {
26361     Register rn = operand.GetBaseRegister();
26362     Alignment align = operand.GetAlignment();
26363     Dt_size_7 encoded_dt(dt);
26364     Align_align_2 encoded_align_1(align, nreglist);
26365     Align_index_align_2 encoded_align_2(align, nreglist, dt);
26366     if (IsUsingT32()) {
26367       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26368       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26369           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26370            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26371            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26372           operand.IsOffset() && encoded_align_1.IsValid() &&
26373           (!rn.IsPC() || AllowUnpredictable())) {
26374         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26375           const DRegister& first = nreglist.GetFirstDRegister();
26376           uint32_t len_encoding;
26377           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26378             len_encoding = 0x8;
26379           }
26380           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26381             len_encoding = 0x9;
26382           }
26383           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26384             len_encoding = 0x3;
26385           }
26386           EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26387                      (encoded_align_1.GetEncodingValue() << 4) |
26388                      first.Encode(22, 12) | (len_encoding << 8) |
26389                      (rn.GetCode() << 16));
26390           AdvanceIT();
26391           return;
26392         }
26393       }
26394       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26395       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26396           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26397            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26398            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26399           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26400           (!rn.IsPC() || AllowUnpredictable())) {
26401         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26402           const DRegister& first = nreglist.GetFirstDRegister();
26403           uint32_t len_encoding;
26404           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26405             len_encoding = 0x8;
26406           }
26407           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26408             len_encoding = 0x9;
26409           }
26410           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26411             len_encoding = 0x3;
26412           }
26413           EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26414                      (encoded_align_1.GetEncodingValue() << 4) |
26415                      first.Encode(22, 12) | (len_encoding << 8) |
26416                      (rn.GetCode() << 16));
26417           AdvanceIT();
26418           return;
26419         }
26420       }
26421       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26422       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26423           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26424            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26425           operand.IsOffset() && encoded_align_2.IsValid() &&
26426           (!rn.IsPC() || AllowUnpredictable())) {
26427         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26428           const DRegister& first = nreglist.GetFirstDRegister();
26429           EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
26430                      (encoded_align_2.GetEncodingValue() << 4) |
26431                      first.Encode(22, 12) | (rn.GetCode() << 16));
26432           AdvanceIT();
26433           return;
26434         }
26435       }
26436       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26437       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26438           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26439            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26440           operand.IsPostIndex() && encoded_align_2.IsValid() &&
26441           (!rn.IsPC() || AllowUnpredictable())) {
26442         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26443           const DRegister& first = nreglist.GetFirstDRegister();
26444           EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
26445                      (encoded_align_2.GetEncodingValue() << 4) |
26446                      first.Encode(22, 12) | (rn.GetCode() << 16));
26447           AdvanceIT();
26448           return;
26449         }
26450       }
26451     } else {
26452       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26453       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26454           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26455            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26456            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26457           operand.IsOffset() && encoded_align_1.IsValid() &&
26458           (!rn.IsPC() || AllowUnpredictable())) {
26459         if (cond.Is(al)) {
26460           const DRegister& first = nreglist.GetFirstDRegister();
26461           uint32_t len_encoding;
26462           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26463             len_encoding = 0x8;
26464           }
26465           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26466             len_encoding = 0x9;
26467           }
26468           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26469             len_encoding = 0x3;
26470           }
26471           EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26472                   (encoded_align_1.GetEncodingValue() << 4) |
26473                   first.Encode(22, 12) | (len_encoding << 8) |
26474                   (rn.GetCode() << 16));
26475           return;
26476         }
26477       }
26478       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26479       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26480           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26481            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26482            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26483           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26484           (!rn.IsPC() || AllowUnpredictable())) {
26485         if (cond.Is(al)) {
26486           const DRegister& first = nreglist.GetFirstDRegister();
26487           uint32_t len_encoding;
26488           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26489             len_encoding = 0x8;
26490           }
26491           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26492             len_encoding = 0x9;
26493           }
26494           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26495             len_encoding = 0x3;
26496           }
26497           EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26498                   (encoded_align_1.GetEncodingValue() << 4) |
26499                   first.Encode(22, 12) | (len_encoding << 8) |
26500                   (rn.GetCode() << 16));
26501           return;
26502         }
26503       }
26504       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26505       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26506           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26507            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26508           operand.IsOffset() && encoded_align_2.IsValid() &&
26509           (!rn.IsPC() || AllowUnpredictable())) {
26510         if (cond.Is(al)) {
26511           const DRegister& first = nreglist.GetFirstDRegister();
26512           EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
26513                   (encoded_align_2.GetEncodingValue() << 4) |
26514                   first.Encode(22, 12) | (rn.GetCode() << 16));
26515           return;
26516         }
26517       }
26518       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26519       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26520           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26521            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26522           operand.IsPostIndex() && encoded_align_2.IsValid() &&
26523           (!rn.IsPC() || AllowUnpredictable())) {
26524         if (cond.Is(al)) {
26525           const DRegister& first = nreglist.GetFirstDRegister();
26526           EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
26527                   (encoded_align_2.GetEncodingValue() << 4) |
26528                   first.Encode(22, 12) | (rn.GetCode() << 16));
26529           return;
26530         }
26531       }
26532     }
26533   }
26534   if (operand.IsPlainRegister()) {
26535     Register rn = operand.GetBaseRegister();
26536     Alignment align = operand.GetAlignment();
26537     Register rm = operand.GetOffsetRegister();
26538     Dt_size_7 encoded_dt(dt);
26539     Align_align_2 encoded_align_1(align, nreglist);
26540     Align_index_align_2 encoded_align_2(align, nreglist, dt);
26541     if (IsUsingT32()) {
26542       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26543       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26544           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26545            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26546            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26547           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26548         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26549           const DRegister& first = nreglist.GetFirstDRegister();
26550           uint32_t len_encoding;
26551           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26552             len_encoding = 0x8;
26553           }
26554           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26555             len_encoding = 0x9;
26556           }
26557           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26558             len_encoding = 0x3;
26559           }
26560           EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26561                      (encoded_align_1.GetEncodingValue() << 4) |
26562                      first.Encode(22, 12) | (len_encoding << 8) |
26563                      (rn.GetCode() << 16) | rm.GetCode());
26564           AdvanceIT();
26565           return;
26566         }
26567       }
26568       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26569       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26570           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26571            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26572           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26573         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26574           const DRegister& first = nreglist.GetFirstDRegister();
26575           EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
26576                      (encoded_align_2.GetEncodingValue() << 4) |
26577                      first.Encode(22, 12) | (rn.GetCode() << 16) |
26578                      rm.GetCode());
26579           AdvanceIT();
26580           return;
26581         }
26582       }
26583     } else {
26584       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26585       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26586           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26587            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26588            (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26589           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26590         if (cond.Is(al)) {
26591           const DRegister& first = nreglist.GetFirstDRegister();
26592           uint32_t len_encoding;
26593           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26594             len_encoding = 0x8;
26595           }
26596           if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26597             len_encoding = 0x9;
26598           }
26599           if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26600             len_encoding = 0x3;
26601           }
26602           EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26603                   (encoded_align_1.GetEncodingValue() << 4) |
26604                   first.Encode(22, 12) | (len_encoding << 8) |
26605                   (rn.GetCode() << 16) | rm.GetCode());
26606           return;
26607         }
26608       }
26609       // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26610       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26611           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26612            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26613           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26614         if (cond.Is(al)) {
26615           const DRegister& first = nreglist.GetFirstDRegister();
26616           EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
26617                   (encoded_align_2.GetEncodingValue() << 4) |
26618                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26619           return;
26620         }
26621       }
26622     }
26623   }
26624   Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
26625 }
26626 
vst3(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)26627 void Assembler::vst3(Condition cond,
26628                      DataType dt,
26629                      const NeonRegisterList& nreglist,
26630                      const AlignedMemOperand& operand) {
26631   VIXL_ASSERT(AllowAssembler());
26632   CheckIT(cond);
26633   if (operand.IsImmediateZero()) {
26634     Register rn = operand.GetBaseRegister();
26635     Alignment align = operand.GetAlignment();
26636     Dt_size_7 encoded_dt(dt);
26637     Align_align_3 encoded_align_1(align);
26638     if (IsUsingT32()) {
26639       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26640       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26641           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26642            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26643           operand.IsOffset() && encoded_align_1.IsValid() &&
26644           (!rn.IsPC() || AllowUnpredictable())) {
26645         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26646           const DRegister& first = nreglist.GetFirstDRegister();
26647           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26648           EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26649                      (encoded_align_1.GetEncodingValue() << 4) |
26650                      first.Encode(22, 12) | (len_encoding << 8) |
26651                      (rn.GetCode() << 16));
26652           AdvanceIT();
26653           return;
26654         }
26655       }
26656       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26657       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26658           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26659            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26660           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26661           (!rn.IsPC() || AllowUnpredictable())) {
26662         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26663           const DRegister& first = nreglist.GetFirstDRegister();
26664           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26665           EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26666                      (encoded_align_1.GetEncodingValue() << 4) |
26667                      first.Encode(22, 12) | (len_encoding << 8) |
26668                      (rn.GetCode() << 16));
26669           AdvanceIT();
26670           return;
26671         }
26672       }
26673     } else {
26674       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26675       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26676           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26677            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26678           operand.IsOffset() && encoded_align_1.IsValid() &&
26679           (!rn.IsPC() || AllowUnpredictable())) {
26680         if (cond.Is(al)) {
26681           const DRegister& first = nreglist.GetFirstDRegister();
26682           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26683           EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26684                   (encoded_align_1.GetEncodingValue() << 4) |
26685                   first.Encode(22, 12) | (len_encoding << 8) |
26686                   (rn.GetCode() << 16));
26687           return;
26688         }
26689       }
26690       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26691       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26692           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26693            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26694           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26695           (!rn.IsPC() || AllowUnpredictable())) {
26696         if (cond.Is(al)) {
26697           const DRegister& first = nreglist.GetFirstDRegister();
26698           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26699           EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26700                   (encoded_align_1.GetEncodingValue() << 4) |
26701                   first.Encode(22, 12) | (len_encoding << 8) |
26702                   (rn.GetCode() << 16));
26703           return;
26704         }
26705       }
26706     }
26707   }
26708   if (operand.IsPlainRegister()) {
26709     Register rn = operand.GetBaseRegister();
26710     Alignment align = operand.GetAlignment();
26711     Register rm = operand.GetOffsetRegister();
26712     Dt_size_7 encoded_dt(dt);
26713     Align_align_3 encoded_align_1(align);
26714     if (IsUsingT32()) {
26715       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26716       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26717           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26718            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26719           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26720         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26721           const DRegister& first = nreglist.GetFirstDRegister();
26722           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26723           EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26724                      (encoded_align_1.GetEncodingValue() << 4) |
26725                      first.Encode(22, 12) | (len_encoding << 8) |
26726                      (rn.GetCode() << 16) | rm.GetCode());
26727           AdvanceIT();
26728           return;
26729         }
26730       }
26731     } else {
26732       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26733       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26734           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26735            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26736           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26737         if (cond.Is(al)) {
26738           const DRegister& first = nreglist.GetFirstDRegister();
26739           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26740           EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26741                   (encoded_align_1.GetEncodingValue() << 4) |
26742                   first.Encode(22, 12) | (len_encoding << 8) |
26743                   (rn.GetCode() << 16) | rm.GetCode());
26744           return;
26745         }
26746       }
26747     }
26748   }
26749   Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26750 }
26751 
vst3(Condition cond,DataType dt,const NeonRegisterList & nreglist,const MemOperand & operand)26752 void Assembler::vst3(Condition cond,
26753                      DataType dt,
26754                      const NeonRegisterList& nreglist,
26755                      const MemOperand& operand) {
26756   VIXL_ASSERT(AllowAssembler());
26757   CheckIT(cond);
26758   if (operand.IsImmediateZero()) {
26759     Register rn = operand.GetBaseRegister();
26760     Dt_size_7 encoded_dt(dt);
26761     Index_1 encoded_align_1(nreglist, dt);
26762     if (IsUsingT32()) {
26763       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
26764       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26765           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26766            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26767           operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
26768         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26769           const DRegister& first = nreglist.GetFirstDRegister();
26770           EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
26771                      (encoded_align_1.GetEncodingValue() << 4) |
26772                      first.Encode(22, 12) | (rn.GetCode() << 16));
26773           AdvanceIT();
26774           return;
26775         }
26776       }
26777       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
26778       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26779           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26780            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26781           operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
26782         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26783           const DRegister& first = nreglist.GetFirstDRegister();
26784           EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
26785                      (encoded_align_1.GetEncodingValue() << 4) |
26786                      first.Encode(22, 12) | (rn.GetCode() << 16));
26787           AdvanceIT();
26788           return;
26789         }
26790       }
26791     } else {
26792       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
26793       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26794           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26795            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26796           operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
26797         if (cond.Is(al)) {
26798           const DRegister& first = nreglist.GetFirstDRegister();
26799           EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
26800                   (encoded_align_1.GetEncodingValue() << 4) |
26801                   first.Encode(22, 12) | (rn.GetCode() << 16));
26802           return;
26803         }
26804       }
26805       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
26806       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26807           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26808            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26809           operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
26810         if (cond.Is(al)) {
26811           const DRegister& first = nreglist.GetFirstDRegister();
26812           EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
26813                   (encoded_align_1.GetEncodingValue() << 4) |
26814                   first.Encode(22, 12) | (rn.GetCode() << 16));
26815           return;
26816         }
26817       }
26818     }
26819   }
26820   if (operand.IsPlainRegister()) {
26821     Register rn = operand.GetBaseRegister();
26822     Sign sign = operand.GetSign();
26823     Register rm = operand.GetOffsetRegister();
26824     Dt_size_7 encoded_dt(dt);
26825     Index_1 encoded_align_1(nreglist, dt);
26826     if (IsUsingT32()) {
26827       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
26828       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26829           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26830            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26831           sign.IsPlus() && operand.IsPostIndex() &&
26832           (!rn.IsPC() || AllowUnpredictable())) {
26833         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26834           const DRegister& first = nreglist.GetFirstDRegister();
26835           EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
26836                      (encoded_align_1.GetEncodingValue() << 4) |
26837                      first.Encode(22, 12) | (rn.GetCode() << 16) |
26838                      rm.GetCode());
26839           AdvanceIT();
26840           return;
26841         }
26842       }
26843     } else {
26844       // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
26845       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26846           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26847            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26848           sign.IsPlus() && operand.IsPostIndex() &&
26849           (!rn.IsPC() || AllowUnpredictable())) {
26850         if (cond.Is(al)) {
26851           const DRegister& first = nreglist.GetFirstDRegister();
26852           EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
26853                   (encoded_align_1.GetEncodingValue() << 4) |
26854                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26855           return;
26856         }
26857       }
26858     }
26859   }
26860   Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26861 }
26862 
vst4(Condition cond,DataType dt,const NeonRegisterList & nreglist,const AlignedMemOperand & operand)26863 void Assembler::vst4(Condition cond,
26864                      DataType dt,
26865                      const NeonRegisterList& nreglist,
26866                      const AlignedMemOperand& operand) {
26867   VIXL_ASSERT(AllowAssembler());
26868   CheckIT(cond);
26869   if (operand.IsImmediateZero()) {
26870     Register rn = operand.GetBaseRegister();
26871     Alignment align = operand.GetAlignment();
26872     Dt_size_7 encoded_dt(dt);
26873     Align_align_4 encoded_align_1(align);
26874     Align_index_align_3 encoded_align_2(align, nreglist, dt);
26875     if (IsUsingT32()) {
26876       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26877       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26878           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26879            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26880           operand.IsOffset() && encoded_align_1.IsValid() &&
26881           (!rn.IsPC() || AllowUnpredictable())) {
26882         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26883           const DRegister& first = nreglist.GetFirstDRegister();
26884           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26885           EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26886                      (encoded_align_1.GetEncodingValue() << 4) |
26887                      first.Encode(22, 12) | (len_encoding << 8) |
26888                      (rn.GetCode() << 16));
26889           AdvanceIT();
26890           return;
26891         }
26892       }
26893       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26894       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26895           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26896            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26897           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26898           (!rn.IsPC() || AllowUnpredictable())) {
26899         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26900           const DRegister& first = nreglist.GetFirstDRegister();
26901           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26902           EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26903                      (encoded_align_1.GetEncodingValue() << 4) |
26904                      first.Encode(22, 12) | (len_encoding << 8) |
26905                      (rn.GetCode() << 16));
26906           AdvanceIT();
26907           return;
26908         }
26909       }
26910       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26911       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26912           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26913            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26914           operand.IsOffset() && encoded_align_2.IsValid() &&
26915           (!rn.IsPC() || AllowUnpredictable())) {
26916         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26917           const DRegister& first = nreglist.GetFirstDRegister();
26918           EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
26919                      (encoded_align_2.GetEncodingValue() << 4) |
26920                      first.Encode(22, 12) | (rn.GetCode() << 16));
26921           AdvanceIT();
26922           return;
26923         }
26924       }
26925       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26926       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26927           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26928            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26929           operand.IsPostIndex() && encoded_align_2.IsValid() &&
26930           (!rn.IsPC() || AllowUnpredictable())) {
26931         if (cond.Is(al) || AllowStronglyDiscouraged()) {
26932           const DRegister& first = nreglist.GetFirstDRegister();
26933           EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
26934                      (encoded_align_2.GetEncodingValue() << 4) |
26935                      first.Encode(22, 12) | (rn.GetCode() << 16));
26936           AdvanceIT();
26937           return;
26938         }
26939       }
26940     } else {
26941       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26942       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26943           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26944            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26945           operand.IsOffset() && encoded_align_1.IsValid() &&
26946           (!rn.IsPC() || AllowUnpredictable())) {
26947         if (cond.Is(al)) {
26948           const DRegister& first = nreglist.GetFirstDRegister();
26949           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26950           EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26951                   (encoded_align_1.GetEncodingValue() << 4) |
26952                   first.Encode(22, 12) | (len_encoding << 8) |
26953                   (rn.GetCode() << 16));
26954           return;
26955         }
26956       }
26957       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26958       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26959           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26960            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26961           operand.IsPostIndex() && encoded_align_1.IsValid() &&
26962           (!rn.IsPC() || AllowUnpredictable())) {
26963         if (cond.Is(al)) {
26964           const DRegister& first = nreglist.GetFirstDRegister();
26965           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26966           EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26967                   (encoded_align_1.GetEncodingValue() << 4) |
26968                   first.Encode(22, 12) | (len_encoding << 8) |
26969                   (rn.GetCode() << 16));
26970           return;
26971         }
26972       }
26973       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26974       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26975           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26976            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26977           operand.IsOffset() && encoded_align_2.IsValid() &&
26978           (!rn.IsPC() || AllowUnpredictable())) {
26979         if (cond.Is(al)) {
26980           const DRegister& first = nreglist.GetFirstDRegister();
26981           EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
26982                   (encoded_align_2.GetEncodingValue() << 4) |
26983                   first.Encode(22, 12) | (rn.GetCode() << 16));
26984           return;
26985         }
26986       }
26987       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26988       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26989           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26990            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26991           operand.IsPostIndex() && encoded_align_2.IsValid() &&
26992           (!rn.IsPC() || AllowUnpredictable())) {
26993         if (cond.Is(al)) {
26994           const DRegister& first = nreglist.GetFirstDRegister();
26995           EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
26996                   (encoded_align_2.GetEncodingValue() << 4) |
26997                   first.Encode(22, 12) | (rn.GetCode() << 16));
26998           return;
26999         }
27000       }
27001     }
27002   }
27003   if (operand.IsPlainRegister()) {
27004     Register rn = operand.GetBaseRegister();
27005     Alignment align = operand.GetAlignment();
27006     Register rm = operand.GetOffsetRegister();
27007     Dt_size_7 encoded_dt(dt);
27008     Align_align_4 encoded_align_1(align);
27009     Align_index_align_3 encoded_align_2(align, nreglist, dt);
27010     if (IsUsingT32()) {
27011       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
27012       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
27013           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27014            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
27015           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
27016         if (cond.Is(al) || AllowStronglyDiscouraged()) {
27017           const DRegister& first = nreglist.GetFirstDRegister();
27018           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
27019           EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
27020                      (encoded_align_1.GetEncodingValue() << 4) |
27021                      first.Encode(22, 12) | (len_encoding << 8) |
27022                      (rn.GetCode() << 16) | rm.GetCode());
27023           AdvanceIT();
27024           return;
27025         }
27026       }
27027       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
27028       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
27029           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27030            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
27031           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
27032         if (cond.Is(al) || AllowStronglyDiscouraged()) {
27033           const DRegister& first = nreglist.GetFirstDRegister();
27034           EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
27035                      (encoded_align_2.GetEncodingValue() << 4) |
27036                      first.Encode(22, 12) | (rn.GetCode() << 16) |
27037                      rm.GetCode());
27038           AdvanceIT();
27039           return;
27040         }
27041       }
27042     } else {
27043       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
27044       if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
27045           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27046            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
27047           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
27048         if (cond.Is(al)) {
27049           const DRegister& first = nreglist.GetFirstDRegister();
27050           uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
27051           EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
27052                   (encoded_align_1.GetEncodingValue() << 4) |
27053                   first.Encode(22, 12) | (len_encoding << 8) |
27054                   (rn.GetCode() << 16) | rm.GetCode());
27055           return;
27056         }
27057       }
27058       // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
27059       if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
27060           ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27061            (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
27062           !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
27063         if (cond.Is(al)) {
27064           const DRegister& first = nreglist.GetFirstDRegister();
27065           EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
27066                   (encoded_align_2.GetEncodingValue() << 4) |
27067                   first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
27068           return;
27069         }
27070       }
27071     }
27072   }
27073   Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
27074 }
27075 
vstm(Condition cond,DataType dt,Register rn,WriteBack write_back,DRegisterList dreglist)27076 void Assembler::vstm(Condition cond,
27077                      DataType dt,
27078                      Register rn,
27079                      WriteBack write_back,
27080                      DRegisterList dreglist) {
27081   VIXL_ASSERT(AllowAssembler());
27082   CheckIT(cond);
27083   USE(dt);
27084   if (IsUsingT32()) {
27085     // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
27086     if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27087          AllowUnpredictable())) {
27088       const DRegister& dreg = dreglist.GetFirstDRegister();
27089       unsigned len = dreglist.GetLength() * 2;
27090       EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27091                  (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27092                  (len & 0xff));
27093       AdvanceIT();
27094       return;
27095     }
27096   } else {
27097     // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
27098     if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27099                                (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27100                               AllowUnpredictable())) {
27101       const DRegister& dreg = dreglist.GetFirstDRegister();
27102       unsigned len = dreglist.GetLength() * 2;
27103       EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27104               (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27105               (len & 0xff));
27106       return;
27107     }
27108   }
27109   Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
27110 }
27111 
vstm(Condition cond,DataType dt,Register rn,WriteBack write_back,SRegisterList sreglist)27112 void Assembler::vstm(Condition cond,
27113                      DataType dt,
27114                      Register rn,
27115                      WriteBack write_back,
27116                      SRegisterList sreglist) {
27117   VIXL_ASSERT(AllowAssembler());
27118   CheckIT(cond);
27119   USE(dt);
27120   if (IsUsingT32()) {
27121     // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
27122     if ((!rn.IsPC() || AllowUnpredictable())) {
27123       const SRegister& sreg = sreglist.GetFirstSRegister();
27124       unsigned len = sreglist.GetLength();
27125       EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27126                  (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27127                  (len & 0xff));
27128       AdvanceIT();
27129       return;
27130     }
27131   } else {
27132     // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
27133     if (cond.IsNotNever() &&
27134         ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
27135       const SRegister& sreg = sreglist.GetFirstSRegister();
27136       unsigned len = sreglist.GetLength();
27137       EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27138               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27139               (len & 0xff));
27140       return;
27141     }
27142   }
27143   Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
27144 }
27145 
vstmdb(Condition cond,DataType dt,Register rn,WriteBack write_back,DRegisterList dreglist)27146 void Assembler::vstmdb(Condition cond,
27147                        DataType dt,
27148                        Register rn,
27149                        WriteBack write_back,
27150                        DRegisterList dreglist) {
27151   VIXL_ASSERT(AllowAssembler());
27152   CheckIT(cond);
27153   USE(dt);
27154   if (IsUsingT32()) {
27155     // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
27156     if (write_back.DoesWriteBack() &&
27157         (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27158          AllowUnpredictable())) {
27159       const DRegister& dreg = dreglist.GetFirstDRegister();
27160       unsigned len = dreglist.GetLength() * 2;
27161       EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
27162                  (len & 0xff));
27163       AdvanceIT();
27164       return;
27165     }
27166   } else {
27167     // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
27168     if (write_back.DoesWriteBack() && cond.IsNotNever() &&
27169         (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27170          AllowUnpredictable())) {
27171       const DRegister& dreg = dreglist.GetFirstDRegister();
27172       unsigned len = dreglist.GetLength() * 2;
27173       EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27174               dreg.Encode(22, 12) | (len & 0xff));
27175       return;
27176     }
27177   }
27178   Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
27179 }
27180 
vstmdb(Condition cond,DataType dt,Register rn,WriteBack write_back,SRegisterList sreglist)27181 void Assembler::vstmdb(Condition cond,
27182                        DataType dt,
27183                        Register rn,
27184                        WriteBack write_back,
27185                        SRegisterList sreglist) {
27186   VIXL_ASSERT(AllowAssembler());
27187   CheckIT(cond);
27188   USE(dt);
27189   if (IsUsingT32()) {
27190     // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
27191     if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
27192       const SRegister& sreg = sreglist.GetFirstSRegister();
27193       unsigned len = sreglist.GetLength();
27194       EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
27195                  (len & 0xff));
27196       AdvanceIT();
27197       return;
27198     }
27199   } else {
27200     // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
27201     if (write_back.DoesWriteBack() && cond.IsNotNever() &&
27202         (!rn.IsPC() || AllowUnpredictable())) {
27203       const SRegister& sreg = sreglist.GetFirstSRegister();
27204       unsigned len = sreglist.GetLength();
27205       EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27206               sreg.Encode(22, 12) | (len & 0xff));
27207       return;
27208     }
27209   }
27210   Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
27211 }
27212 
vstmia(Condition cond,DataType dt,Register rn,WriteBack write_back,DRegisterList dreglist)27213 void Assembler::vstmia(Condition cond,
27214                        DataType dt,
27215                        Register rn,
27216                        WriteBack write_back,
27217                        DRegisterList dreglist) {
27218   VIXL_ASSERT(AllowAssembler());
27219   CheckIT(cond);
27220   USE(dt);
27221   if (IsUsingT32()) {
27222     // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
27223     if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27224          AllowUnpredictable())) {
27225       const DRegister& dreg = dreglist.GetFirstDRegister();
27226       unsigned len = dreglist.GetLength() * 2;
27227       EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27228                  (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27229                  (len & 0xff));
27230       AdvanceIT();
27231       return;
27232     }
27233   } else {
27234     // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
27235     if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27236                                (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27237                               AllowUnpredictable())) {
27238       const DRegister& dreg = dreglist.GetFirstDRegister();
27239       unsigned len = dreglist.GetLength() * 2;
27240       EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27241               (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27242               (len & 0xff));
27243       return;
27244     }
27245   }
27246   Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
27247 }
27248 
vstmia(Condition cond,DataType dt,Register rn,WriteBack write_back,SRegisterList sreglist)27249 void Assembler::vstmia(Condition cond,
27250                        DataType dt,
27251                        Register rn,
27252                        WriteBack write_back,
27253                        SRegisterList sreglist) {
27254   VIXL_ASSERT(AllowAssembler());
27255   CheckIT(cond);
27256   USE(dt);
27257   if (IsUsingT32()) {
27258     // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
27259     if ((!rn.IsPC() || AllowUnpredictable())) {
27260       const SRegister& sreg = sreglist.GetFirstSRegister();
27261       unsigned len = sreglist.GetLength();
27262       EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27263                  (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27264                  (len & 0xff));
27265       AdvanceIT();
27266       return;
27267     }
27268   } else {
27269     // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
27270     if (cond.IsNotNever() &&
27271         ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
27272       const SRegister& sreg = sreglist.GetFirstSRegister();
27273       unsigned len = sreglist.GetLength();
27274       EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27275               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27276               (len & 0xff));
27277       return;
27278     }
27279   }
27280   Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
27281 }
27282 
vstr(Condition cond,DataType dt,DRegister rd,const MemOperand & operand)27283 void Assembler::vstr(Condition cond,
27284                      DataType dt,
27285                      DRegister rd,
27286                      const MemOperand& operand) {
27287   VIXL_ASSERT(AllowAssembler());
27288   CheckIT(cond);
27289   if (operand.IsImmediate()) {
27290     Register rn = operand.GetBaseRegister();
27291     int32_t offset = operand.GetOffsetImmediate();
27292     if (IsUsingT32()) {
27293       // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
27294       if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
27295           ((offset % 4) == 0) && operand.IsOffset() &&
27296           (!rn.IsPC() || AllowUnpredictable())) {
27297         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27298         uint32_t offset_ = abs(offset) >> 2;
27299         EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27300                    offset_ | (sign << 23));
27301         AdvanceIT();
27302         return;
27303       }
27304     } else {
27305       // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
27306       if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
27307           ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
27308         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27309         uint32_t offset_ = abs(offset) >> 2;
27310         EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27311                 (rn.GetCode() << 16) | offset_ | (sign << 23));
27312         return;
27313       }
27314     }
27315   }
27316   Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27317 }
27318 
vstr(Condition cond,DataType dt,SRegister rd,const MemOperand & operand)27319 void Assembler::vstr(Condition cond,
27320                      DataType dt,
27321                      SRegister rd,
27322                      const MemOperand& operand) {
27323   VIXL_ASSERT(AllowAssembler());
27324   CheckIT(cond);
27325   if (operand.IsImmediate()) {
27326     Register rn = operand.GetBaseRegister();
27327     int32_t offset = operand.GetOffsetImmediate();
27328     if (IsUsingT32()) {
27329       // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
27330       if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
27331           ((offset % 4) == 0) && operand.IsOffset() &&
27332           (!rn.IsPC() || AllowUnpredictable())) {
27333         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27334         uint32_t offset_ = abs(offset) >> 2;
27335         EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27336                    offset_ | (sign << 23));
27337         AdvanceIT();
27338         return;
27339       }
27340     } else {
27341       // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
27342       if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
27343           ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
27344         uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27345         uint32_t offset_ = abs(offset) >> 2;
27346         EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27347                 (rn.GetCode() << 16) | offset_ | (sign << 23));
27348         return;
27349       }
27350     }
27351   }
27352   Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27353 }
27354 
vsub(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)27355 void Assembler::vsub(
27356     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
27357   VIXL_ASSERT(AllowAssembler());
27358   CheckIT(cond);
27359   Dt_size_2 encoded_dt(dt);
27360   if (IsUsingT32()) {
27361     // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
27362     if (dt.Is(F32)) {
27363       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27364         EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27365                    rm.Encode(5, 0));
27366         AdvanceIT();
27367         return;
27368       }
27369     }
27370     // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
27371     if (dt.Is(F64)) {
27372       EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27373                  rm.Encode(5, 0));
27374       AdvanceIT();
27375       return;
27376     }
27377     // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27378     if (encoded_dt.IsValid()) {
27379       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27380         EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
27381                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27382         AdvanceIT();
27383         return;
27384       }
27385     }
27386   } else {
27387     // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
27388     if (dt.Is(F32)) {
27389       if (cond.Is(al)) {
27390         EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27391                 rm.Encode(5, 0));
27392         return;
27393       }
27394     }
27395     // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
27396     if (dt.Is(F64) && cond.IsNotNever()) {
27397       EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27398               rn.Encode(7, 16) | rm.Encode(5, 0));
27399       return;
27400     }
27401     // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27402     if (encoded_dt.IsValid()) {
27403       if (cond.Is(al)) {
27404         EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
27405                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27406         return;
27407       }
27408     }
27409   }
27410   Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27411 }
27412 
vsub(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)27413 void Assembler::vsub(
27414     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
27415   VIXL_ASSERT(AllowAssembler());
27416   CheckIT(cond);
27417   Dt_size_2 encoded_dt(dt);
27418   if (IsUsingT32()) {
27419     // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
27420     if (dt.Is(F32)) {
27421       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27422         EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27423                    rm.Encode(5, 0));
27424         AdvanceIT();
27425         return;
27426       }
27427     }
27428     // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27429     if (encoded_dt.IsValid()) {
27430       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27431         EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
27432                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27433         AdvanceIT();
27434         return;
27435       }
27436     }
27437   } else {
27438     // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
27439     if (dt.Is(F32)) {
27440       if (cond.Is(al)) {
27441         EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27442                 rm.Encode(5, 0));
27443         return;
27444       }
27445     }
27446     // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27447     if (encoded_dt.IsValid()) {
27448       if (cond.Is(al)) {
27449         EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
27450                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27451         return;
27452       }
27453     }
27454   }
27455   Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27456 }
27457 
vsub(Condition cond,DataType dt,SRegister rd,SRegister rn,SRegister rm)27458 void Assembler::vsub(
27459     Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
27460   VIXL_ASSERT(AllowAssembler());
27461   CheckIT(cond);
27462   if (IsUsingT32()) {
27463     // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
27464     if (dt.Is(F32)) {
27465       EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27466                  rm.Encode(5, 0));
27467       AdvanceIT();
27468       return;
27469     }
27470   } else {
27471     // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
27472     if (dt.Is(F32) && cond.IsNotNever()) {
27473       EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27474               rn.Encode(7, 16) | rm.Encode(5, 0));
27475       return;
27476     }
27477   }
27478   Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27479 }
27480 
vsubhn(Condition cond,DataType dt,DRegister rd,QRegister rn,QRegister rm)27481 void Assembler::vsubhn(
27482     Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
27483   VIXL_ASSERT(AllowAssembler());
27484   CheckIT(cond);
27485   Dt_size_3 encoded_dt(dt);
27486   if (IsUsingT32()) {
27487     // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
27488     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27489       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27490         EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
27491                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27492         AdvanceIT();
27493         return;
27494       }
27495     }
27496   } else {
27497     // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
27498     if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27499       if (cond.Is(al)) {
27500         EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
27501                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27502         return;
27503       }
27504     }
27505   }
27506   Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
27507 }
27508 
vsubl(Condition cond,DataType dt,QRegister rd,DRegister rn,DRegister rm)27509 void Assembler::vsubl(
27510     Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
27511   VIXL_ASSERT(AllowAssembler());
27512   CheckIT(cond);
27513   Dt_U_size_1 encoded_dt(dt);
27514   if (IsUsingT32()) {
27515     // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
27516     if (encoded_dt.IsValid()) {
27517       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27518         EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27519                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27520                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27521         AdvanceIT();
27522         return;
27523       }
27524     }
27525   } else {
27526     // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
27527     if (encoded_dt.IsValid()) {
27528       if (cond.Is(al)) {
27529         EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27530                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27531                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27532         return;
27533       }
27534     }
27535   }
27536   Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
27537 }
27538 
vsubw(Condition cond,DataType dt,QRegister rd,QRegister rn,DRegister rm)27539 void Assembler::vsubw(
27540     Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
27541   VIXL_ASSERT(AllowAssembler());
27542   CheckIT(cond);
27543   Dt_U_size_1 encoded_dt(dt);
27544   if (IsUsingT32()) {
27545     // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
27546     if (encoded_dt.IsValid()) {
27547       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27548         EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27549                    ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27550                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27551         AdvanceIT();
27552         return;
27553       }
27554     }
27555   } else {
27556     // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
27557     if (encoded_dt.IsValid()) {
27558       if (cond.Is(al)) {
27559         EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27560                 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27561                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27562         return;
27563       }
27564     }
27565   }
27566   Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
27567 }
27568 
vswp(Condition cond,DataType dt,DRegister rd,DRegister rm)27569 void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27570   VIXL_ASSERT(AllowAssembler());
27571   CheckIT(cond);
27572   USE(dt);
27573   if (IsUsingT32()) {
27574     // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
27575     if (cond.Is(al) || AllowStronglyDiscouraged()) {
27576       EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27577       AdvanceIT();
27578       return;
27579     }
27580   } else {
27581     // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
27582     if (cond.Is(al)) {
27583       EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27584       return;
27585     }
27586   }
27587   Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27588 }
27589 
vswp(Condition cond,DataType dt,QRegister rd,QRegister rm)27590 void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27591   VIXL_ASSERT(AllowAssembler());
27592   CheckIT(cond);
27593   USE(dt);
27594   if (IsUsingT32()) {
27595     // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
27596     if (cond.Is(al) || AllowStronglyDiscouraged()) {
27597       EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27598       AdvanceIT();
27599       return;
27600     }
27601   } else {
27602     // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
27603     if (cond.Is(al)) {
27604       EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27605       return;
27606     }
27607   }
27608   Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27609 }
27610 
vtbl(Condition cond,DataType dt,DRegister rd,const NeonRegisterList & nreglist,DRegister rm)27611 void Assembler::vtbl(Condition cond,
27612                      DataType dt,
27613                      DRegister rd,
27614                      const NeonRegisterList& nreglist,
27615                      DRegister rm) {
27616   VIXL_ASSERT(AllowAssembler());
27617   CheckIT(cond);
27618   if (IsUsingT32()) {
27619     // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27620     if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27621         (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27622       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27623         const DRegister& first = nreglist.GetFirstDRegister();
27624         uint32_t len_encoding = nreglist.GetLength() - 1;
27625         EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27626                    (len_encoding << 8) | rm.Encode(5, 0));
27627         AdvanceIT();
27628         return;
27629       }
27630     }
27631   } else {
27632     // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27633     if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27634         (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27635       if (cond.Is(al)) {
27636         const DRegister& first = nreglist.GetFirstDRegister();
27637         uint32_t len_encoding = nreglist.GetLength() - 1;
27638         EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27639                 (len_encoding << 8) | rm.Encode(5, 0));
27640         return;
27641       }
27642     }
27643   }
27644   Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
27645 }
27646 
vtbx(Condition cond,DataType dt,DRegister rd,const NeonRegisterList & nreglist,DRegister rm)27647 void Assembler::vtbx(Condition cond,
27648                      DataType dt,
27649                      DRegister rd,
27650                      const NeonRegisterList& nreglist,
27651                      DRegister rm) {
27652   VIXL_ASSERT(AllowAssembler());
27653   CheckIT(cond);
27654   if (IsUsingT32()) {
27655     // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27656     if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27657         (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27658       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27659         const DRegister& first = nreglist.GetFirstDRegister();
27660         uint32_t len_encoding = nreglist.GetLength() - 1;
27661         EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27662                    (len_encoding << 8) | rm.Encode(5, 0));
27663         AdvanceIT();
27664         return;
27665       }
27666     }
27667   } else {
27668     // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27669     if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27670         (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27671       if (cond.Is(al)) {
27672         const DRegister& first = nreglist.GetFirstDRegister();
27673         uint32_t len_encoding = nreglist.GetLength() - 1;
27674         EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27675                 (len_encoding << 8) | rm.Encode(5, 0));
27676         return;
27677       }
27678     }
27679   }
27680   Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
27681 }
27682 
vtrn(Condition cond,DataType dt,DRegister rd,DRegister rm)27683 void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27684   VIXL_ASSERT(AllowAssembler());
27685   CheckIT(cond);
27686   Dt_size_7 encoded_dt(dt);
27687   if (IsUsingT32()) {
27688     // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27689     if (encoded_dt.IsValid()) {
27690       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27691         EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
27692                    rd.Encode(22, 12) | rm.Encode(5, 0));
27693         AdvanceIT();
27694         return;
27695       }
27696     }
27697   } else {
27698     // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27699     if (encoded_dt.IsValid()) {
27700       if (cond.Is(al)) {
27701         EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
27702                 rd.Encode(22, 12) | rm.Encode(5, 0));
27703         return;
27704       }
27705     }
27706   }
27707   Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27708 }
27709 
vtrn(Condition cond,DataType dt,QRegister rd,QRegister rm)27710 void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27711   VIXL_ASSERT(AllowAssembler());
27712   CheckIT(cond);
27713   Dt_size_7 encoded_dt(dt);
27714   if (IsUsingT32()) {
27715     // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27716     if (encoded_dt.IsValid()) {
27717       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27718         EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
27719                    rd.Encode(22, 12) | rm.Encode(5, 0));
27720         AdvanceIT();
27721         return;
27722       }
27723     }
27724   } else {
27725     // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27726     if (encoded_dt.IsValid()) {
27727       if (cond.Is(al)) {
27728         EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
27729                 rd.Encode(22, 12) | rm.Encode(5, 0));
27730         return;
27731       }
27732     }
27733   }
27734   Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27735 }
27736 
vtst(Condition cond,DataType dt,DRegister rd,DRegister rn,DRegister rm)27737 void Assembler::vtst(
27738     Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
27739   VIXL_ASSERT(AllowAssembler());
27740   CheckIT(cond);
27741   Dt_size_7 encoded_dt(dt);
27742   if (IsUsingT32()) {
27743     // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27744     if (encoded_dt.IsValid()) {
27745       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27746         EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
27747                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27748         AdvanceIT();
27749         return;
27750       }
27751     }
27752   } else {
27753     // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27754     if (encoded_dt.IsValid()) {
27755       if (cond.Is(al)) {
27756         EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
27757                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27758         return;
27759       }
27760     }
27761   }
27762   Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27763 }
27764 
vtst(Condition cond,DataType dt,QRegister rd,QRegister rn,QRegister rm)27765 void Assembler::vtst(
27766     Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
27767   VIXL_ASSERT(AllowAssembler());
27768   CheckIT(cond);
27769   Dt_size_7 encoded_dt(dt);
27770   if (IsUsingT32()) {
27771     // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27772     if (encoded_dt.IsValid()) {
27773       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27774         EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
27775                    rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27776         AdvanceIT();
27777         return;
27778       }
27779     }
27780   } else {
27781     // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27782     if (encoded_dt.IsValid()) {
27783       if (cond.Is(al)) {
27784         EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
27785                 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27786         return;
27787       }
27788     }
27789   }
27790   Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27791 }
27792 
vuzp(Condition cond,DataType dt,DRegister rd,DRegister rm)27793 void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27794   VIXL_ASSERT(AllowAssembler());
27795   CheckIT(cond);
27796   Dt_size_15 encoded_dt(dt);
27797   if (IsUsingT32()) {
27798     // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27799     if (encoded_dt.IsValid()) {
27800       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27801         EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
27802                    rd.Encode(22, 12) | rm.Encode(5, 0));
27803         AdvanceIT();
27804         return;
27805       }
27806     }
27807     // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27808     if (dt.Is(Untyped32)) {
27809       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27810         EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27811         AdvanceIT();
27812         return;
27813       }
27814     }
27815   } else {
27816     // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27817     if (encoded_dt.IsValid()) {
27818       if (cond.Is(al)) {
27819         EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
27820                 rd.Encode(22, 12) | rm.Encode(5, 0));
27821         return;
27822       }
27823     }
27824     // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27825     if (dt.Is(Untyped32)) {
27826       if (cond.Is(al)) {
27827         EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27828         return;
27829       }
27830     }
27831   }
27832   Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27833 }
27834 
vuzp(Condition cond,DataType dt,QRegister rd,QRegister rm)27835 void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27836   VIXL_ASSERT(AllowAssembler());
27837   CheckIT(cond);
27838   Dt_size_7 encoded_dt(dt);
27839   if (IsUsingT32()) {
27840     // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27841     if (encoded_dt.IsValid()) {
27842       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27843         EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
27844                    rd.Encode(22, 12) | rm.Encode(5, 0));
27845         AdvanceIT();
27846         return;
27847       }
27848     }
27849   } else {
27850     // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27851     if (encoded_dt.IsValid()) {
27852       if (cond.Is(al)) {
27853         EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
27854                 rd.Encode(22, 12) | rm.Encode(5, 0));
27855         return;
27856       }
27857     }
27858   }
27859   Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27860 }
27861 
vzip(Condition cond,DataType dt,DRegister rd,DRegister rm)27862 void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27863   VIXL_ASSERT(AllowAssembler());
27864   CheckIT(cond);
27865   Dt_size_15 encoded_dt(dt);
27866   if (IsUsingT32()) {
27867     // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27868     if (encoded_dt.IsValid()) {
27869       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27870         EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
27871                    rd.Encode(22, 12) | rm.Encode(5, 0));
27872         AdvanceIT();
27873         return;
27874       }
27875     }
27876     // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27877     if (dt.Is(Untyped32)) {
27878       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27879         EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27880         AdvanceIT();
27881         return;
27882       }
27883     }
27884   } else {
27885     // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27886     if (encoded_dt.IsValid()) {
27887       if (cond.Is(al)) {
27888         EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
27889                 rd.Encode(22, 12) | rm.Encode(5, 0));
27890         return;
27891       }
27892     }
27893     // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27894     if (dt.Is(Untyped32)) {
27895       if (cond.Is(al)) {
27896         EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27897         return;
27898       }
27899     }
27900   }
27901   Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27902 }
27903 
vzip(Condition cond,DataType dt,QRegister rd,QRegister rm)27904 void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27905   VIXL_ASSERT(AllowAssembler());
27906   CheckIT(cond);
27907   Dt_size_7 encoded_dt(dt);
27908   if (IsUsingT32()) {
27909     // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27910     if (encoded_dt.IsValid()) {
27911       if (cond.Is(al) || AllowStronglyDiscouraged()) {
27912         EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
27913                    rd.Encode(22, 12) | rm.Encode(5, 0));
27914         AdvanceIT();
27915         return;
27916       }
27917     }
27918   } else {
27919     // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27920     if (encoded_dt.IsValid()) {
27921       if (cond.Is(al)) {
27922         EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
27923                 rd.Encode(22, 12) | rm.Encode(5, 0));
27924         return;
27925       }
27926     }
27927   }
27928   Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27929 }
27930 
yield(Condition cond,EncodingSize size)27931 void Assembler::yield(Condition cond, EncodingSize size) {
27932   VIXL_ASSERT(AllowAssembler());
27933   CheckIT(cond);
27934   if (IsUsingT32()) {
27935     // YIELD{<c>}{<q>} ; T1
27936     if (!size.IsWide()) {
27937       EmitT32_16(0xbf10);
27938       AdvanceIT();
27939       return;
27940     }
27941     // YIELD{<c>}.W ; T2
27942     if (!size.IsNarrow()) {
27943       EmitT32_32(0xf3af8001U);
27944       AdvanceIT();
27945       return;
27946     }
27947   } else {
27948     // YIELD{<c>}{<q>} ; A1
27949     if (cond.IsNotNever()) {
27950       EmitA32(0x0320f001U | (cond.GetCondition() << 28));
27951       return;
27952     }
27953   }
27954   Delegate(kYield, &Assembler::yield, cond, size);
27955 }
27956 // End of generated code.
27957 
27958 }  // namespace aarch32
27959 }  // namespace vixl
27960