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
27extern "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
43namespace vixl {
44namespace aarch32 {
45
46void Assembler::EmitT32_16(uint16_t instr) {
47  VIXL_ASSERT(buffer_.Is16bitAligned());
48  buffer_.Emit16(instr);
49}
50
51
52void 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
59void Assembler::EmitA32(uint32_t instr) {
60  VIXL_ASSERT(buffer_.Is32bitAligned());
61  buffer_.Emit32(instr);
62}
63
64
65#ifdef VIXL_DEBUG
66void 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
80void Assembler::BindHelper(Label* label) {
81  VIXL_ASSERT(!label->IsBound());
82  label->SetLocation(this, GetCursorOffset());
83  label->MarkBound();
84}
85
86uint32_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.
100class Dt_L_imm6_1 : public EncodingValue {
101  uint32_t type_;
102
103 public:
104  explicit Dt_L_imm6_1(DataType dt);
105  uint32_t GetTypeEncodingValue() const { return type_; }
106};
107
108Dt_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
149class Dt_L_imm6_2 : public EncodingValue {
150  uint32_t type_;
151
152 public:
153  explicit Dt_L_imm6_2(DataType dt);
154  uint32_t GetTypeEncodingValue() const { return type_; }
155};
156
157Dt_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
182class Dt_L_imm6_3 : public EncodingValue {
183 public:
184  explicit Dt_L_imm6_3(DataType dt);
185};
186
187Dt_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
206class Dt_L_imm6_4 : public EncodingValue {
207 public:
208  explicit Dt_L_imm6_4(DataType dt);
209};
210
211Dt_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
230class Dt_imm6_1 : public EncodingValue {
231  uint32_t type_;
232
233 public:
234  explicit Dt_imm6_1(DataType dt);
235  uint32_t GetTypeEncodingValue() const { return type_; }
236};
237
238Dt_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
271class Dt_imm6_2 : public EncodingValue {
272  uint32_t type_;
273
274 public:
275  explicit Dt_imm6_2(DataType dt);
276  uint32_t GetTypeEncodingValue() const { return type_; }
277};
278
279Dt_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
300class Dt_imm6_3 : public EncodingValue {
301 public:
302  explicit Dt_imm6_3(DataType dt);
303};
304
305Dt_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
321class Dt_imm6_4 : public EncodingValue {
322  uint32_t type_;
323
324 public:
325  explicit Dt_imm6_4(DataType dt);
326  uint32_t GetTypeEncodingValue() const { return type_; }
327};
328
329Dt_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
362class Dt_op_U_size_1 : public EncodingValue {
363 public:
364  explicit Dt_op_U_size_1(DataType dt);
365};
366
367Dt_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
398class Dt_op_size_1 : public EncodingValue {
399 public:
400  explicit Dt_op_size_1(DataType dt);
401};
402
403Dt_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
422class Dt_op_size_2 : public EncodingValue {
423 public:
424  explicit Dt_op_size_2(DataType dt);
425};
426
427Dt_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
452class Dt_op_size_3 : public EncodingValue {
453 public:
454  explicit Dt_op_size_3(DataType dt);
455};
456
457Dt_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
482class Dt_U_imm3H_1 : public EncodingValue {
483 public:
484  explicit Dt_U_imm3H_1(DataType dt);
485};
486
487Dt_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
512class Dt_U_opc1_opc2_1 : public EncodingValue {
513 public:
514  explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
515};
516
517Dt_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
560class Dt_opc1_opc2_1 : public EncodingValue {
561 public:
562  explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
563};
564
565Dt_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
596class Dt_imm4_1 : public EncodingValue {
597 public:
598  explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
599};
600
601Dt_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
626class Dt_B_E_1 : public EncodingValue {
627 public:
628  explicit Dt_B_E_1(DataType dt);
629};
630
631Dt_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
647class Dt_op_1 : public EncodingValue {
648 public:
649  Dt_op_1(DataType dt1, DataType dt2);
650};
651
652Dt_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
671class Dt_op_2 : public EncodingValue {
672 public:
673  explicit Dt_op_2(DataType dt);
674};
675
676Dt_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
689class Dt_op_3 : public EncodingValue {
690 public:
691  explicit Dt_op_3(DataType dt);
692};
693
694Dt_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
707class Dt_U_sx_1 : public EncodingValue {
708 public:
709  explicit Dt_U_sx_1(DataType dt);
710};
711
712Dt_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
731class Dt_op_U_1 : public EncodingValue {
732 public:
733  Dt_op_U_1(DataType dt1, DataType dt2);
734};
735
736Dt_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
755class Dt_sz_1 : public EncodingValue {
756 public:
757  explicit Dt_sz_1(DataType dt);
758};
759
760Dt_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
770class Dt_F_size_1 : public EncodingValue {
771 public:
772  explicit Dt_F_size_1(DataType dt);
773};
774
775Dt_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
794class Dt_F_size_2 : public EncodingValue {
795 public:
796  explicit Dt_F_size_2(DataType dt);
797};
798
799Dt_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
818class Dt_F_size_3 : public EncodingValue {
819 public:
820  explicit Dt_F_size_3(DataType dt);
821};
822
823Dt_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
839class Dt_F_size_4 : public EncodingValue {
840 public:
841  explicit Dt_F_size_4(DataType dt);
842};
843
844Dt_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
857class Dt_U_size_1 : public EncodingValue {
858 public:
859  explicit Dt_U_size_1(DataType dt);
860};
861
862Dt_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
887class Dt_U_size_2 : public EncodingValue {
888 public:
889  explicit Dt_U_size_2(DataType dt);
890};
891
892Dt_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
911class Dt_U_size_3 : public EncodingValue {
912 public:
913  explicit Dt_U_size_3(DataType dt);
914};
915
916Dt_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
947class Dt_size_1 : public EncodingValue {
948 public:
949  explicit Dt_size_1(DataType dt);
950};
951
952Dt_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
962class Dt_size_2 : public EncodingValue {
963 public:
964  explicit Dt_size_2(DataType dt);
965};
966
967Dt_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
986class Dt_size_3 : public EncodingValue {
987 public:
988  explicit Dt_size_3(DataType dt);
989};
990
991Dt_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
1007class Dt_size_4 : public EncodingValue {
1008 public:
1009  explicit Dt_size_4(DataType dt);
1010};
1011
1012Dt_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
1028class Dt_size_5 : public EncodingValue {
1029 public:
1030  explicit Dt_size_5(DataType dt);
1031};
1032
1033Dt_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
1049class Dt_size_6 : public EncodingValue {
1050 public:
1051  explicit Dt_size_6(DataType dt);
1052};
1053
1054Dt_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
1073class Dt_size_7 : public EncodingValue {
1074 public:
1075  explicit Dt_size_7(DataType dt);
1076};
1077
1078Dt_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
1094class Dt_size_8 : public EncodingValue {
1095 public:
1096  Dt_size_8(DataType dt, Alignment align);
1097};
1098
1099Dt_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
1119class Dt_size_9 : public EncodingValue {
1120  uint32_t type_;
1121
1122 public:
1123  explicit Dt_size_9(DataType dt);
1124  uint32_t GetTypeEncodingValue() const { return type_; }
1125};
1126
1127Dt_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
1148class Dt_size_10 : public EncodingValue {
1149 public:
1150  explicit Dt_size_10(DataType dt);
1151};
1152
1153Dt_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
1175class Dt_size_11 : public EncodingValue {
1176  uint32_t type_;
1177
1178 public:
1179  explicit Dt_size_11(DataType dt);
1180  uint32_t GetTypeEncodingValue() const { return type_; }
1181};
1182
1183Dt_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
1208class Dt_size_12 : public EncodingValue {
1209  uint32_t type_;
1210
1211 public:
1212  explicit Dt_size_12(DataType dt);
1213  uint32_t GetTypeEncodingValue() const { return type_; }
1214};
1215
1216Dt_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
1249class Dt_size_13 : public EncodingValue {
1250 public:
1251  explicit Dt_size_13(DataType dt);
1252};
1253
1254Dt_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
1267class Dt_size_14 : public EncodingValue {
1268 public:
1269  explicit Dt_size_14(DataType dt);
1270};
1271
1272Dt_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
1288class Dt_size_15 : public EncodingValue {
1289 public:
1290  explicit Dt_size_15(DataType dt);
1291};
1292
1293Dt_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
1306class Dt_size_16 : public EncodingValue {
1307 public:
1308  explicit Dt_size_16(DataType dt);
1309};
1310
1311Dt_size_16::Dt_size_16(DataType dt) {
1312  switch (dt.GetValue()) {
1313    case I8:
1314      SetEncodingValue(0x0);
1315      break;
1316    case I16:
1317      SetEncodingValue(0x1);
1318      break;
1319    case I32:
1320      SetEncodingValue(0x2);
1321      break;
1322    default:
1323      break;
1324  }
1325}
1326
1327class Index_1 : public EncodingValue {
1328 public:
1329  Index_1(const NeonRegisterList& nreglist, DataType dt);
1330};
1331
1332Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1333  switch (dt.GetValue()) {
1334    case Untyped8: {
1335      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1336        return;
1337      }
1338      uint32_t value = nreglist.GetTransferLane() << 1;
1339      if (!nreglist.IsSingleSpaced()) return;
1340      SetEncodingValue(value);
1341      break;
1342    }
1343    case Untyped16: {
1344      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1345        return;
1346      }
1347      uint32_t value = nreglist.GetTransferLane() << 2;
1348      if (nreglist.IsDoubleSpaced()) value |= 2;
1349      SetEncodingValue(value);
1350      break;
1351    }
1352    case Untyped32: {
1353      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1354        return;
1355      }
1356      uint32_t value = nreglist.GetTransferLane() << 3;
1357      if (nreglist.IsDoubleSpaced()) value |= 4;
1358      SetEncodingValue(value);
1359      break;
1360    }
1361    default:
1362      break;
1363  }
1364}
1365
1366class Align_index_align_1 : public EncodingValue {
1367 public:
1368  Align_index_align_1(Alignment align,
1369                      const NeonRegisterList& nreglist,
1370                      DataType dt);
1371};
1372
1373Align_index_align_1::Align_index_align_1(Alignment align,
1374                                         const NeonRegisterList& nreglist,
1375                                         DataType dt) {
1376  switch (dt.GetValue()) {
1377    case Untyped8: {
1378      uint32_t value;
1379      if (align.GetType() == kNoAlignment) {
1380        value = 0;
1381      } else {
1382        return;
1383      }
1384      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1385        return;
1386      }
1387      value |= nreglist.GetTransferLane() << 1;
1388      SetEncodingValue(value);
1389      break;
1390    }
1391    case Untyped16: {
1392      uint32_t value;
1393      if (align.GetType() == k16BitAlign) {
1394        value = 1;
1395      } else if (align.GetType() == kNoAlignment) {
1396        value = 0;
1397      } else {
1398        return;
1399      }
1400      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1401        return;
1402      }
1403      value |= nreglist.GetTransferLane() << 2;
1404      SetEncodingValue(value);
1405      break;
1406    }
1407    case Untyped32: {
1408      uint32_t value;
1409      if (align.GetType() == k32BitAlign) {
1410        value = 3;
1411      } else if (align.GetType() == kNoAlignment) {
1412        value = 0;
1413      } else {
1414        return;
1415      }
1416      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1417        return;
1418      }
1419      value |= nreglist.GetTransferLane() << 3;
1420      SetEncodingValue(value);
1421      break;
1422    }
1423    default:
1424      break;
1425  }
1426}
1427
1428class Align_index_align_2 : public EncodingValue {
1429 public:
1430  Align_index_align_2(Alignment align,
1431                      const NeonRegisterList& nreglist,
1432                      DataType dt);
1433};
1434
1435Align_index_align_2::Align_index_align_2(Alignment align,
1436                                         const NeonRegisterList& nreglist,
1437                                         DataType dt) {
1438  switch (dt.GetValue()) {
1439    case Untyped8: {
1440      uint32_t value;
1441      if (align.GetType() == k16BitAlign) {
1442        value = 1;
1443      } else if (align.GetType() == kNoAlignment) {
1444        value = 0;
1445      } else {
1446        return;
1447      }
1448      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1449        return;
1450      }
1451      value |= nreglist.GetTransferLane() << 1;
1452      if (!nreglist.IsSingleSpaced()) return;
1453      SetEncodingValue(value);
1454      break;
1455    }
1456    case Untyped16: {
1457      uint32_t value;
1458      if (align.GetType() == k32BitAlign) {
1459        value = 1;
1460      } else if (align.GetType() == kNoAlignment) {
1461        value = 0;
1462      } else {
1463        return;
1464      }
1465      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1466        return;
1467      }
1468      value |= nreglist.GetTransferLane() << 2;
1469      if (nreglist.IsDoubleSpaced()) value |= 2;
1470      SetEncodingValue(value);
1471      break;
1472    }
1473    case Untyped32: {
1474      uint32_t value;
1475      if (align.GetType() == k64BitAlign) {
1476        value = 1;
1477      } else if (align.GetType() == kNoAlignment) {
1478        value = 0;
1479      } else {
1480        return;
1481      }
1482      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1483        return;
1484      }
1485      value |= nreglist.GetTransferLane() << 3;
1486      if (nreglist.IsDoubleSpaced()) value |= 4;
1487      SetEncodingValue(value);
1488      break;
1489    }
1490    default:
1491      break;
1492  }
1493}
1494
1495class Align_index_align_3 : public EncodingValue {
1496 public:
1497  Align_index_align_3(Alignment align,
1498                      const NeonRegisterList& nreglist,
1499                      DataType dt);
1500};
1501
1502Align_index_align_3::Align_index_align_3(Alignment align,
1503                                         const NeonRegisterList& nreglist,
1504                                         DataType dt) {
1505  switch (dt.GetValue()) {
1506    case Untyped8: {
1507      uint32_t value;
1508      if (align.GetType() == k32BitAlign) {
1509        value = 1;
1510      } else if (align.GetType() == kNoAlignment) {
1511        value = 0;
1512      } else {
1513        return;
1514      }
1515      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1516        return;
1517      }
1518      value |= nreglist.GetTransferLane() << 1;
1519      if (!nreglist.IsSingleSpaced()) return;
1520      SetEncodingValue(value);
1521      break;
1522    }
1523    case Untyped16: {
1524      uint32_t value;
1525      if (align.GetType() == k64BitAlign) {
1526        value = 1;
1527      } else if (align.GetType() == kNoAlignment) {
1528        value = 0;
1529      } else {
1530        return;
1531      }
1532      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1533        return;
1534      }
1535      value |= nreglist.GetTransferLane() << 2;
1536      if (nreglist.IsDoubleSpaced()) value |= 2;
1537      SetEncodingValue(value);
1538      break;
1539    }
1540    case Untyped32: {
1541      uint32_t value;
1542      if (align.GetType() == k64BitAlign) {
1543        value = 1;
1544      } else if (align.GetType() == k128BitAlign) {
1545        value = 2;
1546      } else if (align.GetType() == kNoAlignment) {
1547        value = 0;
1548      } else {
1549        return;
1550      }
1551      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1552        return;
1553      }
1554      value |= nreglist.GetTransferLane() << 3;
1555      if (nreglist.IsDoubleSpaced()) value |= 4;
1556      SetEncodingValue(value);
1557      break;
1558    }
1559    default:
1560      break;
1561  }
1562}
1563
1564class Align_a_1 : public EncodingValue {
1565 public:
1566  Align_a_1(Alignment align, DataType dt);
1567};
1568
1569Align_a_1::Align_a_1(Alignment align, DataType dt) {
1570  switch (align.GetType()) {
1571    case k16BitAlign:
1572      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1573      break;
1574    case k32BitAlign:
1575      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1576      break;
1577    case kNoAlignment:
1578      SetEncodingValue(0x0);
1579      break;
1580    default:
1581      break;
1582  }
1583}
1584
1585class Align_a_2 : public EncodingValue {
1586 public:
1587  Align_a_2(Alignment align, DataType dt);
1588};
1589
1590Align_a_2::Align_a_2(Alignment align, DataType dt) {
1591  switch (align.GetType()) {
1592    case k16BitAlign:
1593      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1594      break;
1595    case k32BitAlign:
1596      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1597      break;
1598    case k64BitAlign:
1599      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1600      break;
1601    case kNoAlignment:
1602      SetEncodingValue(0x0);
1603      break;
1604    default:
1605      break;
1606  }
1607}
1608
1609class Align_a_3 : public EncodingValue {
1610 public:
1611  Align_a_3(Alignment align, DataType dt);
1612};
1613
1614Align_a_3::Align_a_3(Alignment align, DataType dt) {
1615  switch (align.GetType()) {
1616    case k32BitAlign:
1617      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1618      break;
1619    case k64BitAlign:
1620      if (dt.Is(Untyped16))
1621        SetEncodingValue(0x1);
1622      else if (dt.Is(Untyped32))
1623        SetEncodingValue(0x1);
1624      break;
1625    case k128BitAlign:
1626      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1627      break;
1628    case kNoAlignment:
1629      SetEncodingValue(0x0);
1630      break;
1631    default:
1632      break;
1633  }
1634}
1635
1636class Align_align_1 : public EncodingValue {
1637 public:
1638  Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1639};
1640
1641Align_align_1::Align_align_1(Alignment align,
1642                             const NeonRegisterList& nreglist) {
1643  switch (align.GetType()) {
1644    case k64BitAlign:
1645      SetEncodingValue(0x1);
1646      break;
1647    case k128BitAlign:
1648      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1649        SetEncodingValue(0x2);
1650      break;
1651    case k256BitAlign:
1652      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1653        SetEncodingValue(0x3);
1654      break;
1655    case kNoAlignment:
1656      SetEncodingValue(0x0);
1657      break;
1658    default:
1659      break;
1660  }
1661}
1662
1663class Align_align_2 : public EncodingValue {
1664 public:
1665  Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1666};
1667
1668Align_align_2::Align_align_2(Alignment align,
1669                             const NeonRegisterList& nreglist) {
1670  switch (align.GetType()) {
1671    case k64BitAlign:
1672      SetEncodingValue(0x1);
1673      break;
1674    case k128BitAlign:
1675      SetEncodingValue(0x2);
1676      break;
1677    case k256BitAlign:
1678      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1679      break;
1680    case kNoAlignment:
1681      SetEncodingValue(0x0);
1682      break;
1683    default:
1684      break;
1685  }
1686}
1687
1688class Align_align_3 : public EncodingValue {
1689 public:
1690  explicit Align_align_3(Alignment align);
1691};
1692
1693Align_align_3::Align_align_3(Alignment align) {
1694  switch (align.GetType()) {
1695    case k64BitAlign:
1696      SetEncodingValue(0x1);
1697      break;
1698    case kNoAlignment:
1699      SetEncodingValue(0x0);
1700      break;
1701    default:
1702      break;
1703  }
1704}
1705
1706class Align_align_4 : public EncodingValue {
1707 public:
1708  explicit Align_align_4(Alignment align);
1709};
1710
1711Align_align_4::Align_align_4(Alignment align) {
1712  switch (align.GetType()) {
1713    case k64BitAlign:
1714      SetEncodingValue(0x1);
1715      break;
1716    case k128BitAlign:
1717      SetEncodingValue(0x2);
1718      break;
1719    case k256BitAlign:
1720      SetEncodingValue(0x3);
1721      break;
1722    case kNoAlignment:
1723      SetEncodingValue(0x0);
1724      break;
1725    default:
1726      break;
1727  }
1728}
1729
1730class Align_align_5 : public EncodingValue {
1731 public:
1732  Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1733};
1734
1735Align_align_5::Align_align_5(Alignment align,
1736                             const NeonRegisterList& nreglist) {
1737  switch (align.GetType()) {
1738    case k64BitAlign:
1739      SetEncodingValue(0x1);
1740      break;
1741    case k128BitAlign:
1742      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1743        SetEncodingValue(0x2);
1744      break;
1745    case k256BitAlign:
1746      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1747      break;
1748    case kNoAlignment:
1749      SetEncodingValue(0x0);
1750      break;
1751    default:
1752      break;
1753  }
1754}
1755
1756
1757// CBNZ{<q>} <Rn>, <label> ; T1
1758// CBZ{<q>} <Rn>, <label> ; T1
1759static const struct ReferenceInfo kT16CbzInfo =
1760    {k16BitT32InstructionSizeInBytes,
1761     0,    // Min offset.
1762     126,  // Max offset.
1763     2,    // Alignment.
1764     ReferenceInfo::kDontAlignPc};
1765
1766
1767// B<c>{<q>} <label> ; T1
1768static const struct ReferenceInfo kT16ConditionalBranchInfo =
1769    {k16BitT32InstructionSizeInBytes,
1770     -256,  // Min offset.
1771     254,   // Max offset.
1772     2,     // Alignment.
1773     ReferenceInfo::kDontAlignPc};
1774
1775
1776// ADR{<c>}{<q>} <Rd>, <label> ; T1
1777// LDR{<c>}{<q>} <Rt>, <label> ; T1
1778static const struct ReferenceInfo kT16DataInfo =
1779    {k16BitT32InstructionSizeInBytes,
1780     0,     // Min offset.
1781     1020,  // Max offset.
1782     4,     // Alignment.
1783     ReferenceInfo::kAlignPc};
1784
1785
1786// B{<c>}{<q>} <label> ; T2
1787static const struct ReferenceInfo kT16BranchInfo =
1788    {k16BitT32InstructionSizeInBytes,
1789     -2048,  // Min offset.
1790     2046,   // Max offset.
1791     2,      // Alignment.
1792     ReferenceInfo::kDontAlignPc};
1793
1794
1795// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
1796// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
1797// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
1798static const struct ReferenceInfo kT32DataInfo =
1799    {k32BitT32InstructionSizeInBytes,
1800     -1020,  // Min offset.
1801     1020,   // Max offset.
1802     4,      // Alignment.
1803     ReferenceInfo::kAlignPc};
1804
1805
1806// ADR{<c>}{<q>} <Rd>, <label> ; T3
1807// LDR{<c>}{<q>} <Rt>, <label> ; T2
1808// LDRB{<c>}{<q>} <Rt>, <label> ; T1
1809// LDRH{<c>}{<q>} <Rt>, <label> ; T1
1810// LDRSB{<c>}{<q>} <Rt>, <label> ; T1
1811// LDRSH{<c>}{<q>} <Rt>, <label> ; T1
1812// PLD{<c>}{<q>} <label> ; T1
1813// PLI{<c>}{<q>} <label> ; T3
1814static const struct ReferenceInfo kT32FarDataInfo =
1815    {k32BitT32InstructionSizeInBytes,
1816     -4095,  // Min offset.
1817     4095,   // Max offset.
1818     1,      // Alignment.
1819     ReferenceInfo::kAlignPc};
1820
1821
1822// B<c>{<q>} <label> ; T3
1823static const struct ReferenceInfo kT32ConditionalBranchInfo =
1824    {k32BitT32InstructionSizeInBytes,
1825     -1048576,  // Min offset.
1826     1048574,   // Max offset.
1827     2,         // Alignment.
1828     ReferenceInfo::kDontAlignPc};
1829
1830
1831// B{<c>}{<q>} <label> ; T4
1832// BL{<c>}{<q>} <label> ; T1
1833static const struct ReferenceInfo kT32BranchInfo =
1834    {k32BitT32InstructionSizeInBytes,
1835     -16777216,  // Min offset.
1836     16777214,   // Max offset.
1837     2,          // Alignment.
1838     ReferenceInfo::kDontAlignPc};
1839
1840
1841// BLX{<c>}{<q>} <label> ; T2
1842static const struct ReferenceInfo kT32BlxInfo =
1843    {k32BitT32InstructionSizeInBytes,
1844     -16777216,  // Min offset.
1845     16777212,   // Max offset.
1846     4,          // Alignment.
1847     ReferenceInfo::kAlignPc};
1848
1849
1850// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
1851// LDRH{<c>}{<q>} <Rt>, <label> ; A1
1852// LDRSB{<c>}{<q>} <Rt>, <label> ; A1
1853// LDRSH{<c>}{<q>} <Rt>, <label> ; A1
1854static const struct ReferenceInfo kA32VeryNearDataInfo =
1855    {kA32InstructionSizeInBytes,
1856     -255,  // Min offset.
1857     255,   // Max offset.
1858     1,     // Alignment.
1859     ReferenceInfo::kAlignPc};
1860
1861
1862// ADR{<c>}{<q>} <Rd>, <label> ; A1
1863static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes,
1864                                                 -256,  // Min offset.
1865                                                 256,   // Max offset.
1866                                                 1,     // Alignment.
1867                                                 ReferenceInfo::kAlignPc};
1868
1869
1870// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
1871// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
1872static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes,
1873                                                  -1020,  // Min offset.
1874                                                  1020,   // Max offset.
1875                                                  4,      // Alignment.
1876                                                  ReferenceInfo::kAlignPc};
1877
1878
1879// LDR{<c>}{<q>} <Rt>, <label> ; A1
1880// LDRB{<c>}{<q>} <Rt>, <label> ; A1
1881// PLD{<c>}{<q>} <label> ; A1
1882// PLI{<c>}{<q>} <label> ; A1
1883static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes,
1884                                                     -4095,  // Min offset.
1885                                                     4095,   // Max offset.
1886                                                     1,      // Alignment.
1887                                                     ReferenceInfo::kAlignPc};
1888
1889
1890// B{<c>}{<q>} <label> ; A1
1891// BL{<c>}{<q>} <label> ; A1
1892static const struct ReferenceInfo kA32BranchInfo =
1893    {kA32InstructionSizeInBytes,
1894     -33554432,  // Min offset.
1895     33554428,   // Max offset.
1896     4,          // Alignment.
1897     ReferenceInfo::kDontAlignPc};
1898
1899
1900// BLX{<c>}{<q>} <label> ; A2
1901static const struct ReferenceInfo kA32BlxInfo = {kA32InstructionSizeInBytes,
1902                                                 -33554432,  // Min offset.
1903                                                 33554430,   // Max offset.
1904                                                 2,          // Alignment.
1905                                                 ReferenceInfo::kAlignPc};
1906
1907
1908void Assembler::adc(Condition cond,
1909                    EncodingSize size,
1910                    Register rd,
1911                    Register rn,
1912                    const Operand& operand) {
1913  VIXL_ASSERT(AllowAssembler());
1914  CheckIT(cond);
1915  if (operand.IsImmediate()) {
1916    uint32_t imm = operand.GetImmediate();
1917    if (IsUsingT32()) {
1918      ImmediateT32 immediate_t32(imm);
1919      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1920      if (!size.IsNarrow() && immediate_t32.IsValid() &&
1921          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
1922        EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1923                   (immediate_t32.GetEncodingValue() & 0xff) |
1924                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1925                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1926        AdvanceIT();
1927        return;
1928      }
1929    } else {
1930      ImmediateA32 immediate_a32(imm);
1931      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1932      if (immediate_a32.IsValid() && cond.IsNotNever()) {
1933        EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1934                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1935                immediate_a32.GetEncodingValue());
1936        return;
1937      }
1938    }
1939  }
1940  if (operand.IsImmediateShiftedRegister()) {
1941    Register rm = operand.GetBaseRegister();
1942    if (operand.IsPlainRegister()) {
1943      if (IsUsingT32()) {
1944        // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1945        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1946            rm.IsLow()) {
1947          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1948          AdvanceIT();
1949          return;
1950        }
1951      }
1952    }
1953    Shift shift = operand.GetShift();
1954    uint32_t amount = operand.GetShiftAmount();
1955    if (IsUsingT32()) {
1956      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1957      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1958          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
1959        uint32_t amount_ = amount % 32;
1960        EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1961                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1962                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1963        AdvanceIT();
1964        return;
1965      }
1966    } else {
1967      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1968      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1969        uint32_t amount_ = amount % 32;
1970        EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1971                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1972                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1973        return;
1974      }
1975    }
1976  }
1977  if (operand.IsRegisterShiftedRegister()) {
1978    Register rm = operand.GetBaseRegister();
1979    Shift shift = operand.GetShift();
1980    Register rs = operand.GetShiftRegister();
1981    if (IsUsingA32()) {
1982      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1983      if (cond.IsNotNever() &&
1984          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
1985           AllowUnpredictable())) {
1986        EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
1987                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1988                (shift.GetType() << 5) | (rs.GetCode() << 8));
1989        return;
1990      }
1991    }
1992  }
1993  Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
1994}
1995
1996void Assembler::adcs(Condition cond,
1997                     EncodingSize size,
1998                     Register rd,
1999                     Register rn,
2000                     const Operand& operand) {
2001  VIXL_ASSERT(AllowAssembler());
2002  CheckIT(cond);
2003  if (operand.IsImmediate()) {
2004    uint32_t imm = operand.GetImmediate();
2005    if (IsUsingT32()) {
2006      ImmediateT32 immediate_t32(imm);
2007      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2008      if (!size.IsNarrow() && immediate_t32.IsValid() &&
2009          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2010        EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2011                   (immediate_t32.GetEncodingValue() & 0xff) |
2012                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2013                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2014        AdvanceIT();
2015        return;
2016      }
2017    } else {
2018      ImmediateA32 immediate_a32(imm);
2019      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2020      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2021        EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
2022                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2023                immediate_a32.GetEncodingValue());
2024        return;
2025      }
2026    }
2027  }
2028  if (operand.IsImmediateShiftedRegister()) {
2029    Register rm = operand.GetBaseRegister();
2030    if (operand.IsPlainRegister()) {
2031      if (IsUsingT32()) {
2032        // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2033        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2034            rm.IsLow()) {
2035          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
2036          AdvanceIT();
2037          return;
2038        }
2039      }
2040    }
2041    Shift shift = operand.GetShift();
2042    uint32_t amount = operand.GetShiftAmount();
2043    if (IsUsingT32()) {
2044      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2045      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2046          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2047        uint32_t amount_ = amount % 32;
2048        EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2049                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2050                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2051        AdvanceIT();
2052        return;
2053      }
2054    } else {
2055      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2056      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2057        uint32_t amount_ = amount % 32;
2058        EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
2059                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2060                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2061        return;
2062      }
2063    }
2064  }
2065  if (operand.IsRegisterShiftedRegister()) {
2066    Register rm = operand.GetBaseRegister();
2067    Shift shift = operand.GetShift();
2068    Register rs = operand.GetShiftRegister();
2069    if (IsUsingA32()) {
2070      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2071      if (cond.IsNotNever() &&
2072          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2073           AllowUnpredictable())) {
2074        EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
2075                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2076                (shift.GetType() << 5) | (rs.GetCode() << 8));
2077        return;
2078      }
2079    }
2080  }
2081  Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
2082}
2083
2084void Assembler::add(Condition cond,
2085                    EncodingSize size,
2086                    Register rd,
2087                    Register rn,
2088                    const Operand& operand) {
2089  VIXL_ASSERT(AllowAssembler());
2090  CheckIT(cond);
2091  if (operand.IsImmediate()) {
2092    uint32_t imm = operand.GetImmediate();
2093    if (IsUsingT32()) {
2094      ImmediateT32 immediate_t32(imm);
2095      // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
2096      if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
2097          ((imm % 4) == 0)) {
2098        uint32_t imm_ = imm >> 2;
2099        EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
2100        AdvanceIT();
2101        return;
2102      }
2103      // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
2104      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2105          (imm <= 7)) {
2106        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2107        AdvanceIT();
2108        return;
2109      }
2110      // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2111      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2112          (imm <= 255)) {
2113        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2114        AdvanceIT();
2115        return;
2116      }
2117      // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
2118      if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
2119          ((imm % 4) == 0)) {
2120        uint32_t imm_ = imm >> 2;
2121        EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2122        AdvanceIT();
2123        return;
2124      }
2125      // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2126      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2127          ((imm % 4) == 0)) {
2128        uint32_t imm_ = imm >> 2;
2129        EmitT32_16(0xb000 | imm_);
2130        AdvanceIT();
2131        return;
2132      }
2133      // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2134      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
2135          (!rd.IsPC() || AllowUnpredictable())) {
2136        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2137                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2138        AdvanceIT();
2139        return;
2140      }
2141      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2142      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2143          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2144        EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2145                   (immediate_t32.GetEncodingValue() & 0xff) |
2146                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2147                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2148        AdvanceIT();
2149        return;
2150      }
2151      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2152      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
2153          (!rd.IsPC() || AllowUnpredictable())) {
2154        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2155                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2156        AdvanceIT();
2157        return;
2158      }
2159      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2160      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2161          (!rd.IsPC() || AllowUnpredictable())) {
2162        EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2163                   (immediate_t32.GetEncodingValue() & 0xff) |
2164                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2165                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2166        AdvanceIT();
2167        return;
2168      }
2169      // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2170      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
2171          (!rd.IsPC() || AllowUnpredictable())) {
2172        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2173                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2174        AdvanceIT();
2175        return;
2176      }
2177    } else {
2178      ImmediateA32 immediate_a32(imm);
2179      // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2180      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2181        EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2182                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2183        return;
2184      }
2185      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2186      if (immediate_a32.IsValid() && cond.IsNotNever() &&
2187          ((rn.GetCode() & 0xd) != 0xd)) {
2188        EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2189                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2190                immediate_a32.GetEncodingValue());
2191        return;
2192      }
2193      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2194      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2195        EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2196                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2197        return;
2198      }
2199    }
2200  }
2201  if (operand.IsImmediateShiftedRegister()) {
2202    Register rm = operand.GetBaseRegister();
2203    if (operand.IsPlainRegister()) {
2204      if (IsUsingT32()) {
2205        // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2206        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2207            rm.IsLow()) {
2208          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2209                     (rm.GetCode() << 6));
2210          AdvanceIT();
2211          return;
2212        }
2213        // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
2214        if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
2215            (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2216              (!rd.IsPC() || !rm.IsPC())) ||
2217             AllowUnpredictable())) {
2218          EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2219                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2220          AdvanceIT();
2221          return;
2222        }
2223        // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
2224        if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
2225            ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
2226             AllowUnpredictable())) {
2227          EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2228                     ((rd.GetCode() & 0x8) << 4));
2229          AdvanceIT();
2230          return;
2231        }
2232        // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2233        if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2234          EmitT32_16(0x4485 | (rm.GetCode() << 3));
2235          AdvanceIT();
2236          return;
2237        }
2238      }
2239    }
2240    Shift shift = operand.GetShift();
2241    uint32_t amount = operand.GetShiftAmount();
2242    if (IsUsingT32()) {
2243      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2244      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2245          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2246        uint32_t amount_ = amount % 32;
2247        EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2248                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2249                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2250        AdvanceIT();
2251        return;
2252      }
2253      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2254      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2255          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2256        uint32_t amount_ = amount % 32;
2257        EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2258                   (operand.GetTypeEncodingValue() << 4) |
2259                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2260        AdvanceIT();
2261        return;
2262      }
2263    } else {
2264      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2265      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2266        uint32_t amount_ = amount % 32;
2267        EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2268                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2269                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2270        return;
2271      }
2272      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2273      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2274        uint32_t amount_ = amount % 32;
2275        EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2276                (rd.GetCode() << 12) | rm.GetCode() |
2277                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2278        return;
2279      }
2280    }
2281  }
2282  if (operand.IsRegisterShiftedRegister()) {
2283    Register rm = operand.GetBaseRegister();
2284    Shift shift = operand.GetShift();
2285    Register rs = operand.GetShiftRegister();
2286    if (IsUsingA32()) {
2287      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2288      if (cond.IsNotNever() &&
2289          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2290           AllowUnpredictable())) {
2291        EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2292                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2293                (shift.GetType() << 5) | (rs.GetCode() << 8));
2294        return;
2295      }
2296    }
2297  }
2298  Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2299}
2300
2301void Assembler::add(Condition cond, Register rd, const Operand& operand) {
2302  VIXL_ASSERT(AllowAssembler());
2303  CheckIT(cond);
2304  if (operand.IsImmediate()) {
2305    uint32_t imm = operand.GetImmediate();
2306    if (IsUsingT32()) {
2307      // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2308      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2309        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2310        AdvanceIT();
2311        return;
2312      }
2313    }
2314  }
2315  if (operand.IsPlainRegister()) {
2316    Register rm = operand.GetBaseRegister();
2317    if (IsUsingT32()) {
2318      // ADD<c>{<q>} <Rdn>, <Rm> ; T2
2319      if (InITBlock() && !rm.Is(sp) &&
2320          (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2321            (!rd.IsPC() || !rm.IsPC())) ||
2322           AllowUnpredictable())) {
2323        EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2324                   (rm.GetCode() << 3));
2325        AdvanceIT();
2326        return;
2327      }
2328    }
2329  }
2330  Delegate(kAdd, &Assembler::add, cond, rd, operand);
2331}
2332
2333void Assembler::adds(Condition cond,
2334                     EncodingSize size,
2335                     Register rd,
2336                     Register rn,
2337                     const Operand& operand) {
2338  VIXL_ASSERT(AllowAssembler());
2339  CheckIT(cond);
2340  if (operand.IsImmediate()) {
2341    uint32_t imm = operand.GetImmediate();
2342    if (IsUsingT32()) {
2343      ImmediateT32 immediate_t32(imm);
2344      // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2345      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2346          (imm <= 7)) {
2347        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2348        AdvanceIT();
2349        return;
2350      }
2351      // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2352      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2353          (imm <= 255)) {
2354        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2355        AdvanceIT();
2356        return;
2357      }
2358      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2359      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2360          !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
2361        EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2362                   (immediate_t32.GetEncodingValue() & 0xff) |
2363                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2364                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2365        AdvanceIT();
2366        return;
2367      }
2368      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2369      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2370          !rd.Is(pc)) {
2371        EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2372                   (immediate_t32.GetEncodingValue() & 0xff) |
2373                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2374                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2375        AdvanceIT();
2376        return;
2377      }
2378    } else {
2379      ImmediateA32 immediate_a32(imm);
2380      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2381      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2382        EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2383                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2384                immediate_a32.GetEncodingValue());
2385        return;
2386      }
2387      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2388      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2389        EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2390                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2391        return;
2392      }
2393    }
2394  }
2395  if (operand.IsImmediateShiftedRegister()) {
2396    Register rm = operand.GetBaseRegister();
2397    if (operand.IsPlainRegister()) {
2398      if (IsUsingT32()) {
2399        // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2400        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2401            rm.IsLow()) {
2402          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2403                     (rm.GetCode() << 6));
2404          AdvanceIT();
2405          return;
2406        }
2407      }
2408    }
2409    Shift shift = operand.GetShift();
2410    uint32_t amount = operand.GetShiftAmount();
2411    if (IsUsingT32()) {
2412      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2413      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2414          !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2415        uint32_t amount_ = amount % 32;
2416        EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2417                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2418                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2419        AdvanceIT();
2420        return;
2421      }
2422      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2423      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2424          !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
2425        uint32_t amount_ = amount % 32;
2426        EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2427                   (operand.GetTypeEncodingValue() << 4) |
2428                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2429        AdvanceIT();
2430        return;
2431      }
2432    } else {
2433      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2434      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2435        uint32_t amount_ = amount % 32;
2436        EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2437                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2438                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2439        return;
2440      }
2441      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2442      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2443        uint32_t amount_ = amount % 32;
2444        EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2445                (rd.GetCode() << 12) | rm.GetCode() |
2446                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2447        return;
2448      }
2449    }
2450  }
2451  if (operand.IsRegisterShiftedRegister()) {
2452    Register rm = operand.GetBaseRegister();
2453    Shift shift = operand.GetShift();
2454    Register rs = operand.GetShiftRegister();
2455    if (IsUsingA32()) {
2456      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2457      if (cond.IsNotNever() &&
2458          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2459           AllowUnpredictable())) {
2460        EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2461                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2462                (shift.GetType() << 5) | (rs.GetCode() << 8));
2463        return;
2464      }
2465    }
2466  }
2467  Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2468}
2469
2470void Assembler::adds(Register rd, const Operand& operand) {
2471  VIXL_ASSERT(AllowAssembler());
2472  CheckIT(al);
2473  if (operand.IsImmediate()) {
2474    uint32_t imm = operand.GetImmediate();
2475    if (IsUsingT32()) {
2476      // ADDS{<q>} <Rdn>, #<imm8> ; T2
2477      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2478        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2479        AdvanceIT();
2480        return;
2481      }
2482    }
2483  }
2484  Delegate(kAdds, &Assembler::adds, rd, operand);
2485}
2486
2487void Assembler::addw(Condition cond,
2488                     Register rd,
2489                     Register rn,
2490                     const Operand& operand) {
2491  VIXL_ASSERT(AllowAssembler());
2492  CheckIT(cond);
2493  if (operand.IsImmediate()) {
2494    uint32_t imm = operand.GetImmediate();
2495    if (IsUsingT32()) {
2496      // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2497      if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2498        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2499                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2500        AdvanceIT();
2501        return;
2502      }
2503      // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2504      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
2505          (!rd.IsPC() || AllowUnpredictable())) {
2506        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2507                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2508        AdvanceIT();
2509        return;
2510      }
2511      // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2512      if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2513        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2514                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2515        AdvanceIT();
2516        return;
2517      }
2518    }
2519  }
2520  Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2521}
2522
2523void Assembler::adr(Condition cond,
2524                    EncodingSize size,
2525                    Register rd,
2526                    Location* location) {
2527  VIXL_ASSERT(AllowAssembler());
2528  CheckIT(cond);
2529  Location::Offset offset =
2530      location->IsBound()
2531          ? location->GetLocation() -
2532                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2533          : 0;
2534  if (IsUsingT32()) {
2535    int32_t neg_offset = -offset;
2536    // ADR{<c>}{<q>} <Rd>, <label> ; T1
2537    if (!size.IsWide() && rd.IsLow() &&
2538        ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
2539          ((offset & 0x3) == 0)) ||
2540         (!location->IsBound() && size.IsNarrow()))) {
2541      static class EmitOp : public Location::EmitOperator {
2542       public:
2543        EmitOp() : Location::EmitOperator(T32) {}
2544        virtual uint32_t Encode(uint32_t instr,
2545                                Location::Offset pc,
2546                                const Location* location) const VIXL_OVERRIDE {
2547          pc += kT32PcDelta;
2548          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
2549          VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2550                      ((offset & 0x3) == 0));
2551          const int32_t target = offset >> 2;
2552          return instr | (target & 0xff);
2553        }
2554      } immop;
2555      EmitT32_16(
2556          Link(0xa000 | (rd.GetCode() << 8), location, immop, &kT16DataInfo));
2557      AdvanceIT();
2558      return;
2559    }
2560    // ADR{<c>}{<q>} <Rd>, <label> ; T2
2561    if (!size.IsNarrow() && location->IsBound() && (neg_offset > 0) &&
2562        (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2563      EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2564                 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2565      AdvanceIT();
2566      return;
2567    }
2568    // ADR{<c>}{<q>} <Rd>, <label> ; T3
2569    if (!size.IsNarrow() &&
2570        (!location->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
2571        (!rd.IsPC() || AllowUnpredictable())) {
2572      static class EmitOp : public Location::EmitOperator {
2573       public:
2574        EmitOp() : Location::EmitOperator(T32) {}
2575        virtual uint32_t Encode(uint32_t instr,
2576                                Location::Offset pc,
2577                                const Location* location) const VIXL_OVERRIDE {
2578          pc += kT32PcDelta;
2579          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
2580          int32_t target;
2581          if ((offset >= 0) && (offset <= 4095)) {
2582            target = offset;
2583          } else {
2584            target = -offset;
2585            VIXL_ASSERT((target >= 0) && (target <= 4095));
2586            // Emit the T2 encoding.
2587            instr |= 0x00a00000;
2588          }
2589          return instr | (target & 0xff) | ((target & 0x700) << 4) |
2590                 ((target & 0x800) << 15);
2591        }
2592      } immop;
2593      EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8),
2594                      location,
2595                      immop,
2596                      &kT32FarDataInfo));
2597      AdvanceIT();
2598      return;
2599    }
2600  } else {
2601    ImmediateA32 positive_immediate_a32(offset);
2602    ImmediateA32 negative_immediate_a32(-offset);
2603    // ADR{<c>}{<q>} <Rd>, <label> ; A1
2604    if ((!location->IsBound() || positive_immediate_a32.IsValid()) &&
2605        cond.IsNotNever()) {
2606      static class EmitOp : public Location::EmitOperator {
2607       public:
2608        EmitOp() : Location::EmitOperator(A32) {}
2609        virtual uint32_t Encode(uint32_t instr,
2610                                Location::Offset pc,
2611                                const Location* location) const VIXL_OVERRIDE {
2612          pc += kA32PcDelta;
2613          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
2614          int32_t target;
2615          ImmediateA32 positive_immediate_a32(offset);
2616          if (positive_immediate_a32.IsValid()) {
2617            target = positive_immediate_a32.GetEncodingValue();
2618          } else {
2619            ImmediateA32 negative_immediate_a32(-offset);
2620            VIXL_ASSERT(negative_immediate_a32.IsValid());
2621            // Emit the A2 encoding.
2622            target = negative_immediate_a32.GetEncodingValue();
2623            instr = (instr & ~0x00f00000) | 0x00400000;
2624          }
2625          return instr | (target & 0xfff);
2626        }
2627      } immop;
2628      EmitA32(
2629          Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
2630               location,
2631               immop,
2632               &kA32AdrInfo));
2633      return;
2634    }
2635    // ADR{<c>}{<q>} <Rd>, <label> ; A2
2636    if (location->IsBound() && negative_immediate_a32.IsValid() &&
2637        cond.IsNotNever()) {
2638      EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2639              negative_immediate_a32.GetEncodingValue());
2640      return;
2641    }
2642  }
2643  Delegate(kAdr, &Assembler::adr, cond, size, rd, location);
2644}
2645
2646bool Assembler::adr_info(Condition cond,
2647                         EncodingSize size,
2648                         Register rd,
2649                         Location* location,
2650                         const struct ReferenceInfo** info) {
2651  VIXL_ASSERT(!location->IsBound());
2652  USE(location);
2653  if (IsUsingT32()) {
2654    // ADR{<c>}{<q>} <Rd>, <label> ; T1
2655    if (!size.IsWide() && rd.IsLow() && size.IsNarrow()) {
2656      *info = &kT16DataInfo;
2657      return true;
2658    }
2659    // Skipped T2, as it is a negative offset variant.
2660    // The minimum offset is included in the corresponding
2661    // positive variant.
2662    // ADR{<c>}{<q>} <Rd>, <label> ; T3
2663    if (!size.IsNarrow()) {
2664      *info = &kT32FarDataInfo;
2665      return true;
2666    }
2667  } else {
2668    // ADR{<c>}{<q>} <Rd>, <label> ; A1
2669    if (cond.IsNotNever()) {
2670      *info = &kA32AdrInfo;
2671      return true;
2672    }
2673    // Skipped A2, as it is a negative offset variant.
2674    // The minimum offset is included in the corresponding
2675    // positive variant.
2676  }
2677  return false;
2678}
2679
2680void Assembler::and_(Condition cond,
2681                     EncodingSize size,
2682                     Register rd,
2683                     Register rn,
2684                     const Operand& operand) {
2685  VIXL_ASSERT(AllowAssembler());
2686  CheckIT(cond);
2687  if (operand.IsImmediate()) {
2688    uint32_t imm = operand.GetImmediate();
2689    if (IsUsingT32()) {
2690      ImmediateT32 immediate_t32(imm);
2691      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2692      if (!size.IsNarrow() && immediate_t32.IsValid() &&
2693          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2694        EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2695                   (immediate_t32.GetEncodingValue() & 0xff) |
2696                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2697                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2698        AdvanceIT();
2699        return;
2700      }
2701    } else {
2702      ImmediateA32 immediate_a32(imm);
2703      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2704      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2705        EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2706                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2707                immediate_a32.GetEncodingValue());
2708        return;
2709      }
2710    }
2711  }
2712  if (operand.IsImmediateShiftedRegister()) {
2713    Register rm = operand.GetBaseRegister();
2714    if (operand.IsPlainRegister()) {
2715      if (IsUsingT32()) {
2716        // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2717        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2718            rm.IsLow()) {
2719          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2720          AdvanceIT();
2721          return;
2722        }
2723      }
2724    }
2725    Shift shift = operand.GetShift();
2726    uint32_t amount = operand.GetShiftAmount();
2727    if (IsUsingT32()) {
2728      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2729      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2730          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2731        uint32_t amount_ = amount % 32;
2732        EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2733                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2734                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2735        AdvanceIT();
2736        return;
2737      }
2738    } else {
2739      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2740      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2741        uint32_t amount_ = amount % 32;
2742        EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2743                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2744                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2745        return;
2746      }
2747    }
2748  }
2749  if (operand.IsRegisterShiftedRegister()) {
2750    Register rm = operand.GetBaseRegister();
2751    Shift shift = operand.GetShift();
2752    Register rs = operand.GetShiftRegister();
2753    if (IsUsingA32()) {
2754      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2755      if (cond.IsNotNever() &&
2756          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2757           AllowUnpredictable())) {
2758        EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2759                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2760                (shift.GetType() << 5) | (rs.GetCode() << 8));
2761        return;
2762      }
2763    }
2764  }
2765  Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2766}
2767
2768void Assembler::ands(Condition cond,
2769                     EncodingSize size,
2770                     Register rd,
2771                     Register rn,
2772                     const Operand& operand) {
2773  VIXL_ASSERT(AllowAssembler());
2774  CheckIT(cond);
2775  if (operand.IsImmediate()) {
2776    uint32_t imm = operand.GetImmediate();
2777    if (IsUsingT32()) {
2778      ImmediateT32 immediate_t32(imm);
2779      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2780      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
2781          (!rn.IsPC() || AllowUnpredictable())) {
2782        EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2783                   (immediate_t32.GetEncodingValue() & 0xff) |
2784                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2785                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2786        AdvanceIT();
2787        return;
2788      }
2789    } else {
2790      ImmediateA32 immediate_a32(imm);
2791      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2792      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2793        EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2794                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2795                immediate_a32.GetEncodingValue());
2796        return;
2797      }
2798    }
2799  }
2800  if (operand.IsImmediateShiftedRegister()) {
2801    Register rm = operand.GetBaseRegister();
2802    if (operand.IsPlainRegister()) {
2803      if (IsUsingT32()) {
2804        // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2805        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2806            rm.IsLow()) {
2807          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2808          AdvanceIT();
2809          return;
2810        }
2811      }
2812    }
2813    Shift shift = operand.GetShift();
2814    uint32_t amount = operand.GetShiftAmount();
2815    if (IsUsingT32()) {
2816      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2817      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
2818          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2819        uint32_t amount_ = amount % 32;
2820        EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2821                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2822                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2823        AdvanceIT();
2824        return;
2825      }
2826    } else {
2827      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2828      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2829        uint32_t amount_ = amount % 32;
2830        EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2831                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2832                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2833        return;
2834      }
2835    }
2836  }
2837  if (operand.IsRegisterShiftedRegister()) {
2838    Register rm = operand.GetBaseRegister();
2839    Shift shift = operand.GetShift();
2840    Register rs = operand.GetShiftRegister();
2841    if (IsUsingA32()) {
2842      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2843      if (cond.IsNotNever() &&
2844          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2845           AllowUnpredictable())) {
2846        EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2847                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2848                (shift.GetType() << 5) | (rs.GetCode() << 8));
2849        return;
2850      }
2851    }
2852  }
2853  Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2854}
2855
2856void Assembler::asr(Condition cond,
2857                    EncodingSize size,
2858                    Register rd,
2859                    Register rm,
2860                    const Operand& operand) {
2861  VIXL_ASSERT(AllowAssembler());
2862  CheckIT(cond);
2863  if (operand.IsImmediate()) {
2864    uint32_t imm = operand.GetImmediate();
2865    if (IsUsingT32()) {
2866      // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2867      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2868          (imm >= 1) && (imm <= 32)) {
2869        uint32_t amount_ = imm % 32;
2870        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2871                   (amount_ << 6));
2872        AdvanceIT();
2873        return;
2874      }
2875      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2876      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2877          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2878        uint32_t amount_ = imm % 32;
2879        EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2880                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2881        AdvanceIT();
2882        return;
2883      }
2884    } else {
2885      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2886      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2887        uint32_t amount_ = imm % 32;
2888        EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2889                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2890        return;
2891      }
2892    }
2893  }
2894  if (operand.IsPlainRegister()) {
2895    Register rs = operand.GetBaseRegister();
2896    if (IsUsingT32()) {
2897      // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2898      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2899          rs.IsLow()) {
2900        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2901        AdvanceIT();
2902        return;
2903      }
2904      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2905      if (!size.IsNarrow() &&
2906          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2907        EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2908                   rs.GetCode());
2909        AdvanceIT();
2910        return;
2911      }
2912    } else {
2913      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2914      if (cond.IsNotNever() &&
2915          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2916        EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2917                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2918        return;
2919      }
2920    }
2921  }
2922  Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2923}
2924
2925void Assembler::asrs(Condition cond,
2926                     EncodingSize size,
2927                     Register rd,
2928                     Register rm,
2929                     const Operand& operand) {
2930  VIXL_ASSERT(AllowAssembler());
2931  CheckIT(cond);
2932  if (operand.IsImmediate()) {
2933    uint32_t imm = operand.GetImmediate();
2934    if (IsUsingT32()) {
2935      // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2936      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2937          (imm >= 1) && (imm <= 32)) {
2938        uint32_t amount_ = imm % 32;
2939        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2940                   (amount_ << 6));
2941        AdvanceIT();
2942        return;
2943      }
2944      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2945      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2946          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2947        uint32_t amount_ = imm % 32;
2948        EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2949                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2950        AdvanceIT();
2951        return;
2952      }
2953    } else {
2954      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2955      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2956        uint32_t amount_ = imm % 32;
2957        EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2958                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2959        return;
2960      }
2961    }
2962  }
2963  if (operand.IsPlainRegister()) {
2964    Register rs = operand.GetBaseRegister();
2965    if (IsUsingT32()) {
2966      // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2967      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2968          rs.IsLow()) {
2969        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2970        AdvanceIT();
2971        return;
2972      }
2973      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2974      if (!size.IsNarrow() &&
2975          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2976        EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2977                   rs.GetCode());
2978        AdvanceIT();
2979        return;
2980      }
2981    } else {
2982      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2983      if (cond.IsNotNever() &&
2984          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
2985        EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
2986                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2987        return;
2988      }
2989    }
2990  }
2991  Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
2992}
2993
2994void Assembler::b(Condition cond, EncodingSize size, Location* location) {
2995  VIXL_ASSERT(AllowAssembler());
2996  Location::Offset offset =
2997      location->IsBound()
2998          ? location->GetLocation() -
2999                (GetCursorOffset() + GetArchitectureStatePCOffset())
3000          : 0;
3001  if (IsUsingT32()) {
3002    // B<c>{<q>} <label> ; T1
3003    if (OutsideITBlock() && !size.IsWide() &&
3004        ((location->IsBound() && (offset >= -256) && (offset <= 254) &&
3005          ((offset & 0x1) == 0)) ||
3006         (!location->IsBound() && size.IsNarrow())) &&
3007        !cond.Is(al) && cond.IsNotNever()) {
3008      static class EmitOp : public Location::EmitOperator {
3009       public:
3010        EmitOp() : Location::EmitOperator(T32) {}
3011        virtual uint32_t Encode(uint32_t instr,
3012                                Location::Offset pc,
3013                                const Location* location) const VIXL_OVERRIDE {
3014          pc += kT32PcDelta;
3015          Location::Offset offset = location->GetLocation() - pc;
3016          VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
3017                      ((offset & 0x1) == 0));
3018          const int32_t target = offset >> 1;
3019          return instr | (target & 0xff);
3020        }
3021      } immop;
3022      EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8),
3023                      location,
3024                      immop,
3025                      &kT16ConditionalBranchInfo));
3026      AdvanceIT();
3027      return;
3028    }
3029    // B{<c>}{<q>} <label> ; T2
3030    if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
3031        ((location->IsBound() && (offset >= -2048) && (offset <= 2046) &&
3032          ((offset & 0x1) == 0)) ||
3033         (!location->IsBound() && size.IsNarrow()))) {
3034      CheckIT(cond);
3035      static class EmitOp : public Location::EmitOperator {
3036       public:
3037        EmitOp() : Location::EmitOperator(T32) {}
3038        virtual uint32_t Encode(uint32_t instr,
3039                                Location::Offset pc,
3040                                const Location* location) const VIXL_OVERRIDE {
3041          pc += kT32PcDelta;
3042          Location::Offset offset = location->GetLocation() - pc;
3043          VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
3044                      ((offset & 0x1) == 0));
3045          const int32_t target = offset >> 1;
3046          return instr | (target & 0x7ff);
3047        }
3048      } immop;
3049      EmitT32_16(Link(0xe000, location, immop, &kT16BranchInfo));
3050      AdvanceIT();
3051      return;
3052    }
3053    // B<c>{<q>} <label> ; T3
3054    if (OutsideITBlock() && !size.IsNarrow() &&
3055        ((location->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
3056          ((offset & 0x1) == 0)) ||
3057         !location->IsBound()) &&
3058        !cond.Is(al) && cond.IsNotNever()) {
3059      static class EmitOp : public Location::EmitOperator {
3060       public:
3061        EmitOp() : Location::EmitOperator(T32) {}
3062        virtual uint32_t Encode(uint32_t instr,
3063                                Location::Offset pc,
3064                                const Location* location) const VIXL_OVERRIDE {
3065          pc += kT32PcDelta;
3066          Location::Offset offset = location->GetLocation() - pc;
3067          VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
3068                      ((offset & 0x1) == 0));
3069          const int32_t target = offset >> 1;
3070          return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
3071                 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
3072                 ((target & 0x80000) << 7);
3073        }
3074      } immop;
3075      EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22),
3076                      location,
3077                      immop,
3078                      &kT32ConditionalBranchInfo));
3079      AdvanceIT();
3080      return;
3081    }
3082    // B{<c>}{<q>} <label> ; T4
3083    if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
3084        ((location->IsBound() && (offset >= -16777216) &&
3085          (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3086         !location->IsBound())) {
3087      CheckIT(cond);
3088      static class EmitOp : public Location::EmitOperator {
3089       public:
3090        EmitOp() : Location::EmitOperator(T32) {}
3091        virtual uint32_t Encode(uint32_t instr,
3092                                Location::Offset pc,
3093                                const Location* location) const VIXL_OVERRIDE {
3094          pc += kT32PcDelta;
3095          Location::Offset offset = location->GetLocation() - pc;
3096          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3097                      ((offset & 0x1) == 0));
3098          int32_t target = offset >> 1;
3099          uint32_t S = target & (1 << 23);
3100          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3101          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3102                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3103                 ((target & 0x800000) << 3);
3104        }
3105      } immop;
3106      EmitT32_32(Link(0xf0009000U, location, immop, &kT32BranchInfo));
3107      AdvanceIT();
3108      return;
3109    }
3110  } else {
3111    // B{<c>}{<q>} <label> ; A1
3112    if (((location->IsBound() && (offset >= -33554432) &&
3113          (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3114         !location->IsBound()) &&
3115        cond.IsNotNever()) {
3116      static class EmitOp : public Location::EmitOperator {
3117       public:
3118        EmitOp() : Location::EmitOperator(A32) {}
3119        virtual uint32_t Encode(uint32_t instr,
3120                                Location::Offset pc,
3121                                const Location* location) const VIXL_OVERRIDE {
3122          pc += kA32PcDelta;
3123          Location::Offset offset = location->GetLocation() - pc;
3124          VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3125                      ((offset & 0x3) == 0));
3126          const int32_t target = offset >> 2;
3127          return instr | (target & 0xffffff);
3128        }
3129      } immop;
3130      EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28),
3131                   location,
3132                   immop,
3133                   &kA32BranchInfo));
3134      return;
3135    }
3136  }
3137  Delegate(kB, &Assembler::b, cond, size, location);
3138}
3139
3140bool Assembler::b_info(Condition cond,
3141                       EncodingSize size,
3142                       Location* location,
3143                       const struct ReferenceInfo** info) {
3144  VIXL_ASSERT(!location->IsBound());
3145  USE(location);
3146  if (IsUsingT32()) {
3147    // B<c>{<q>} <label> ; T1
3148    if (OutsideITBlock() && !size.IsWide() && size.IsNarrow() && !cond.Is(al) &&
3149        cond.IsNotNever()) {
3150      *info = &kT16ConditionalBranchInfo;
3151      return true;
3152    }
3153    // B{<c>}{<q>} <label> ; T2
3154    if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() && size.IsNarrow()) {
3155      *info = &kT16BranchInfo;
3156      return true;
3157    }
3158    // B<c>{<q>} <label> ; T3
3159    if (OutsideITBlock() && !size.IsNarrow() && !cond.Is(al) &&
3160        cond.IsNotNever()) {
3161      *info = &kT32ConditionalBranchInfo;
3162      return true;
3163    }
3164    // B{<c>}{<q>} <label> ; T4
3165    if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow()) {
3166      *info = &kT32BranchInfo;
3167      return true;
3168    }
3169  } else {
3170    // B{<c>}{<q>} <label> ; A1
3171    if (cond.IsNotNever()) {
3172      *info = &kA32BranchInfo;
3173      return true;
3174    }
3175  }
3176  return false;
3177}
3178
3179void Assembler::bfc(Condition cond, Register rd, uint32_t lsb, uint32_t width) {
3180  VIXL_ASSERT(AllowAssembler());
3181  CheckIT(cond);
3182  if (IsUsingT32()) {
3183    // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
3184    if ((lsb <= 31) && (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3185                        AllowUnpredictable())) {
3186      uint32_t msb = lsb + width - 1;
3187      EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
3188                 ((lsb & 0x1c) << 10) | msb);
3189      AdvanceIT();
3190      return;
3191    }
3192  } else {
3193    // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
3194    if ((lsb <= 31) && cond.IsNotNever() &&
3195        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3196         AllowUnpredictable())) {
3197      uint32_t msb = lsb + width - 1;
3198      EmitA32(0x07c0001fU | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3199              (lsb << 7) | (msb << 16));
3200      return;
3201    }
3202  }
3203  Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, width);
3204}
3205
3206void Assembler::bfi(
3207    Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
3208  VIXL_ASSERT(AllowAssembler());
3209  CheckIT(cond);
3210  if (IsUsingT32()) {
3211    // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
3212    if ((lsb <= 31) && !rn.Is(pc) &&
3213        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3214         AllowUnpredictable())) {
3215      uint32_t msb = lsb + width - 1;
3216      EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3217                 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
3218      AdvanceIT();
3219      return;
3220    }
3221  } else {
3222    // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
3223    if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
3224        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3225         AllowUnpredictable())) {
3226      uint32_t msb = lsb + width - 1;
3227      EmitA32(0x07c00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3228              rn.GetCode() | (lsb << 7) | (msb << 16));
3229      return;
3230    }
3231  }
3232  Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, width);
3233}
3234
3235void Assembler::bic(Condition cond,
3236                    EncodingSize size,
3237                    Register rd,
3238                    Register rn,
3239                    const Operand& operand) {
3240  VIXL_ASSERT(AllowAssembler());
3241  CheckIT(cond);
3242  if (operand.IsImmediate()) {
3243    uint32_t imm = operand.GetImmediate();
3244    if (IsUsingT32()) {
3245      ImmediateT32 immediate_t32(imm);
3246      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3247      if (!size.IsNarrow() && immediate_t32.IsValid() &&
3248          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
3249        EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3250                   (immediate_t32.GetEncodingValue() & 0xff) |
3251                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3252                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3253        AdvanceIT();
3254        return;
3255      }
3256    } else {
3257      ImmediateA32 immediate_a32(imm);
3258      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3259      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3260        EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3261                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3262                immediate_a32.GetEncodingValue());
3263        return;
3264      }
3265    }
3266  }
3267  if (operand.IsImmediateShiftedRegister()) {
3268    Register rm = operand.GetBaseRegister();
3269    if (operand.IsPlainRegister()) {
3270      if (IsUsingT32()) {
3271        // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3272        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3273            rm.IsLow()) {
3274          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3275          AdvanceIT();
3276          return;
3277        }
3278      }
3279    }
3280    Shift shift = operand.GetShift();
3281    uint32_t amount = operand.GetShiftAmount();
3282    if (IsUsingT32()) {
3283      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3284      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3285          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3286        uint32_t amount_ = amount % 32;
3287        EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3288                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3289                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3290        AdvanceIT();
3291        return;
3292      }
3293    } else {
3294      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3295      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3296        uint32_t amount_ = amount % 32;
3297        EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3298                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3299                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3300        return;
3301      }
3302    }
3303  }
3304  if (operand.IsRegisterShiftedRegister()) {
3305    Register rm = operand.GetBaseRegister();
3306    Shift shift = operand.GetShift();
3307    Register rs = operand.GetShiftRegister();
3308    if (IsUsingA32()) {
3309      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3310      if (cond.IsNotNever() &&
3311          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3312           AllowUnpredictable())) {
3313        EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3314                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3315                (shift.GetType() << 5) | (rs.GetCode() << 8));
3316        return;
3317      }
3318    }
3319  }
3320  Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3321}
3322
3323void Assembler::bics(Condition cond,
3324                     EncodingSize size,
3325                     Register rd,
3326                     Register rn,
3327                     const Operand& operand) {
3328  VIXL_ASSERT(AllowAssembler());
3329  CheckIT(cond);
3330  if (operand.IsImmediate()) {
3331    uint32_t imm = operand.GetImmediate();
3332    if (IsUsingT32()) {
3333      ImmediateT32 immediate_t32(imm);
3334      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3335      if (!size.IsNarrow() && immediate_t32.IsValid() &&
3336          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
3337        EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3338                   (immediate_t32.GetEncodingValue() & 0xff) |
3339                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3340                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3341        AdvanceIT();
3342        return;
3343      }
3344    } else {
3345      ImmediateA32 immediate_a32(imm);
3346      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3347      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3348        EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3349                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3350                immediate_a32.GetEncodingValue());
3351        return;
3352      }
3353    }
3354  }
3355  if (operand.IsImmediateShiftedRegister()) {
3356    Register rm = operand.GetBaseRegister();
3357    if (operand.IsPlainRegister()) {
3358      if (IsUsingT32()) {
3359        // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3360        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3361            rm.IsLow()) {
3362          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3363          AdvanceIT();
3364          return;
3365        }
3366      }
3367    }
3368    Shift shift = operand.GetShift();
3369    uint32_t amount = operand.GetShiftAmount();
3370    if (IsUsingT32()) {
3371      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3372      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3373          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3374        uint32_t amount_ = amount % 32;
3375        EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3376                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3377                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3378        AdvanceIT();
3379        return;
3380      }
3381    } else {
3382      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3383      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3384        uint32_t amount_ = amount % 32;
3385        EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3386                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3387                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3388        return;
3389      }
3390    }
3391  }
3392  if (operand.IsRegisterShiftedRegister()) {
3393    Register rm = operand.GetBaseRegister();
3394    Shift shift = operand.GetShift();
3395    Register rs = operand.GetShiftRegister();
3396    if (IsUsingA32()) {
3397      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3398      if (cond.IsNotNever() &&
3399          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3400           AllowUnpredictable())) {
3401        EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3402                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3403                (shift.GetType() << 5) | (rs.GetCode() << 8));
3404        return;
3405      }
3406    }
3407  }
3408  Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3409}
3410
3411void Assembler::bkpt(Condition cond, uint32_t imm) {
3412  VIXL_ASSERT(AllowAssembler());
3413  CheckIT(cond);
3414  if (IsUsingT32()) {
3415    // BKPT{<q>} {#}<imm> ; T1
3416    if ((imm <= 255)) {
3417      EmitT32_16(0xbe00 | imm);
3418      AdvanceIT();
3419      return;
3420    }
3421  } else {
3422    // BKPT{<q>} {#}<imm> ; A1
3423    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3424      EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3425              ((imm & 0xfff0) << 4));
3426      return;
3427    }
3428  }
3429  Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3430}
3431
3432void Assembler::bl(Condition cond, Location* location) {
3433  VIXL_ASSERT(AllowAssembler());
3434  CheckIT(cond);
3435  Location::Offset offset =
3436      location->IsBound()
3437          ? location->GetLocation() -
3438                (GetCursorOffset() + GetArchitectureStatePCOffset())
3439          : 0;
3440  if (IsUsingT32()) {
3441    // BL{<c>}{<q>} <label> ; T1
3442    if (((location->IsBound() && (offset >= -16777216) &&
3443          (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3444         !location->IsBound()) &&
3445        (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3446      static class EmitOp : public Location::EmitOperator {
3447       public:
3448        EmitOp() : Location::EmitOperator(T32) {}
3449        virtual uint32_t Encode(uint32_t instr,
3450                                Location::Offset pc,
3451                                const Location* location) const VIXL_OVERRIDE {
3452          pc += kT32PcDelta;
3453          Location::Offset offset = location->GetLocation() - pc;
3454          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3455                      ((offset & 0x1) == 0));
3456          int32_t target = offset >> 1;
3457          uint32_t S = target & (1 << 23);
3458          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3459          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3460                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3461                 ((target & 0x800000) << 3);
3462        }
3463      } immop;
3464      EmitT32_32(Link(0xf000d000U, location, immop, &kT32BranchInfo));
3465      AdvanceIT();
3466      return;
3467    }
3468  } else {
3469    // BL{<c>}{<q>} <label> ; A1
3470    if (((location->IsBound() && (offset >= -33554432) &&
3471          (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3472         !location->IsBound()) &&
3473        cond.IsNotNever()) {
3474      static class EmitOp : public Location::EmitOperator {
3475       public:
3476        EmitOp() : Location::EmitOperator(A32) {}
3477        virtual uint32_t Encode(uint32_t instr,
3478                                Location::Offset pc,
3479                                const Location* location) const VIXL_OVERRIDE {
3480          pc += kA32PcDelta;
3481          Location::Offset offset = location->GetLocation() - pc;
3482          VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3483                      ((offset & 0x3) == 0));
3484          const int32_t target = offset >> 2;
3485          return instr | (target & 0xffffff);
3486        }
3487      } immop;
3488      EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28),
3489                   location,
3490                   immop,
3491                   &kA32BranchInfo));
3492      return;
3493    }
3494  }
3495  Delegate(kBl, &Assembler::bl, cond, location);
3496}
3497
3498bool Assembler::bl_info(Condition cond,
3499                        Location* location,
3500                        const struct ReferenceInfo** info) {
3501  VIXL_ASSERT(!location->IsBound());
3502  USE(location);
3503  if (IsUsingT32()) {
3504    // BL{<c>}{<q>} <label> ; T1
3505    if (true) {
3506      *info = &kT32BranchInfo;
3507      return true;
3508    }
3509  } else {
3510    // BL{<c>}{<q>} <label> ; A1
3511    if (cond.IsNotNever()) {
3512      *info = &kA32BranchInfo;
3513      return true;
3514    }
3515  }
3516  return false;
3517}
3518
3519void Assembler::blx(Condition cond, Location* location) {
3520  VIXL_ASSERT(AllowAssembler());
3521  CheckIT(cond);
3522  Location::Offset offset =
3523      location->IsBound()
3524          ? location->GetLocation() -
3525                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3526          : 0;
3527  if (IsUsingT32()) {
3528    // BLX{<c>}{<q>} <label> ; T2
3529    if (((location->IsBound() && (offset >= -16777216) &&
3530          (offset <= 16777212) && ((offset & 0x3) == 0)) ||
3531         !location->IsBound()) &&
3532        (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3533      static class EmitOp : public Location::EmitOperator {
3534       public:
3535        EmitOp() : Location::EmitOperator(T32) {}
3536        virtual uint32_t Encode(uint32_t instr,
3537                                Location::Offset pc,
3538                                const Location* location) const VIXL_OVERRIDE {
3539          pc += kT32PcDelta;
3540          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
3541          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3542                      ((offset & 0x3) == 0));
3543          int32_t target = offset >> 2;
3544          uint32_t S = target & (1 << 22);
3545          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3546          return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3547                 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3548                 ((target & 0x400000) << 4);
3549        }
3550      } immop;
3551      EmitT32_32(Link(0xf000c000U, location, immop, &kT32BlxInfo));
3552      AdvanceIT();
3553      return;
3554    }
3555  } else {
3556    // BLX{<c>}{<q>} <label> ; A2
3557    if (((location->IsBound() && (offset >= -33554432) &&
3558          (offset <= 33554430) && ((offset & 0x1) == 0)) ||
3559         !location->IsBound())) {
3560      if (cond.Is(al) || AllowStronglyDiscouraged()) {
3561        static class EmitOp : public Location::EmitOperator {
3562         public:
3563          EmitOp() : Location::EmitOperator(A32) {}
3564          virtual uint32_t Encode(uint32_t instr,
3565                                  Location::Offset pc,
3566                                  const Location* location) const
3567              VIXL_OVERRIDE {
3568            pc += kA32PcDelta;
3569            Location::Offset offset =
3570                location->GetLocation() - AlignDown(pc, 4);
3571            VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3572                        ((offset & 0x1) == 0));
3573            const int32_t target = offset >> 1;
3574            return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3575          }
3576        } immop;
3577        EmitA32(Link(0xfa000000U, location, immop, &kA32BlxInfo));
3578        return;
3579      }
3580    }
3581  }
3582  Delegate(kBlx, &Assembler::blx, cond, location);
3583}
3584
3585bool Assembler::blx_info(Condition cond,
3586                         Location* location,
3587                         const struct ReferenceInfo** info) {
3588  VIXL_ASSERT(!location->IsBound());
3589  USE(location);
3590  USE(cond);
3591  if (IsUsingT32()) {
3592    // BLX{<c>}{<q>} <label> ; T2
3593    if (true) {
3594      *info = &kT32BlxInfo;
3595      return true;
3596    }
3597  } else {
3598    // BLX{<c>}{<q>} <label> ; A2
3599    if (true) {
3600      *info = &kA32BlxInfo;
3601      return true;
3602    }
3603  }
3604  return false;
3605}
3606
3607void Assembler::blx(Condition cond, Register rm) {
3608  VIXL_ASSERT(AllowAssembler());
3609  CheckIT(cond);
3610  if (IsUsingT32()) {
3611    // BLX{<c>}{<q>} <Rm> ; T1
3612    if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3613         AllowUnpredictable())) {
3614      EmitT32_16(0x4780 | (rm.GetCode() << 3));
3615      AdvanceIT();
3616      return;
3617    }
3618  } else {
3619    // BLX{<c>}{<q>} <Rm> ; A1
3620    if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
3621      EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3622      return;
3623    }
3624  }
3625  Delegate(kBlx, &Assembler::blx, cond, rm);
3626}
3627
3628void Assembler::bx(Condition cond, Register rm) {
3629  VIXL_ASSERT(AllowAssembler());
3630  CheckIT(cond);
3631  if (IsUsingT32()) {
3632    // BX{<c>}{<q>} <Rm> ; T1
3633    if ((OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3634      EmitT32_16(0x4700 | (rm.GetCode() << 3));
3635      AdvanceIT();
3636      return;
3637    }
3638  } else {
3639    // BX{<c>}{<q>} <Rm> ; A1
3640    if (cond.IsNotNever()) {
3641      EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3642      return;
3643    }
3644  }
3645  Delegate(kBx, &Assembler::bx, cond, rm);
3646}
3647
3648void Assembler::bxj(Condition cond, Register rm) {
3649  VIXL_ASSERT(AllowAssembler());
3650  CheckIT(cond);
3651  if (IsUsingT32()) {
3652    // BXJ{<c>}{<q>} <Rm> ; T1
3653    if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3654         AllowUnpredictable())) {
3655      EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3656      AdvanceIT();
3657      return;
3658    }
3659  } else {
3660    // BXJ{<c>}{<q>} <Rm> ; A1
3661    if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
3662      EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3663      return;
3664    }
3665  }
3666  Delegate(kBxj, &Assembler::bxj, cond, rm);
3667}
3668
3669void Assembler::cbnz(Register rn, Location* location) {
3670  VIXL_ASSERT(AllowAssembler());
3671  CheckIT(al);
3672  Location::Offset offset =
3673      location->IsBound()
3674          ? location->GetLocation() -
3675                (GetCursorOffset() + GetArchitectureStatePCOffset())
3676          : 0;
3677  if (IsUsingT32()) {
3678    // CBNZ{<q>} <Rn>, <label> ; T1
3679    if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3680                        (offset <= 126) && ((offset & 0x1) == 0)) ||
3681                       !location->IsBound())) {
3682      static class EmitOp : public Location::EmitOperator {
3683       public:
3684        EmitOp() : Location::EmitOperator(T32) {}
3685        virtual uint32_t Encode(uint32_t instr,
3686                                Location::Offset pc,
3687                                const Location* location) const VIXL_OVERRIDE {
3688          pc += kT32PcDelta;
3689          Location::Offset offset = location->GetLocation() - pc;
3690          VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3691                      ((offset & 0x1) == 0));
3692          const int32_t target = offset >> 1;
3693          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3694        }
3695      } immop;
3696      EmitT32_16(Link(0xb900 | rn.GetCode(), location, immop, &kT16CbzInfo));
3697      AdvanceIT();
3698      return;
3699    }
3700  }
3701  Delegate(kCbnz, &Assembler::cbnz, rn, location);
3702}
3703
3704bool Assembler::cbnz_info(Register rn,
3705                          Location* location,
3706                          const struct ReferenceInfo** info) {
3707  VIXL_ASSERT(!location->IsBound());
3708  USE(location);
3709  if (IsUsingT32()) {
3710    // CBNZ{<q>} <Rn>, <label> ; T1
3711    if (rn.IsLow()) {
3712      *info = &kT16CbzInfo;
3713      return true;
3714    }
3715  }
3716  return false;
3717}
3718
3719void Assembler::cbz(Register rn, Location* location) {
3720  VIXL_ASSERT(AllowAssembler());
3721  CheckIT(al);
3722  Location::Offset offset =
3723      location->IsBound()
3724          ? location->GetLocation() -
3725                (GetCursorOffset() + GetArchitectureStatePCOffset())
3726          : 0;
3727  if (IsUsingT32()) {
3728    // CBZ{<q>} <Rn>, <label> ; T1
3729    if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3730                        (offset <= 126) && ((offset & 0x1) == 0)) ||
3731                       !location->IsBound())) {
3732      static class EmitOp : public Location::EmitOperator {
3733       public:
3734        EmitOp() : Location::EmitOperator(T32) {}
3735        virtual uint32_t Encode(uint32_t instr,
3736                                Location::Offset pc,
3737                                const Location* location) const VIXL_OVERRIDE {
3738          pc += kT32PcDelta;
3739          Location::Offset offset = location->GetLocation() - pc;
3740          VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3741                      ((offset & 0x1) == 0));
3742          const int32_t target = offset >> 1;
3743          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3744        }
3745      } immop;
3746      EmitT32_16(Link(0xb100 | rn.GetCode(), location, immop, &kT16CbzInfo));
3747      AdvanceIT();
3748      return;
3749    }
3750  }
3751  Delegate(kCbz, &Assembler::cbz, rn, location);
3752}
3753
3754bool Assembler::cbz_info(Register rn,
3755                         Location* location,
3756                         const struct ReferenceInfo** info) {
3757  VIXL_ASSERT(!location->IsBound());
3758  USE(location);
3759  if (IsUsingT32()) {
3760    // CBZ{<q>} <Rn>, <label> ; T1
3761    if (rn.IsLow()) {
3762      *info = &kT16CbzInfo;
3763      return true;
3764    }
3765  }
3766  return false;
3767}
3768
3769void Assembler::clrex(Condition cond) {
3770  VIXL_ASSERT(AllowAssembler());
3771  CheckIT(cond);
3772  if (IsUsingT32()) {
3773    // CLREX{<c>}{<q>} ; T1
3774    EmitT32_32(0xf3bf8f2fU);
3775    AdvanceIT();
3776    return;
3777  } else {
3778    // CLREX{<c>}{<q>} ; A1
3779    if (cond.Is(al)) {
3780      EmitA32(0xf57ff01fU);
3781      return;
3782    }
3783  }
3784  Delegate(kClrex, &Assembler::clrex, cond);
3785}
3786
3787void Assembler::clz(Condition cond, Register rd, Register rm) {
3788  VIXL_ASSERT(AllowAssembler());
3789  CheckIT(cond);
3790  if (IsUsingT32()) {
3791    // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
3792    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3793      EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3794                 (rm.GetCode() << 16));
3795      AdvanceIT();
3796      return;
3797    }
3798  } else {
3799    // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
3800    if (cond.IsNotNever() &&
3801        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3802      EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3803              rm.GetCode());
3804      return;
3805    }
3806  }
3807  Delegate(kClz, &Assembler::clz, cond, rd, rm);
3808}
3809
3810void Assembler::cmn(Condition cond,
3811                    EncodingSize size,
3812                    Register rn,
3813                    const Operand& operand) {
3814  VIXL_ASSERT(AllowAssembler());
3815  CheckIT(cond);
3816  if (operand.IsImmediate()) {
3817    uint32_t imm = operand.GetImmediate();
3818    if (IsUsingT32()) {
3819      ImmediateT32 immediate_t32(imm);
3820      // CMN{<c>}{<q>} <Rn>, #<const> ; T1
3821      if (!size.IsNarrow() && immediate_t32.IsValid() &&
3822          (!rn.IsPC() || AllowUnpredictable())) {
3823        EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3824                   (immediate_t32.GetEncodingValue() & 0xff) |
3825                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3826                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3827        AdvanceIT();
3828        return;
3829      }
3830    } else {
3831      ImmediateA32 immediate_a32(imm);
3832      // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3833      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3834        EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3835                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3836        return;
3837      }
3838    }
3839  }
3840  if (operand.IsImmediateShiftedRegister()) {
3841    Register rm = operand.GetBaseRegister();
3842    if (operand.IsPlainRegister()) {
3843      if (IsUsingT32()) {
3844        // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3845        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3846          EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3847          AdvanceIT();
3848          return;
3849        }
3850      }
3851    }
3852    Shift shift = operand.GetShift();
3853    uint32_t amount = operand.GetShiftAmount();
3854    if (IsUsingT32()) {
3855      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
3856      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3857          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3858        uint32_t amount_ = amount % 32;
3859        EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3860                   (operand.GetTypeEncodingValue() << 4) |
3861                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3862        AdvanceIT();
3863        return;
3864      }
3865    } else {
3866      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3867      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3868        uint32_t amount_ = amount % 32;
3869        EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3870                (rn.GetCode() << 16) | rm.GetCode() |
3871                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3872        return;
3873      }
3874    }
3875  }
3876  if (operand.IsRegisterShiftedRegister()) {
3877    Register rm = operand.GetBaseRegister();
3878    Shift shift = operand.GetShift();
3879    Register rs = operand.GetShiftRegister();
3880    if (IsUsingA32()) {
3881      // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3882      if (cond.IsNotNever() &&
3883          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
3884        EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3885                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3886                (rs.GetCode() << 8));
3887        return;
3888      }
3889    }
3890  }
3891  Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3892}
3893
3894void Assembler::cmp(Condition cond,
3895                    EncodingSize size,
3896                    Register rn,
3897                    const Operand& operand) {
3898  VIXL_ASSERT(AllowAssembler());
3899  CheckIT(cond);
3900  if (operand.IsImmediate()) {
3901    uint32_t imm = operand.GetImmediate();
3902    if (IsUsingT32()) {
3903      ImmediateT32 immediate_t32(imm);
3904      // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3905      if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3906        EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3907        AdvanceIT();
3908        return;
3909      }
3910      // CMP{<c>}{<q>} <Rn>, #<const> ; T2
3911      if (!size.IsNarrow() && immediate_t32.IsValid() &&
3912          (!rn.IsPC() || AllowUnpredictable())) {
3913        EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3914                   (immediate_t32.GetEncodingValue() & 0xff) |
3915                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3916                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3917        AdvanceIT();
3918        return;
3919      }
3920    } else {
3921      ImmediateA32 immediate_a32(imm);
3922      // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3923      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3924        EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3925                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3926        return;
3927      }
3928    }
3929  }
3930  if (operand.IsImmediateShiftedRegister()) {
3931    Register rm = operand.GetBaseRegister();
3932    if (operand.IsPlainRegister()) {
3933      if (IsUsingT32()) {
3934        // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3935        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3936          EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3937          AdvanceIT();
3938          return;
3939        }
3940        // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
3941        if (!size.IsWide() &&
3942            ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3943          EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3944                     ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3945          AdvanceIT();
3946          return;
3947        }
3948      }
3949    }
3950    Shift shift = operand.GetShift();
3951    uint32_t amount = operand.GetShiftAmount();
3952    if (IsUsingT32()) {
3953      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
3954      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3955          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3956        uint32_t amount_ = amount % 32;
3957        EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3958                   (operand.GetTypeEncodingValue() << 4) |
3959                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3960        AdvanceIT();
3961        return;
3962      }
3963    } else {
3964      // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3965      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3966        uint32_t amount_ = amount % 32;
3967        EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3968                (rn.GetCode() << 16) | rm.GetCode() |
3969                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3970        return;
3971      }
3972    }
3973  }
3974  if (operand.IsRegisterShiftedRegister()) {
3975    Register rm = operand.GetBaseRegister();
3976    Shift shift = operand.GetShift();
3977    Register rs = operand.GetShiftRegister();
3978    if (IsUsingA32()) {
3979      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3980      if (cond.IsNotNever() &&
3981          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
3982        EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3983                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3984                (rs.GetCode() << 8));
3985        return;
3986      }
3987    }
3988  }
3989  Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
3990}
3991
3992void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
3993  VIXL_ASSERT(AllowAssembler());
3994  CheckIT(cond);
3995  if (IsUsingT32()) {
3996    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
3997    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
3998         AllowUnpredictable())) {
3999      EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4000                 rm.GetCode());
4001      AdvanceIT();
4002      return;
4003    }
4004  } else {
4005    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
4006    if ((cond.Is(al) || AllowUnpredictable()) &&
4007        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4008      EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4009              (rn.GetCode() << 16) | rm.GetCode());
4010      return;
4011    }
4012  }
4013  Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
4014}
4015
4016void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
4017  VIXL_ASSERT(AllowAssembler());
4018  CheckIT(cond);
4019  if (IsUsingT32()) {
4020    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
4021    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4022         AllowUnpredictable())) {
4023      EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4024                 rm.GetCode());
4025      AdvanceIT();
4026      return;
4027    }
4028  } else {
4029    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
4030    if ((cond.Is(al) || AllowUnpredictable()) &&
4031        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4032      EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4033              (rn.GetCode() << 16) | rm.GetCode());
4034      return;
4035    }
4036  }
4037  Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
4038}
4039
4040void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
4041  VIXL_ASSERT(AllowAssembler());
4042  CheckIT(cond);
4043  if (IsUsingT32()) {
4044    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
4045    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4046         AllowUnpredictable())) {
4047      EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4048                 rm.GetCode());
4049      AdvanceIT();
4050      return;
4051    }
4052  } else {
4053    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
4054    if ((cond.Is(al) || AllowUnpredictable()) &&
4055        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4056      EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4057              (rn.GetCode() << 16) | rm.GetCode());
4058      return;
4059    }
4060  }
4061  Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
4062}
4063
4064void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
4065  VIXL_ASSERT(AllowAssembler());
4066  CheckIT(cond);
4067  if (IsUsingT32()) {
4068    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
4069    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4070         AllowUnpredictable())) {
4071      EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4072                 rm.GetCode());
4073      AdvanceIT();
4074      return;
4075    }
4076  } else {
4077    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
4078    if ((cond.Is(al) || AllowUnpredictable()) &&
4079        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4080      EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4081              (rn.GetCode() << 16) | rm.GetCode());
4082      return;
4083    }
4084  }
4085  Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
4086}
4087
4088void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
4089  VIXL_ASSERT(AllowAssembler());
4090  CheckIT(cond);
4091  if (IsUsingT32()) {
4092    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
4093    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4094         AllowUnpredictable())) {
4095      EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4096                 rm.GetCode());
4097      AdvanceIT();
4098      return;
4099    }
4100  } else {
4101    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
4102    if ((cond.Is(al) || AllowUnpredictable()) &&
4103        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4104      EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4105              (rn.GetCode() << 16) | rm.GetCode());
4106      return;
4107    }
4108  }
4109  Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
4110}
4111
4112void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
4113  VIXL_ASSERT(AllowAssembler());
4114  CheckIT(cond);
4115  if (IsUsingT32()) {
4116    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
4117    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4118         AllowUnpredictable())) {
4119      EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4120                 rm.GetCode());
4121      AdvanceIT();
4122      return;
4123    }
4124  } else {
4125    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
4126    if ((cond.Is(al) || AllowUnpredictable()) &&
4127        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4128      EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4129              (rn.GetCode() << 16) | rm.GetCode());
4130      return;
4131    }
4132  }
4133  Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
4134}
4135
4136void Assembler::dmb(Condition cond, MemoryBarrier option) {
4137  VIXL_ASSERT(AllowAssembler());
4138  CheckIT(cond);
4139  if (IsUsingT32()) {
4140    // DMB{<c>}{<q>} {<option>} ; T1
4141    EmitT32_32(0xf3bf8f50U | option.GetType());
4142    AdvanceIT();
4143    return;
4144  } else {
4145    // DMB{<c>}{<q>} {<option>} ; A1
4146    if (cond.Is(al)) {
4147      EmitA32(0xf57ff050U | option.GetType());
4148      return;
4149    }
4150  }
4151  Delegate(kDmb, &Assembler::dmb, cond, option);
4152}
4153
4154void Assembler::dsb(Condition cond, MemoryBarrier option) {
4155  VIXL_ASSERT(AllowAssembler());
4156  CheckIT(cond);
4157  if (IsUsingT32()) {
4158    // DSB{<c>}{<q>} {<option>} ; T1
4159    EmitT32_32(0xf3bf8f40U | option.GetType());
4160    AdvanceIT();
4161    return;
4162  } else {
4163    // DSB{<c>}{<q>} {<option>} ; A1
4164    if (cond.Is(al)) {
4165      EmitA32(0xf57ff040U | option.GetType());
4166      return;
4167    }
4168  }
4169  Delegate(kDsb, &Assembler::dsb, cond, option);
4170}
4171
4172void Assembler::eor(Condition cond,
4173                    EncodingSize size,
4174                    Register rd,
4175                    Register rn,
4176                    const Operand& operand) {
4177  VIXL_ASSERT(AllowAssembler());
4178  CheckIT(cond);
4179  if (operand.IsImmediate()) {
4180    uint32_t imm = operand.GetImmediate();
4181    if (IsUsingT32()) {
4182      ImmediateT32 immediate_t32(imm);
4183      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
4184      if (!size.IsNarrow() && immediate_t32.IsValid() &&
4185          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4186        EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4187                   (immediate_t32.GetEncodingValue() & 0xff) |
4188                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4189                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4190        AdvanceIT();
4191        return;
4192      }
4193    } else {
4194      ImmediateA32 immediate_a32(imm);
4195      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4196      if (immediate_a32.IsValid() && cond.IsNotNever()) {
4197        EmitA32(0x02200000U | (cond.GetCondition() << 28) |
4198                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4199                immediate_a32.GetEncodingValue());
4200        return;
4201      }
4202    }
4203  }
4204  if (operand.IsImmediateShiftedRegister()) {
4205    Register rm = operand.GetBaseRegister();
4206    if (operand.IsPlainRegister()) {
4207      if (IsUsingT32()) {
4208        // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4209        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4210            rm.IsLow()) {
4211          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4212          AdvanceIT();
4213          return;
4214        }
4215      }
4216    }
4217    Shift shift = operand.GetShift();
4218    uint32_t amount = operand.GetShiftAmount();
4219    if (IsUsingT32()) {
4220      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
4221      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
4222          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4223        uint32_t amount_ = amount % 32;
4224        EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4225                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4226                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4227        AdvanceIT();
4228        return;
4229      }
4230    } else {
4231      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4232      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4233        uint32_t amount_ = amount % 32;
4234        EmitA32(0x00200000U | (cond.GetCondition() << 28) |
4235                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4236                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4237        return;
4238      }
4239    }
4240  }
4241  if (operand.IsRegisterShiftedRegister()) {
4242    Register rm = operand.GetBaseRegister();
4243    Shift shift = operand.GetShift();
4244    Register rs = operand.GetShiftRegister();
4245    if (IsUsingA32()) {
4246      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
4247      if (cond.IsNotNever() &&
4248          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4249           AllowUnpredictable())) {
4250        EmitA32(0x00200010U | (cond.GetCondition() << 28) |
4251                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4252                (shift.GetType() << 5) | (rs.GetCode() << 8));
4253        return;
4254      }
4255    }
4256  }
4257  Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
4258}
4259
4260void Assembler::eors(Condition cond,
4261                     EncodingSize size,
4262                     Register rd,
4263                     Register rn,
4264                     const Operand& operand) {
4265  VIXL_ASSERT(AllowAssembler());
4266  CheckIT(cond);
4267  if (operand.IsImmediate()) {
4268    uint32_t imm = operand.GetImmediate();
4269    if (IsUsingT32()) {
4270      ImmediateT32 immediate_t32(imm);
4271      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
4272      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
4273          (!rn.IsPC() || AllowUnpredictable())) {
4274        EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4275                   (immediate_t32.GetEncodingValue() & 0xff) |
4276                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4277                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4278        AdvanceIT();
4279        return;
4280      }
4281    } else {
4282      ImmediateA32 immediate_a32(imm);
4283      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4284      if (immediate_a32.IsValid() && cond.IsNotNever()) {
4285        EmitA32(0x02300000U | (cond.GetCondition() << 28) |
4286                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4287                immediate_a32.GetEncodingValue());
4288        return;
4289      }
4290    }
4291  }
4292  if (operand.IsImmediateShiftedRegister()) {
4293    Register rm = operand.GetBaseRegister();
4294    if (operand.IsPlainRegister()) {
4295      if (IsUsingT32()) {
4296        // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4297        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4298            rm.IsLow()) {
4299          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4300          AdvanceIT();
4301          return;
4302        }
4303      }
4304    }
4305    Shift shift = operand.GetShift();
4306    uint32_t amount = operand.GetShiftAmount();
4307    if (IsUsingT32()) {
4308      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
4309      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
4310          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4311        uint32_t amount_ = amount % 32;
4312        EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4313                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4314                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4315        AdvanceIT();
4316        return;
4317      }
4318    } else {
4319      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4320      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4321        uint32_t amount_ = amount % 32;
4322        EmitA32(0x00300000U | (cond.GetCondition() << 28) |
4323                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4324                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4325        return;
4326      }
4327    }
4328  }
4329  if (operand.IsRegisterShiftedRegister()) {
4330    Register rm = operand.GetBaseRegister();
4331    Shift shift = operand.GetShift();
4332    Register rs = operand.GetShiftRegister();
4333    if (IsUsingA32()) {
4334      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
4335      if (cond.IsNotNever() &&
4336          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4337           AllowUnpredictable())) {
4338        EmitA32(0x00300010U | (cond.GetCondition() << 28) |
4339                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4340                (shift.GetType() << 5) | (rs.GetCode() << 8));
4341        return;
4342      }
4343    }
4344  }
4345  Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
4346}
4347
4348void Assembler::fldmdbx(Condition cond,
4349                        Register rn,
4350                        WriteBack write_back,
4351                        DRegisterList dreglist) {
4352  VIXL_ASSERT(AllowAssembler());
4353  CheckIT(cond);
4354  if (IsUsingT32()) {
4355    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4356    if (write_back.DoesWriteBack() &&
4357        (((dreglist.GetLength() <= 16) &&
4358          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4359         AllowUnpredictable())) {
4360      const DRegister& dreg = dreglist.GetFirstDRegister();
4361      unsigned len = dreglist.GetLength() * 2;
4362      EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4363                 (len & 0xff));
4364      AdvanceIT();
4365      return;
4366    }
4367  } else {
4368    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4369    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
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      EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4376              dreg.Encode(22, 12) | (len & 0xff));
4377      return;
4378    }
4379  }
4380  Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
4381}
4382
4383void Assembler::fldmiax(Condition cond,
4384                        Register rn,
4385                        WriteBack write_back,
4386                        DRegisterList dreglist) {
4387  VIXL_ASSERT(AllowAssembler());
4388  CheckIT(cond);
4389  if (IsUsingT32()) {
4390    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4391    if ((((dreglist.GetLength() <= 16) &&
4392          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4393         AllowUnpredictable())) {
4394      const DRegister& dreg = dreglist.GetFirstDRegister();
4395      unsigned len = dreglist.GetLength() * 2;
4396      EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4397                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4398                 (len & 0xff));
4399      AdvanceIT();
4400      return;
4401    }
4402  } else {
4403    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4404    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4405                               (dreglist.GetLastDRegister().GetCode() < 16) &&
4406                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
4407                              AllowUnpredictable())) {
4408      const DRegister& dreg = dreglist.GetFirstDRegister();
4409      unsigned len = dreglist.GetLength() * 2;
4410      EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4411              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4412              (len & 0xff));
4413      return;
4414    }
4415  }
4416  Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4417}
4418
4419void Assembler::fstmdbx(Condition cond,
4420                        Register rn,
4421                        WriteBack write_back,
4422                        DRegisterList dreglist) {
4423  VIXL_ASSERT(AllowAssembler());
4424  CheckIT(cond);
4425  if (IsUsingT32()) {
4426    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4427    if (write_back.DoesWriteBack() &&
4428        (((dreglist.GetLength() <= 16) &&
4429          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4430         AllowUnpredictable())) {
4431      const DRegister& dreg = dreglist.GetFirstDRegister();
4432      unsigned len = dreglist.GetLength() * 2;
4433      EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4434                 (len & 0xff));
4435      AdvanceIT();
4436      return;
4437    }
4438  } else {
4439    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4440    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
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      EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4447              dreg.Encode(22, 12) | (len & 0xff));
4448      return;
4449    }
4450  }
4451  Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4452}
4453
4454void Assembler::fstmiax(Condition cond,
4455                        Register rn,
4456                        WriteBack write_back,
4457                        DRegisterList dreglist) {
4458  VIXL_ASSERT(AllowAssembler());
4459  CheckIT(cond);
4460  if (IsUsingT32()) {
4461    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4462    if ((((dreglist.GetLength() <= 16) &&
4463          (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
4464         AllowUnpredictable())) {
4465      const DRegister& dreg = dreglist.GetFirstDRegister();
4466      unsigned len = dreglist.GetLength() * 2;
4467      EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4468                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4469                 (len & 0xff));
4470      AdvanceIT();
4471      return;
4472    }
4473  } else {
4474    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4475    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4476                               (dreglist.GetLastDRegister().GetCode() < 16) &&
4477                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
4478                              AllowUnpredictable())) {
4479      const DRegister& dreg = dreglist.GetFirstDRegister();
4480      unsigned len = dreglist.GetLength() * 2;
4481      EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4482              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4483              (len & 0xff));
4484      return;
4485    }
4486  }
4487  Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4488}
4489
4490void Assembler::hlt(Condition cond, uint32_t imm) {
4491  VIXL_ASSERT(AllowAssembler());
4492  CheckIT(cond);
4493  if (IsUsingT32()) {
4494    // HLT{<q>} {#}<imm> ; T1
4495    if ((imm <= 63)) {
4496      EmitT32_16(0xba80 | imm);
4497      AdvanceIT();
4498      return;
4499    }
4500  } else {
4501    // HLT{<q>} {#}<imm> ; A1
4502    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4503      EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4504              ((imm & 0xfff0) << 4));
4505      return;
4506    }
4507  }
4508  Delegate(kHlt, &Assembler::hlt, cond, imm);
4509}
4510
4511void Assembler::hvc(Condition cond, uint32_t imm) {
4512  VIXL_ASSERT(AllowAssembler());
4513  CheckIT(cond);
4514  if (IsUsingT32()) {
4515    // HVC{<q>} {#}<imm16> ; T1
4516    if ((imm <= 65535) && (OutsideITBlock() || AllowUnpredictable())) {
4517      EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4518      AdvanceIT();
4519      return;
4520    }
4521  } else {
4522    // HVC{<q>} {#}<imm16> ; A1
4523    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4524      EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4525              ((imm & 0xfff0) << 4));
4526      return;
4527    }
4528  }
4529  Delegate(kHvc, &Assembler::hvc, cond, imm);
4530}
4531
4532void Assembler::isb(Condition cond, MemoryBarrier option) {
4533  VIXL_ASSERT(AllowAssembler());
4534  CheckIT(cond);
4535  if (IsUsingT32()) {
4536    // ISB{<c>}{<q>} {<option>} ; T1
4537    EmitT32_32(0xf3bf8f60U | option.GetType());
4538    AdvanceIT();
4539    return;
4540  } else {
4541    // ISB{<c>}{<q>} {<option>} ; A1
4542    if (cond.Is(al)) {
4543      EmitA32(0xf57ff060U | option.GetType());
4544      return;
4545    }
4546  }
4547  Delegate(kIsb, &Assembler::isb, cond, option);
4548}
4549
4550void Assembler::it(Condition cond, uint16_t mask) {
4551  VIXL_ASSERT(AllowAssembler());
4552  CheckNotIT();
4553  if (mask != 0) {
4554    if ((cond.GetCondition() & 0x1) != 0) {
4555      if ((mask & 0x1) != 0) {
4556        mask ^= 0xE;
4557      } else if ((mask & 0x2) != 0) {
4558        mask ^= 0xC;
4559      } else if ((mask & 0x4) != 0) {
4560        mask ^= 0x8;
4561      }
4562    }
4563    if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
4564    SetIT(cond, mask);
4565    return;
4566  }
4567  DelegateIt(cond, mask);
4568}
4569
4570void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
4571  VIXL_ASSERT(AllowAssembler());
4572  CheckIT(cond);
4573  if (operand.IsImmediateZero()) {
4574    Register rn = operand.GetBaseRegister();
4575    if (IsUsingT32()) {
4576      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
4577      if (operand.IsOffset() &&
4578          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4579        EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4580        AdvanceIT();
4581        return;
4582      }
4583    } else {
4584      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
4585      if (operand.IsOffset() && cond.IsNotNever() &&
4586          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4587        EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4588                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4589        return;
4590      }
4591    }
4592  }
4593  Delegate(kLda, &Assembler::lda, cond, rt, operand);
4594}
4595
4596void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
4597  VIXL_ASSERT(AllowAssembler());
4598  CheckIT(cond);
4599  if (operand.IsImmediateZero()) {
4600    Register rn = operand.GetBaseRegister();
4601    if (IsUsingT32()) {
4602      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4603      if (operand.IsOffset() &&
4604          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4605        EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4606        AdvanceIT();
4607        return;
4608      }
4609    } else {
4610      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4611      if (operand.IsOffset() && cond.IsNotNever() &&
4612          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4613        EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4614                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4615        return;
4616      }
4617    }
4618  }
4619  Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4620}
4621
4622void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
4623  VIXL_ASSERT(AllowAssembler());
4624  CheckIT(cond);
4625  if (operand.IsImmediateZero()) {
4626    Register rn = operand.GetBaseRegister();
4627    if (IsUsingT32()) {
4628      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
4629      if (operand.IsOffset() &&
4630          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4631        EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4632        AdvanceIT();
4633        return;
4634      }
4635    } else {
4636      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
4637      if (operand.IsOffset() && cond.IsNotNever() &&
4638          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4639        EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4640                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4641        return;
4642      }
4643    }
4644  }
4645  Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4646}
4647
4648void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
4649  VIXL_ASSERT(AllowAssembler());
4650  CheckIT(cond);
4651  if (operand.IsImmediateZero()) {
4652    Register rn = operand.GetBaseRegister();
4653    if (IsUsingT32()) {
4654      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4655      if (operand.IsOffset() &&
4656          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4657        EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4658        AdvanceIT();
4659        return;
4660      }
4661    } else {
4662      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4663      if (operand.IsOffset() && cond.IsNotNever() &&
4664          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4665        EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4666                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4667        return;
4668      }
4669    }
4670  }
4671  Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4672}
4673
4674void Assembler::ldaexd(Condition cond,
4675                       Register rt,
4676                       Register rt2,
4677                       const MemOperand& operand) {
4678  VIXL_ASSERT(AllowAssembler());
4679  CheckIT(cond);
4680  if (operand.IsImmediateZero()) {
4681    Register rn = operand.GetBaseRegister();
4682    if (IsUsingT32()) {
4683      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
4684      if (operand.IsOffset() &&
4685          ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4686        EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4687                   (rn.GetCode() << 16));
4688        AdvanceIT();
4689        return;
4690      }
4691    } else {
4692      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4693      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
4694          operand.IsOffset() && cond.IsNotNever() &&
4695          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
4696           AllowUnpredictable())) {
4697        EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4698                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4699        return;
4700      }
4701    }
4702  }
4703  Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4704}
4705
4706void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
4707  VIXL_ASSERT(AllowAssembler());
4708  CheckIT(cond);
4709  if (operand.IsImmediateZero()) {
4710    Register rn = operand.GetBaseRegister();
4711    if (IsUsingT32()) {
4712      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4713      if (operand.IsOffset() &&
4714          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4715        EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4716        AdvanceIT();
4717        return;
4718      }
4719    } else {
4720      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4721      if (operand.IsOffset() && cond.IsNotNever() &&
4722          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4723        EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4724                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4725        return;
4726      }
4727    }
4728  }
4729  Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4730}
4731
4732void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
4733  VIXL_ASSERT(AllowAssembler());
4734  CheckIT(cond);
4735  if (operand.IsImmediateZero()) {
4736    Register rn = operand.GetBaseRegister();
4737    if (IsUsingT32()) {
4738      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4739      if (operand.IsOffset() &&
4740          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4741        EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4742        AdvanceIT();
4743        return;
4744      }
4745    } else {
4746      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4747      if (operand.IsOffset() && cond.IsNotNever() &&
4748          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
4749        EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4750                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4751        return;
4752      }
4753    }
4754  }
4755  Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4756}
4757
4758void Assembler::ldm(Condition cond,
4759                    EncodingSize size,
4760                    Register rn,
4761                    WriteBack write_back,
4762                    RegisterList registers) {
4763  VIXL_ASSERT(AllowAssembler());
4764  CheckIT(cond);
4765  if (IsUsingT32()) {
4766    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4767    if (!size.IsWide() && rn.IsLow() &&
4768        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4769         write_back.DoesWriteBack()) &&
4770        ((registers.GetList() & ~0xff) == 0)) {
4771      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4772                 GetRegisterListEncoding(registers, 0, 8));
4773      AdvanceIT();
4774      return;
4775    }
4776    // LDM{<c>}{<q>} SP!, <registers> ; T1
4777    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4778        ((registers.GetList() & ~0x80ff) == 0)) {
4779      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4780                 GetRegisterListEncoding(registers, 0, 8));
4781      AdvanceIT();
4782      return;
4783    }
4784    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
4785    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4786        (!rn.IsPC() || AllowUnpredictable())) {
4787      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4788                 (write_back.GetWriteBackUint32() << 21) |
4789                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4790                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4791                 GetRegisterListEncoding(registers, 0, 13));
4792      AdvanceIT();
4793      return;
4794    }
4795  } else {
4796    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
4797    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4798      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4799              (write_back.GetWriteBackUint32() << 21) |
4800              GetRegisterListEncoding(registers, 0, 16));
4801      return;
4802    }
4803  }
4804  Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4805}
4806
4807void Assembler::ldmda(Condition cond,
4808                      Register rn,
4809                      WriteBack write_back,
4810                      RegisterList registers) {
4811  VIXL_ASSERT(AllowAssembler());
4812  CheckIT(cond);
4813  if (IsUsingA32()) {
4814    // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4815    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4816      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4817              (write_back.GetWriteBackUint32() << 21) |
4818              GetRegisterListEncoding(registers, 0, 16));
4819      return;
4820    }
4821  }
4822  Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4823}
4824
4825void Assembler::ldmdb(Condition cond,
4826                      Register rn,
4827                      WriteBack write_back,
4828                      RegisterList registers) {
4829  VIXL_ASSERT(AllowAssembler());
4830  CheckIT(cond);
4831  if (IsUsingT32()) {
4832    // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
4833    if (((registers.GetList() & ~0xdfff) == 0) &&
4834        (!rn.IsPC() || AllowUnpredictable())) {
4835      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4836                 (write_back.GetWriteBackUint32() << 21) |
4837                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4838                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4839                 GetRegisterListEncoding(registers, 0, 13));
4840      AdvanceIT();
4841      return;
4842    }
4843  } else {
4844    // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4845    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4846      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4847              (write_back.GetWriteBackUint32() << 21) |
4848              GetRegisterListEncoding(registers, 0, 16));
4849      return;
4850    }
4851  }
4852  Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4853}
4854
4855void Assembler::ldmea(Condition cond,
4856                      Register rn,
4857                      WriteBack write_back,
4858                      RegisterList registers) {
4859  VIXL_ASSERT(AllowAssembler());
4860  CheckIT(cond);
4861  if (IsUsingT32()) {
4862    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
4863    if (((registers.GetList() & ~0xdfff) == 0) &&
4864        (!rn.IsPC() || AllowUnpredictable())) {
4865      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4866                 (write_back.GetWriteBackUint32() << 21) |
4867                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4868                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4869                 GetRegisterListEncoding(registers, 0, 13));
4870      AdvanceIT();
4871      return;
4872    }
4873  } else {
4874    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4875    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4876      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4877              (write_back.GetWriteBackUint32() << 21) |
4878              GetRegisterListEncoding(registers, 0, 16));
4879      return;
4880    }
4881  }
4882  Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4883}
4884
4885void Assembler::ldmed(Condition cond,
4886                      Register rn,
4887                      WriteBack write_back,
4888                      RegisterList registers) {
4889  VIXL_ASSERT(AllowAssembler());
4890  CheckIT(cond);
4891  if (IsUsingA32()) {
4892    // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
4893    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4894      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4895              (write_back.GetWriteBackUint32() << 21) |
4896              GetRegisterListEncoding(registers, 0, 16));
4897      return;
4898    }
4899  }
4900  Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4901}
4902
4903void Assembler::ldmfa(Condition cond,
4904                      Register rn,
4905                      WriteBack write_back,
4906                      RegisterList registers) {
4907  VIXL_ASSERT(AllowAssembler());
4908  CheckIT(cond);
4909  if (IsUsingA32()) {
4910    // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4911    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4912      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4913              (write_back.GetWriteBackUint32() << 21) |
4914              GetRegisterListEncoding(registers, 0, 16));
4915      return;
4916    }
4917  }
4918  Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4919}
4920
4921void Assembler::ldmfd(Condition cond,
4922                      EncodingSize size,
4923                      Register rn,
4924                      WriteBack write_back,
4925                      RegisterList registers) {
4926  VIXL_ASSERT(AllowAssembler());
4927  CheckIT(cond);
4928  if (IsUsingT32()) {
4929    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4930    if (!size.IsWide() && rn.IsLow() &&
4931        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4932         write_back.DoesWriteBack()) &&
4933        ((registers.GetList() & ~0xff) == 0)) {
4934      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4935                 GetRegisterListEncoding(registers, 0, 8));
4936      AdvanceIT();
4937      return;
4938    }
4939    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
4940    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4941        (!rn.IsPC() || AllowUnpredictable())) {
4942      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4943                 (write_back.GetWriteBackUint32() << 21) |
4944                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4945                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4946                 GetRegisterListEncoding(registers, 0, 13));
4947      AdvanceIT();
4948      return;
4949    }
4950  } else {
4951    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
4952    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4953      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4954              (write_back.GetWriteBackUint32() << 21) |
4955              GetRegisterListEncoding(registers, 0, 16));
4956      return;
4957    }
4958  }
4959  Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4960}
4961
4962void Assembler::ldmib(Condition cond,
4963                      Register rn,
4964                      WriteBack write_back,
4965                      RegisterList registers) {
4966  VIXL_ASSERT(AllowAssembler());
4967  CheckIT(cond);
4968  if (IsUsingA32()) {
4969    // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4970    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
4971      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4972              (write_back.GetWriteBackUint32() << 21) |
4973              GetRegisterListEncoding(registers, 0, 16));
4974      return;
4975    }
4976  }
4977  Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4978}
4979
4980void Assembler::ldr(Condition cond,
4981                    EncodingSize size,
4982                    Register rt,
4983                    const MemOperand& operand) {
4984  VIXL_ASSERT(AllowAssembler());
4985  CheckIT(cond);
4986  if (operand.IsImmediate()) {
4987    Register rn = operand.GetBaseRegister();
4988    int32_t offset = operand.GetOffsetImmediate();
4989    if (IsUsingT32()) {
4990      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4991      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4992          (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
4993        int32_t offset_ = offset >> 2;
4994        EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
4995                   ((offset_ & 0x1f) << 6));
4996        AdvanceIT();
4997        return;
4998      }
4999      // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
5000      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
5001          ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
5002        int32_t offset_ = offset >> 2;
5003        EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
5004        AdvanceIT();
5005        return;
5006      }
5007      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
5008      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5009          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5010          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5011           AllowUnpredictable())) {
5012        EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5013                   (offset & 0xfff));
5014        AdvanceIT();
5015        return;
5016      }
5017      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
5018      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5019          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5020          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5021           AllowUnpredictable())) {
5022        EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5023                   (-offset & 0xff));
5024        AdvanceIT();
5025        return;
5026      }
5027      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
5028      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5029          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5030          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5031           AllowUnpredictable())) {
5032        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5033        uint32_t offset_ = abs(offset);
5034        EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5035                   offset_ | (sign << 9));
5036        AdvanceIT();
5037        return;
5038      }
5039      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
5040      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5041          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5042          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5043           AllowUnpredictable())) {
5044        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5045        uint32_t offset_ = abs(offset);
5046        EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5047                   offset_ | (sign << 9));
5048        AdvanceIT();
5049        return;
5050      }
5051      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
5052      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5053          rn.Is(pc) && operand.IsOffset() &&
5054          ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5055           AllowUnpredictable())) {
5056        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5057        uint32_t offset_ = abs(offset);
5058        EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5059        AdvanceIT();
5060        return;
5061      }
5062    } else {
5063      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5064      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5065          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5066        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5067        uint32_t offset_ = abs(offset);
5068        EmitA32(0x05100000U | (cond.GetCondition() << 28) |
5069                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5070                (sign << 23));
5071        return;
5072      }
5073      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5074      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5075          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5076        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5077        uint32_t offset_ = abs(offset);
5078        EmitA32(0x04100000U | (cond.GetCondition() << 28) |
5079                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5080                (sign << 23));
5081        return;
5082      }
5083      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5084      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5085          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5086        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5087        uint32_t offset_ = abs(offset);
5088        EmitA32(0x05300000U | (cond.GetCondition() << 28) |
5089                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5090                (sign << 23));
5091        return;
5092      }
5093      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5094      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
5095          operand.IsOffset() && cond.IsNotNever()) {
5096        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5097        uint32_t offset_ = abs(offset);
5098        EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
5099                (rt.GetCode() << 12) | offset_ | (sign << 23));
5100        return;
5101      }
5102    }
5103  }
5104  if (operand.IsPlainRegister()) {
5105    Register rn = operand.GetBaseRegister();
5106    Sign sign = operand.GetSign();
5107    Register rm = operand.GetOffsetRegister();
5108    if (IsUsingT32()) {
5109      // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5110      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5111          sign.IsPlus() && operand.IsOffset()) {
5112        EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
5113                   (rm.GetCode() << 6));
5114        AdvanceIT();
5115        return;
5116      }
5117    }
5118  }
5119  if (operand.IsShiftedRegister()) {
5120    Register rn = operand.GetBaseRegister();
5121    Sign sign = operand.GetSign();
5122    Register rm = operand.GetOffsetRegister();
5123    Shift shift = operand.GetShift();
5124    uint32_t amount = operand.GetShiftAmount();
5125    if (IsUsingT32()) {
5126      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5127      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5128          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5129          ((!rm.IsPC() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
5130           AllowUnpredictable())) {
5131        EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5132                   rm.GetCode() | (amount << 4));
5133        AdvanceIT();
5134        return;
5135      }
5136    } else {
5137      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5138      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5139          (!rm.IsPC() || AllowUnpredictable())) {
5140        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5141        uint32_t shift_ = TypeEncodingValue(shift);
5142        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5143        EmitA32(0x07100000U | (cond.GetCondition() << 28) |
5144                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5145                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5146        return;
5147      }
5148      // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
5149      if (operand.IsShiftValid() && operand.IsPostIndex() &&
5150          cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
5151        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5152        uint32_t shift_ = TypeEncodingValue(shift);
5153        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5154        EmitA32(0x06100000U | (cond.GetCondition() << 28) |
5155                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5156                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5157        return;
5158      }
5159      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5160      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5161          (!rm.IsPC() || AllowUnpredictable())) {
5162        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5163        uint32_t shift_ = TypeEncodingValue(shift);
5164        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5165        EmitA32(0x07300000U | (cond.GetCondition() << 28) |
5166                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5167                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5168        return;
5169      }
5170    }
5171  }
5172  Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
5173}
5174
5175void Assembler::ldr(Condition cond,
5176                    EncodingSize size,
5177                    Register rt,
5178                    Location* location) {
5179  VIXL_ASSERT(AllowAssembler());
5180  CheckIT(cond);
5181  Location::Offset offset =
5182      location->IsBound()
5183          ? location->GetLocation() -
5184                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5185          : 0;
5186  if (IsUsingT32()) {
5187    // LDR{<c>}{<q>} <Rt>, <label> ; T1
5188    if (!size.IsWide() && rt.IsLow() &&
5189        ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
5190          ((offset & 0x3) == 0)) ||
5191         (!location->IsBound() && size.IsNarrow()))) {
5192      static class EmitOp : public Location::EmitOperator {
5193       public:
5194        EmitOp() : Location::EmitOperator(T32) {}
5195        virtual uint32_t Encode(uint32_t instr,
5196                                Location::Offset pc,
5197                                const Location* location) const VIXL_OVERRIDE {
5198          pc += kT32PcDelta;
5199          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5200          VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
5201                      ((offset & 0x3) == 0));
5202          const int32_t target = offset >> 2;
5203          return instr | (target & 0xff);
5204        }
5205      } immop;
5206      EmitT32_16(
5207          Link(0x4800 | (rt.GetCode() << 8), location, immop, &kT16DataInfo));
5208      AdvanceIT();
5209      return;
5210    }
5211    // LDR{<c>}{<q>} <Rt>, <label> ; T2
5212    if (!size.IsNarrow() &&
5213        ((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5214         !location->IsBound()) &&
5215        ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5216         AllowUnpredictable())) {
5217      static class EmitOp : public Location::EmitOperator {
5218       public:
5219        EmitOp() : Location::EmitOperator(T32) {}
5220        virtual uint32_t Encode(uint32_t instr,
5221                                Location::Offset pc,
5222                                const Location* location) const VIXL_OVERRIDE {
5223          pc += kT32PcDelta;
5224          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5225          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5226          uint32_t U = (offset >= 0);
5227          int32_t target = abs(offset) | (U << 12);
5228          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5229        }
5230      } immop;
5231      EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12),
5232                      location,
5233                      immop,
5234                      &kT32FarDataInfo));
5235      AdvanceIT();
5236      return;
5237    }
5238  } else {
5239    // LDR{<c>}{<q>} <Rt>, <label> ; A1
5240    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5241         !location->IsBound()) &&
5242        cond.IsNotNever()) {
5243      static class EmitOp : public Location::EmitOperator {
5244       public:
5245        EmitOp() : Location::EmitOperator(A32) {}
5246        virtual uint32_t Encode(uint32_t instr,
5247                                Location::Offset pc,
5248                                const Location* location) const VIXL_OVERRIDE {
5249          pc += kA32PcDelta;
5250          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5251          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5252          uint32_t U = (offset >= 0);
5253          int32_t target = abs(offset) | (U << 12);
5254          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5255        }
5256      } immop;
5257      EmitA32(
5258          Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5259               location,
5260               immop,
5261               &kA32FarDataInfo));
5262      return;
5263    }
5264  }
5265  Delegate(kLdr, &Assembler::ldr, cond, size, rt, location);
5266}
5267
5268bool Assembler::ldr_info(Condition cond,
5269                         EncodingSize size,
5270                         Register rt,
5271                         Location* location,
5272                         const struct ReferenceInfo** info) {
5273  VIXL_ASSERT(!location->IsBound());
5274  USE(location);
5275  if (IsUsingT32()) {
5276    // LDR{<c>}{<q>} <Rt>, <label> ; T1
5277    if (!size.IsWide() && rt.IsLow() && size.IsNarrow()) {
5278      *info = &kT16DataInfo;
5279      return true;
5280    }
5281    // LDR{<c>}{<q>} <Rt>, <label> ; T2
5282    if (!size.IsNarrow()) {
5283      *info = &kT32FarDataInfo;
5284      return true;
5285    }
5286  } else {
5287    // LDR{<c>}{<q>} <Rt>, <label> ; A1
5288    if (cond.IsNotNever()) {
5289      *info = &kA32FarDataInfo;
5290      return true;
5291    }
5292  }
5293  return false;
5294}
5295
5296void Assembler::ldrb(Condition cond,
5297                     EncodingSize size,
5298                     Register rt,
5299                     const MemOperand& operand) {
5300  VIXL_ASSERT(AllowAssembler());
5301  CheckIT(cond);
5302  if (operand.IsImmediate()) {
5303    Register rn = operand.GetBaseRegister();
5304    int32_t offset = operand.GetOffsetImmediate();
5305    if (IsUsingT32()) {
5306      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5307      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5308          (offset <= 31) && operand.IsOffset()) {
5309        EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
5310                   ((offset & 0x1f) << 6));
5311        AdvanceIT();
5312        return;
5313      }
5314      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5315      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5316          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5317        EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5318                   (offset & 0xfff));
5319        AdvanceIT();
5320        return;
5321      }
5322      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5323      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5324          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5325        EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5326                   (-offset & 0xff));
5327        AdvanceIT();
5328        return;
5329      }
5330      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5331      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5332          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5333        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5334        uint32_t offset_ = abs(offset);
5335        EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5336                   offset_ | (sign << 9));
5337        AdvanceIT();
5338        return;
5339      }
5340      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5341      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5342          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5343        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5344        uint32_t offset_ = abs(offset);
5345        EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5346                   offset_ | (sign << 9));
5347        AdvanceIT();
5348        return;
5349      }
5350      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5351      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5352          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
5353        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5354        uint32_t offset_ = abs(offset);
5355        EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5356        AdvanceIT();
5357        return;
5358      }
5359    } else {
5360      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5361      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5362          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5363          (!rt.IsPC() || AllowUnpredictable())) {
5364        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5365        uint32_t offset_ = abs(offset);
5366        EmitA32(0x05500000U | (cond.GetCondition() << 28) |
5367                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5368                (sign << 23));
5369        return;
5370      }
5371      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5372      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5373          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5374          (!rt.IsPC() || AllowUnpredictable())) {
5375        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5376        uint32_t offset_ = abs(offset);
5377        EmitA32(0x04500000U | (cond.GetCondition() << 28) |
5378                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5379                (sign << 23));
5380        return;
5381      }
5382      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5383      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5384          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5385          (!rt.IsPC() || AllowUnpredictable())) {
5386        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5387        uint32_t offset_ = abs(offset);
5388        EmitA32(0x05700000U | (cond.GetCondition() << 28) |
5389                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5390                (sign << 23));
5391        return;
5392      }
5393      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5394      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
5395          operand.IsOffset() && cond.IsNotNever() &&
5396          (!rt.IsPC() || AllowUnpredictable())) {
5397        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5398        uint32_t offset_ = abs(offset);
5399        EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
5400                (rt.GetCode() << 12) | offset_ | (sign << 23));
5401        return;
5402      }
5403    }
5404  }
5405  if (operand.IsPlainRegister()) {
5406    Register rn = operand.GetBaseRegister();
5407    Sign sign = operand.GetSign();
5408    Register rm = operand.GetOffsetRegister();
5409    if (IsUsingT32()) {
5410      // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5411      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5412          sign.IsPlus() && operand.IsOffset()) {
5413        EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
5414                   (rm.GetCode() << 6));
5415        AdvanceIT();
5416        return;
5417      }
5418    }
5419  }
5420  if (operand.IsShiftedRegister()) {
5421    Register rn = operand.GetBaseRegister();
5422    Sign sign = operand.GetSign();
5423    Register rm = operand.GetOffsetRegister();
5424    Shift shift = operand.GetShift();
5425    uint32_t amount = operand.GetShiftAmount();
5426    if (IsUsingT32()) {
5427      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5428      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5429          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
5430          (!rm.IsPC() || AllowUnpredictable())) {
5431        EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5432                   rm.GetCode() | (amount << 4));
5433        AdvanceIT();
5434        return;
5435      }
5436    } else {
5437      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5438      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5439          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
5440        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5441        uint32_t shift_ = TypeEncodingValue(shift);
5442        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5443        EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5444                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5445                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5446        return;
5447      }
5448      // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
5449      if (operand.IsShiftValid() && operand.IsPostIndex() &&
5450          cond.IsNotNever() &&
5451          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
5452        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5453        uint32_t shift_ = TypeEncodingValue(shift);
5454        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5455        EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5456                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5457                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5458        return;
5459      }
5460      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5461      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5462          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
5463        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5464        uint32_t shift_ = TypeEncodingValue(shift);
5465        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5466        EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5467                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5468                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5469        return;
5470      }
5471    }
5472  }
5473  Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5474}
5475
5476void Assembler::ldrb(Condition cond, Register rt, Location* location) {
5477  VIXL_ASSERT(AllowAssembler());
5478  CheckIT(cond);
5479  Location::Offset offset =
5480      location->IsBound()
5481          ? location->GetLocation() -
5482                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5483          : 0;
5484  if (IsUsingT32()) {
5485    // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5486    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5487         !location->IsBound()) &&
5488        !rt.Is(pc)) {
5489      static class EmitOp : public Location::EmitOperator {
5490       public:
5491        EmitOp() : Location::EmitOperator(T32) {}
5492        virtual uint32_t Encode(uint32_t instr,
5493                                Location::Offset pc,
5494                                const Location* location) const VIXL_OVERRIDE {
5495          pc += kT32PcDelta;
5496          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5497          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5498          uint32_t U = (offset >= 0);
5499          int32_t target = abs(offset) | (U << 12);
5500          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5501        }
5502      } immop;
5503      EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12),
5504                      location,
5505                      immop,
5506                      &kT32FarDataInfo));
5507      AdvanceIT();
5508      return;
5509    }
5510  } else {
5511    // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5512    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5513         !location->IsBound()) &&
5514        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
5515      static class EmitOp : public Location::EmitOperator {
5516       public:
5517        EmitOp() : Location::EmitOperator(A32) {}
5518        virtual uint32_t Encode(uint32_t instr,
5519                                Location::Offset pc,
5520                                const Location* location) const VIXL_OVERRIDE {
5521          pc += kA32PcDelta;
5522          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5523          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5524          uint32_t U = (offset >= 0);
5525          int32_t target = abs(offset) | (U << 12);
5526          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5527        }
5528      } immop;
5529      EmitA32(
5530          Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5531               location,
5532               immop,
5533               &kA32FarDataInfo));
5534      return;
5535    }
5536  }
5537  Delegate(kLdrb, &Assembler::ldrb, cond, rt, location);
5538}
5539
5540bool Assembler::ldrb_info(Condition cond,
5541                          Register rt,
5542                          Location* location,
5543                          const struct ReferenceInfo** info) {
5544  VIXL_ASSERT(!location->IsBound());
5545  USE(location);
5546  if (IsUsingT32()) {
5547    // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5548    if (!rt.Is(pc)) {
5549      *info = &kT32FarDataInfo;
5550      return true;
5551    }
5552  } else {
5553    // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5554    if (cond.IsNotNever()) {
5555      *info = &kA32FarDataInfo;
5556      return true;
5557    }
5558  }
5559  return false;
5560}
5561
5562void Assembler::ldrd(Condition cond,
5563                     Register rt,
5564                     Register rt2,
5565                     const MemOperand& operand) {
5566  VIXL_ASSERT(AllowAssembler());
5567  CheckIT(cond);
5568  if (operand.IsImmediate()) {
5569    Register rn = operand.GetBaseRegister();
5570    int32_t offset = operand.GetOffsetImmediate();
5571    if (IsUsingT32()) {
5572      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5573      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5574          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5575          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5576        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5577        uint32_t offset_ = abs(offset) >> 2;
5578        EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5579                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5580        AdvanceIT();
5581        return;
5582      }
5583      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5584      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5585          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5586          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5587        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5588        uint32_t offset_ = abs(offset) >> 2;
5589        EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5590                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5591        AdvanceIT();
5592        return;
5593      }
5594      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5595      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5596          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5597          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5598        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5599        uint32_t offset_ = abs(offset) >> 2;
5600        EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5601                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5602        AdvanceIT();
5603        return;
5604      }
5605      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5606      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5607          operand.IsOffset() &&
5608          ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5609        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5610        uint32_t offset_ = abs(offset);
5611        EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5612                   offset_ | (sign << 23));
5613        AdvanceIT();
5614        return;
5615      }
5616    } else {
5617      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5618      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5619          (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5620          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5621          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5622           AllowUnpredictable())) {
5623        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5624        uint32_t offset_ = abs(offset);
5625        EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5626                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5627                ((offset_ & 0xf0) << 4) | (sign << 23));
5628        return;
5629      }
5630      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5631      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5632          (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5633          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5634          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5635           AllowUnpredictable())) {
5636        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5637        uint32_t offset_ = abs(offset);
5638        EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5639                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5640                ((offset_ & 0xf0) << 4) | (sign << 23));
5641        return;
5642      }
5643      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5644      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5645          (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5646          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5647          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5648           AllowUnpredictable())) {
5649        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5650        uint32_t offset_ = abs(offset);
5651        EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5652                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5653                ((offset_ & 0xf0) << 4) | (sign << 23));
5654        return;
5655      }
5656      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5657      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5658          (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5659          operand.IsOffset() && cond.IsNotNever() &&
5660          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
5661           AllowUnpredictable())) {
5662        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5663        uint32_t offset_ = abs(offset);
5664        EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5665                (rt.GetCode() << 12) | (offset_ & 0xf) |
5666                ((offset_ & 0xf0) << 4) | (sign << 23));
5667        return;
5668      }
5669    }
5670  }
5671  if (operand.IsPlainRegister()) {
5672    Register rn = operand.GetBaseRegister();
5673    Sign sign = operand.GetSign();
5674    Register rm = operand.GetOffsetRegister();
5675    if (IsUsingA32()) {
5676      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5677      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5678          operand.IsOffset() && cond.IsNotNever() &&
5679          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
5680           AllowUnpredictable())) {
5681        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5682        EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5683                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5684                (sign_ << 23));
5685        return;
5686      }
5687      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5688      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5689          operand.IsPostIndex() && cond.IsNotNever() &&
5690          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
5691           AllowUnpredictable())) {
5692        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5693        EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5694                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5695                (sign_ << 23));
5696        return;
5697      }
5698      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5699      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5700          operand.IsPreIndex() && cond.IsNotNever() &&
5701          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
5702           AllowUnpredictable())) {
5703        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5704        EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5705                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5706                (sign_ << 23));
5707        return;
5708      }
5709    }
5710  }
5711  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5712}
5713
5714void Assembler::ldrd(Condition cond,
5715                     Register rt,
5716                     Register rt2,
5717                     Location* location) {
5718  VIXL_ASSERT(AllowAssembler());
5719  CheckIT(cond);
5720  Location::Offset offset =
5721      location->IsBound()
5722          ? location->GetLocation() -
5723                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5724          : 0;
5725  if (IsUsingT32()) {
5726    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5727    if (((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
5728          ((offset & 0x3) == 0)) ||
5729         !location->IsBound()) &&
5730        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
5731      static class EmitOp : public Location::EmitOperator {
5732       public:
5733        EmitOp() : Location::EmitOperator(T32) {}
5734        virtual uint32_t Encode(uint32_t instr,
5735                                Location::Offset pc,
5736                                const Location* location) const VIXL_OVERRIDE {
5737          pc += kT32PcDelta;
5738          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5739          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5740                      ((offset & 0x3) == 0));
5741          int32_t target = offset >> 2;
5742          uint32_t U = (target >= 0);
5743          target = abs(target) | (U << 8);
5744          return instr | (target & 0xff) | ((target & 0x100) << 15);
5745        }
5746      } immop;
5747      EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
5748                      location,
5749                      immop,
5750                      &kT32DataInfo));
5751      AdvanceIT();
5752      return;
5753    }
5754  } else {
5755    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5756    if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5757        ((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
5758         !location->IsBound()) &&
5759        cond.IsNotNever() &&
5760        ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) || AllowUnpredictable())) {
5761      static class EmitOp : public Location::EmitOperator {
5762       public:
5763        EmitOp() : Location::EmitOperator(A32) {}
5764        virtual uint32_t Encode(uint32_t instr,
5765                                Location::Offset pc,
5766                                const Location* location) const VIXL_OVERRIDE {
5767          pc += kA32PcDelta;
5768          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
5769          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5770          uint32_t U = (offset >= 0);
5771          int32_t target = abs(offset) | (U << 8);
5772          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5773                 ((target & 0x100) << 15);
5774        }
5775      } immop;
5776      EmitA32(
5777          Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5778               location,
5779               immop,
5780               &kA32VeryNearDataInfo));
5781      return;
5782    }
5783  }
5784  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, location);
5785}
5786
5787bool Assembler::ldrd_info(Condition cond,
5788                          Register rt,
5789                          Register rt2,
5790                          Location* location,
5791                          const struct ReferenceInfo** info) {
5792  VIXL_ASSERT(!location->IsBound());
5793  USE(location);
5794  if (IsUsingT32()) {
5795    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5796    if (true) {
5797      *info = &kT32DataInfo;
5798      return true;
5799    }
5800  } else {
5801    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5802    if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5803        cond.IsNotNever()) {
5804      *info = &kA32VeryNearDataInfo;
5805      return true;
5806    }
5807  }
5808  return false;
5809}
5810
5811void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
5812  VIXL_ASSERT(AllowAssembler());
5813  CheckIT(cond);
5814  if (operand.IsImmediate()) {
5815    Register rn = operand.GetBaseRegister();
5816    int32_t offset = operand.GetOffsetImmediate();
5817    if (IsUsingT32()) {
5818      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5819      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
5820          operand.IsOffset() &&
5821          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5822        int32_t offset_ = offset >> 2;
5823        EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5824                   (offset_ & 0xff));
5825        AdvanceIT();
5826        return;
5827      }
5828    } else {
5829      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
5830      if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
5831          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5832        EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5833                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5834        return;
5835      }
5836    }
5837  }
5838  Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5839}
5840
5841void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
5842  VIXL_ASSERT(AllowAssembler());
5843  CheckIT(cond);
5844  if (operand.IsImmediateZero()) {
5845    Register rn = operand.GetBaseRegister();
5846    if (IsUsingT32()) {
5847      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
5848      if (operand.IsOffset() &&
5849          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5850        EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5851        AdvanceIT();
5852        return;
5853      }
5854    } else {
5855      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
5856      if (operand.IsOffset() && cond.IsNotNever() &&
5857          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5858        EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5859                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5860        return;
5861      }
5862    }
5863  }
5864  Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5865}
5866
5867void Assembler::ldrexd(Condition cond,
5868                       Register rt,
5869                       Register rt2,
5870                       const MemOperand& operand) {
5871  VIXL_ASSERT(AllowAssembler());
5872  CheckIT(cond);
5873  if (operand.IsImmediateZero()) {
5874    Register rn = operand.GetBaseRegister();
5875    if (IsUsingT32()) {
5876      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
5877      if (operand.IsOffset() &&
5878          ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5879        EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5880                   (rn.GetCode() << 16));
5881        AdvanceIT();
5882        return;
5883      }
5884    } else {
5885      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5886      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5887          operand.IsOffset() && cond.IsNotNever() &&
5888          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
5889           AllowUnpredictable())) {
5890        EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5891                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5892        return;
5893      }
5894    }
5895  }
5896  Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5897}
5898
5899void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
5900  VIXL_ASSERT(AllowAssembler());
5901  CheckIT(cond);
5902  if (operand.IsImmediateZero()) {
5903    Register rn = operand.GetBaseRegister();
5904    if (IsUsingT32()) {
5905      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
5906      if (operand.IsOffset() &&
5907          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5908        EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5909        AdvanceIT();
5910        return;
5911      }
5912    } else {
5913      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
5914      if (operand.IsOffset() && cond.IsNotNever() &&
5915          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
5916        EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5917                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5918        return;
5919      }
5920    }
5921  }
5922  Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5923}
5924
5925void Assembler::ldrh(Condition cond,
5926                     EncodingSize size,
5927                     Register rt,
5928                     const MemOperand& operand) {
5929  VIXL_ASSERT(AllowAssembler());
5930  CheckIT(cond);
5931  if (operand.IsImmediate()) {
5932    Register rn = operand.GetBaseRegister();
5933    int32_t offset = operand.GetOffsetImmediate();
5934    if (IsUsingT32()) {
5935      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5936      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5937          (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
5938        int32_t offset_ = offset >> 1;
5939        EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5940                   ((offset_ & 0x1f) << 6));
5941        AdvanceIT();
5942        return;
5943      }
5944      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5945      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5946          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5947        EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5948                   (offset & 0xfff));
5949        AdvanceIT();
5950        return;
5951      }
5952      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5953      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5954          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5955        EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5956                   (-offset & 0xff));
5957        AdvanceIT();
5958        return;
5959      }
5960      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5961      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5962          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5963        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5964        uint32_t offset_ = abs(offset);
5965        EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5966                   offset_ | (sign << 9));
5967        AdvanceIT();
5968        return;
5969      }
5970      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5971      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5972          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5973        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5974        uint32_t offset_ = abs(offset);
5975        EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5976                   offset_ | (sign << 9));
5977        AdvanceIT();
5978        return;
5979      }
5980      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5981      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5982          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
5983        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5984        uint32_t offset_ = abs(offset);
5985        EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5986        AdvanceIT();
5987        return;
5988      }
5989    } else {
5990      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5991      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5992          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5993          (!rt.IsPC() || AllowUnpredictable())) {
5994        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5995        uint32_t offset_ = abs(offset);
5996        EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
5997                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5998                ((offset_ & 0xf0) << 4) | (sign << 23));
5999        return;
6000      }
6001      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
6002      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
6003          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6004          (!rt.IsPC() || AllowUnpredictable())) {
6005        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6006        uint32_t offset_ = abs(offset);
6007        EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
6008                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6009                ((offset_ & 0xf0) << 4) | (sign << 23));
6010        return;
6011      }
6012      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
6013      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
6014          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6015          (!rt.IsPC() || AllowUnpredictable())) {
6016        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6017        uint32_t offset_ = abs(offset);
6018        EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
6019                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6020                ((offset_ & 0xf0) << 4) | (sign << 23));
6021        return;
6022      }
6023      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6024      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
6025          operand.IsOffset() && cond.IsNotNever() &&
6026          (!rt.IsPC() || AllowUnpredictable())) {
6027        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6028        uint32_t offset_ = abs(offset);
6029        EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
6030                (rt.GetCode() << 12) | (offset_ & 0xf) |
6031                ((offset_ & 0xf0) << 4) | (sign << 23));
6032        return;
6033      }
6034    }
6035  }
6036  if (operand.IsPlainRegister()) {
6037    Register rn = operand.GetBaseRegister();
6038    Sign sign = operand.GetSign();
6039    Register rm = operand.GetOffsetRegister();
6040    if (IsUsingT32()) {
6041      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6042      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
6043          sign.IsPlus() && operand.IsOffset()) {
6044        EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
6045                   (rm.GetCode() << 6));
6046        AdvanceIT();
6047        return;
6048      }
6049    } else {
6050      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6051      if (operand.IsOffset() && cond.IsNotNever() &&
6052          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6053        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6054        EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
6055                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6056                (sign_ << 23));
6057        return;
6058      }
6059      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6060      if (operand.IsPostIndex() && cond.IsNotNever() &&
6061          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6062        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6063        EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
6064                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6065                (sign_ << 23));
6066        return;
6067      }
6068      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6069      if (operand.IsPreIndex() && cond.IsNotNever() &&
6070          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6071        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6072        EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
6073                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6074                (sign_ << 23));
6075        return;
6076      }
6077    }
6078  }
6079  if (operand.IsShiftedRegister()) {
6080    Register rn = operand.GetBaseRegister();
6081    Sign sign = operand.GetSign();
6082    Register rm = operand.GetOffsetRegister();
6083    Shift shift = operand.GetShift();
6084    uint32_t amount = operand.GetShiftAmount();
6085    if (IsUsingT32()) {
6086      // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6087      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6088          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6089          (!rm.IsPC() || AllowUnpredictable())) {
6090        EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6091                   rm.GetCode() | (amount << 4));
6092        AdvanceIT();
6093        return;
6094      }
6095    }
6096  }
6097  Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
6098}
6099
6100void Assembler::ldrh(Condition cond, Register rt, Location* location) {
6101  VIXL_ASSERT(AllowAssembler());
6102  CheckIT(cond);
6103  Location::Offset offset =
6104      location->IsBound()
6105          ? location->GetLocation() -
6106                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6107          : 0;
6108  if (IsUsingT32()) {
6109    // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6110    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6111         !location->IsBound()) &&
6112        !rt.Is(pc)) {
6113      static class EmitOp : public Location::EmitOperator {
6114       public:
6115        EmitOp() : Location::EmitOperator(T32) {}
6116        virtual uint32_t Encode(uint32_t instr,
6117                                Location::Offset pc,
6118                                const Location* location) const VIXL_OVERRIDE {
6119          pc += kT32PcDelta;
6120          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
6121          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
6122          uint32_t U = (offset >= 0);
6123          int32_t target = abs(offset) | (U << 12);
6124          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6125        }
6126      } immop;
6127      EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12),
6128                      location,
6129                      immop,
6130                      &kT32FarDataInfo));
6131      AdvanceIT();
6132      return;
6133    }
6134  } else {
6135    // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6136    if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6137         !location->IsBound()) &&
6138        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
6139      static class EmitOp : public Location::EmitOperator {
6140       public:
6141        EmitOp() : Location::EmitOperator(A32) {}
6142        virtual uint32_t Encode(uint32_t instr,
6143                                Location::Offset pc,
6144                                const Location* location) const VIXL_OVERRIDE {
6145          pc += kA32PcDelta;
6146          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
6147          VIXL_ASSERT((offset >= -255) && (offset <= 255));
6148          uint32_t U = (offset >= 0);
6149          int32_t target = abs(offset) | (U << 8);
6150          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6151                 ((target & 0x100) << 15);
6152        }
6153      } immop;
6154      EmitA32(
6155          Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6156               location,
6157               immop,
6158               &kA32VeryNearDataInfo));
6159      return;
6160    }
6161  }
6162  Delegate(kLdrh, &Assembler::ldrh, cond, rt, location);
6163}
6164
6165bool Assembler::ldrh_info(Condition cond,
6166                          Register rt,
6167                          Location* location,
6168                          const struct ReferenceInfo** info) {
6169  VIXL_ASSERT(!location->IsBound());
6170  USE(location);
6171  if (IsUsingT32()) {
6172    // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6173    if (!rt.Is(pc)) {
6174      *info = &kT32FarDataInfo;
6175      return true;
6176    }
6177  } else {
6178    // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6179    if (cond.IsNotNever()) {
6180      *info = &kA32VeryNearDataInfo;
6181      return true;
6182    }
6183  }
6184  return false;
6185}
6186
6187void Assembler::ldrsb(Condition cond,
6188                      EncodingSize size,
6189                      Register rt,
6190                      const MemOperand& operand) {
6191  VIXL_ASSERT(AllowAssembler());
6192  CheckIT(cond);
6193  if (operand.IsImmediate()) {
6194    Register rn = operand.GetBaseRegister();
6195    int32_t offset = operand.GetOffsetImmediate();
6196    if (IsUsingT32()) {
6197      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6198      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
6199          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6200        EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6201                   (offset & 0xfff));
6202        AdvanceIT();
6203        return;
6204      }
6205      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6206      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
6207          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6208        EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6209                   (-offset & 0xff));
6210        AdvanceIT();
6211        return;
6212      }
6213      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6214      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6215          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6216        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6217        uint32_t offset_ = abs(offset);
6218        EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6219                   offset_ | (sign << 9));
6220        AdvanceIT();
6221        return;
6222      }
6223      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6224      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6225          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6226        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6227        uint32_t offset_ = abs(offset);
6228        EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6229                   offset_ | (sign << 9));
6230        AdvanceIT();
6231        return;
6232      }
6233      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6234      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
6235          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
6236        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6237        uint32_t offset_ = abs(offset);
6238        EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6239        AdvanceIT();
6240        return;
6241      }
6242    } else {
6243      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
6244      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
6245          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6246          (!rt.IsPC() || AllowUnpredictable())) {
6247        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6248        uint32_t offset_ = abs(offset);
6249        EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
6250                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6251                ((offset_ & 0xf0) << 4) | (sign << 23));
6252        return;
6253      }
6254      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
6255      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
6256          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6257          (!rt.IsPC() || AllowUnpredictable())) {
6258        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6259        uint32_t offset_ = abs(offset);
6260        EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
6261                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6262                ((offset_ & 0xf0) << 4) | (sign << 23));
6263        return;
6264      }
6265      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
6266      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
6267          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6268          (!rt.IsPC() || AllowUnpredictable())) {
6269        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6270        uint32_t offset_ = abs(offset);
6271        EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
6272                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6273                ((offset_ & 0xf0) << 4) | (sign << 23));
6274        return;
6275      }
6276      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6277      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
6278          operand.IsOffset() && cond.IsNotNever() &&
6279          (!rt.IsPC() || AllowUnpredictable())) {
6280        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6281        uint32_t offset_ = abs(offset);
6282        EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
6283                (rt.GetCode() << 12) | (offset_ & 0xf) |
6284                ((offset_ & 0xf0) << 4) | (sign << 23));
6285        return;
6286      }
6287    }
6288  }
6289  if (operand.IsPlainRegister()) {
6290    Register rn = operand.GetBaseRegister();
6291    Sign sign = operand.GetSign();
6292    Register rm = operand.GetOffsetRegister();
6293    if (IsUsingT32()) {
6294      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6295      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
6296          sign.IsPlus() && operand.IsOffset()) {
6297        EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
6298                   (rm.GetCode() << 6));
6299        AdvanceIT();
6300        return;
6301      }
6302    } else {
6303      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6304      if (operand.IsOffset() && cond.IsNotNever() &&
6305          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6306        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6307        EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
6308                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6309                (sign_ << 23));
6310        return;
6311      }
6312      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6313      if (operand.IsPostIndex() && cond.IsNotNever() &&
6314          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6315        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6316        EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
6317                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6318                (sign_ << 23));
6319        return;
6320      }
6321      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6322      if (operand.IsPreIndex() && cond.IsNotNever() &&
6323          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6324        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6325        EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
6326                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6327                (sign_ << 23));
6328        return;
6329      }
6330    }
6331  }
6332  if (operand.IsShiftedRegister()) {
6333    Register rn = operand.GetBaseRegister();
6334    Sign sign = operand.GetSign();
6335    Register rm = operand.GetOffsetRegister();
6336    Shift shift = operand.GetShift();
6337    uint32_t amount = operand.GetShiftAmount();
6338    if (IsUsingT32()) {
6339      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6340      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6341          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6342          (!rm.IsPC() || AllowUnpredictable())) {
6343        EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6344                   rm.GetCode() | (amount << 4));
6345        AdvanceIT();
6346        return;
6347      }
6348    }
6349  }
6350  Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
6351}
6352
6353void Assembler::ldrsb(Condition cond, Register rt, Location* location) {
6354  VIXL_ASSERT(AllowAssembler());
6355  CheckIT(cond);
6356  Location::Offset offset =
6357      location->IsBound()
6358          ? location->GetLocation() -
6359                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6360          : 0;
6361  if (IsUsingT32()) {
6362    // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6363    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6364         !location->IsBound()) &&
6365        !rt.Is(pc)) {
6366      static class EmitOp : public Location::EmitOperator {
6367       public:
6368        EmitOp() : Location::EmitOperator(T32) {}
6369        virtual uint32_t Encode(uint32_t instr,
6370                                Location::Offset pc,
6371                                const Location* location) const VIXL_OVERRIDE {
6372          pc += kT32PcDelta;
6373          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
6374          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
6375          uint32_t U = (offset >= 0);
6376          int32_t target = abs(offset) | (U << 12);
6377          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6378        }
6379      } immop;
6380      EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12),
6381                      location,
6382                      immop,
6383                      &kT32FarDataInfo));
6384      AdvanceIT();
6385      return;
6386    }
6387  } else {
6388    // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6389    if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6390         !location->IsBound()) &&
6391        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
6392      static class EmitOp : public Location::EmitOperator {
6393       public:
6394        EmitOp() : Location::EmitOperator(A32) {}
6395        virtual uint32_t Encode(uint32_t instr,
6396                                Location::Offset pc,
6397                                const Location* location) const VIXL_OVERRIDE {
6398          pc += kA32PcDelta;
6399          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
6400          VIXL_ASSERT((offset >= -255) && (offset <= 255));
6401          uint32_t U = (offset >= 0);
6402          int32_t target = abs(offset) | (U << 8);
6403          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6404                 ((target & 0x100) << 15);
6405        }
6406      } immop;
6407      EmitA32(
6408          Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6409               location,
6410               immop,
6411               &kA32VeryNearDataInfo));
6412      return;
6413    }
6414  }
6415  Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, location);
6416}
6417
6418bool Assembler::ldrsb_info(Condition cond,
6419                           Register rt,
6420                           Location* location,
6421                           const struct ReferenceInfo** info) {
6422  VIXL_ASSERT(!location->IsBound());
6423  USE(location);
6424  if (IsUsingT32()) {
6425    // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6426    if (!rt.Is(pc)) {
6427      *info = &kT32FarDataInfo;
6428      return true;
6429    }
6430  } else {
6431    // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6432    if (cond.IsNotNever()) {
6433      *info = &kA32VeryNearDataInfo;
6434      return true;
6435    }
6436  }
6437  return false;
6438}
6439
6440void Assembler::ldrsh(Condition cond,
6441                      EncodingSize size,
6442                      Register rt,
6443                      const MemOperand& operand) {
6444  VIXL_ASSERT(AllowAssembler());
6445  CheckIT(cond);
6446  if (operand.IsImmediate()) {
6447    Register rn = operand.GetBaseRegister();
6448    int32_t offset = operand.GetOffsetImmediate();
6449    if (IsUsingT32()) {
6450      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6451      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
6452          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6453        EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6454                   (offset & 0xfff));
6455        AdvanceIT();
6456        return;
6457      }
6458      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6459      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
6460          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6461        EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6462                   (-offset & 0xff));
6463        AdvanceIT();
6464        return;
6465      }
6466      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6467      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6468          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6469        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6470        uint32_t offset_ = abs(offset);
6471        EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6472                   offset_ | (sign << 9));
6473        AdvanceIT();
6474        return;
6475      }
6476      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6477      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
6478          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
6479        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6480        uint32_t offset_ = abs(offset);
6481        EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6482                   offset_ | (sign << 9));
6483        AdvanceIT();
6484        return;
6485      }
6486      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6487      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
6488          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
6489        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6490        uint32_t offset_ = abs(offset);
6491        EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6492        AdvanceIT();
6493        return;
6494      }
6495    } else {
6496      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
6497      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
6498          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6499          (!rt.IsPC() || AllowUnpredictable())) {
6500        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6501        uint32_t offset_ = abs(offset);
6502        EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
6503                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6504                ((offset_ & 0xf0) << 4) | (sign << 23));
6505        return;
6506      }
6507      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
6508      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
6509          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6510          (!rt.IsPC() || AllowUnpredictable())) {
6511        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6512        uint32_t offset_ = abs(offset);
6513        EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
6514                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6515                ((offset_ & 0xf0) << 4) | (sign << 23));
6516        return;
6517      }
6518      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
6519      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
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(0x017000f0U | (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>, [PC, #<_plusminus_><imm_1>] ; A1
6530      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
6531          operand.IsOffset() && cond.IsNotNever() &&
6532          (!rt.IsPC() || AllowUnpredictable())) {
6533        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6534        uint32_t offset_ = abs(offset);
6535        EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
6536                (rt.GetCode() << 12) | (offset_ & 0xf) |
6537                ((offset_ & 0xf0) << 4) | (sign << 23));
6538        return;
6539      }
6540    }
6541  }
6542  if (operand.IsPlainRegister()) {
6543    Register rn = operand.GetBaseRegister();
6544    Sign sign = operand.GetSign();
6545    Register rm = operand.GetOffsetRegister();
6546    if (IsUsingT32()) {
6547      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6548      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
6549          sign.IsPlus() && operand.IsOffset()) {
6550        EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
6551                   (rm.GetCode() << 6));
6552        AdvanceIT();
6553        return;
6554      }
6555    } else {
6556      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6557      if (operand.IsOffset() && cond.IsNotNever() &&
6558          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6559        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6560        EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6561                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6562                (sign_ << 23));
6563        return;
6564      }
6565      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6566      if (operand.IsPostIndex() && cond.IsNotNever() &&
6567          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6568        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6569        EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6570                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6571                (sign_ << 23));
6572        return;
6573      }
6574      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6575      if (operand.IsPreIndex() && cond.IsNotNever() &&
6576          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6577        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6578        EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6579                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6580                (sign_ << 23));
6581        return;
6582      }
6583    }
6584  }
6585  if (operand.IsShiftedRegister()) {
6586    Register rn = operand.GetBaseRegister();
6587    Sign sign = operand.GetSign();
6588    Register rm = operand.GetOffsetRegister();
6589    Shift shift = operand.GetShift();
6590    uint32_t amount = operand.GetShiftAmount();
6591    if (IsUsingT32()) {
6592      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6593      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6594          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6595          (!rm.IsPC() || AllowUnpredictable())) {
6596        EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6597                   rm.GetCode() | (amount << 4));
6598        AdvanceIT();
6599        return;
6600      }
6601    }
6602  }
6603  Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6604}
6605
6606void Assembler::ldrsh(Condition cond, Register rt, Location* location) {
6607  VIXL_ASSERT(AllowAssembler());
6608  CheckIT(cond);
6609  Location::Offset offset =
6610      location->IsBound()
6611          ? location->GetLocation() -
6612                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6613          : 0;
6614  if (IsUsingT32()) {
6615    // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6616    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6617         !location->IsBound()) &&
6618        !rt.Is(pc)) {
6619      static class EmitOp : public Location::EmitOperator {
6620       public:
6621        EmitOp() : Location::EmitOperator(T32) {}
6622        virtual uint32_t Encode(uint32_t instr,
6623                                Location::Offset pc,
6624                                const Location* location) const VIXL_OVERRIDE {
6625          pc += kT32PcDelta;
6626          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
6627          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
6628          uint32_t U = (offset >= 0);
6629          int32_t target = abs(offset) | (U << 12);
6630          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6631        }
6632      } immop;
6633      EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12),
6634                      location,
6635                      immop,
6636                      &kT32FarDataInfo));
6637      AdvanceIT();
6638      return;
6639    }
6640  } else {
6641    // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6642    if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6643         !location->IsBound()) &&
6644        cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
6645      static class EmitOp : public Location::EmitOperator {
6646       public:
6647        EmitOp() : Location::EmitOperator(A32) {}
6648        virtual uint32_t Encode(uint32_t instr,
6649                                Location::Offset pc,
6650                                const Location* location) const VIXL_OVERRIDE {
6651          pc += kA32PcDelta;
6652          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
6653          VIXL_ASSERT((offset >= -255) && (offset <= 255));
6654          uint32_t U = (offset >= 0);
6655          int32_t target = abs(offset) | (U << 8);
6656          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6657                 ((target & 0x100) << 15);
6658        }
6659      } immop;
6660      EmitA32(
6661          Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6662               location,
6663               immop,
6664               &kA32VeryNearDataInfo));
6665      return;
6666    }
6667  }
6668  Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, location);
6669}
6670
6671bool Assembler::ldrsh_info(Condition cond,
6672                           Register rt,
6673                           Location* location,
6674                           const struct ReferenceInfo** info) {
6675  VIXL_ASSERT(!location->IsBound());
6676  USE(location);
6677  if (IsUsingT32()) {
6678    // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6679    if (!rt.Is(pc)) {
6680      *info = &kT32FarDataInfo;
6681      return true;
6682    }
6683  } else {
6684    // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6685    if (cond.IsNotNever()) {
6686      *info = &kA32VeryNearDataInfo;
6687      return true;
6688    }
6689  }
6690  return false;
6691}
6692
6693void Assembler::lsl(Condition cond,
6694                    EncodingSize size,
6695                    Register rd,
6696                    Register rm,
6697                    const Operand& operand) {
6698  VIXL_ASSERT(AllowAssembler());
6699  CheckIT(cond);
6700  if (operand.IsImmediate()) {
6701    uint32_t imm = operand.GetImmediate();
6702    if (IsUsingT32()) {
6703      // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6704      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6705          (imm >= 1) && (imm <= 31)) {
6706        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6707        AdvanceIT();
6708        return;
6709      }
6710      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6711      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6712          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6713        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6714                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6715        AdvanceIT();
6716        return;
6717      }
6718    } else {
6719      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6720      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6721        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6722                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6723        return;
6724      }
6725    }
6726  }
6727  if (operand.IsPlainRegister()) {
6728    Register rs = operand.GetBaseRegister();
6729    if (IsUsingT32()) {
6730      // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6731      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6732          rs.IsLow()) {
6733        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6734        AdvanceIT();
6735        return;
6736      }
6737      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6738      if (!size.IsNarrow() &&
6739          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6740        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6741                   rs.GetCode());
6742        AdvanceIT();
6743        return;
6744      }
6745    } else {
6746      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6747      if (cond.IsNotNever() &&
6748          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6749        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6750                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6751        return;
6752      }
6753    }
6754  }
6755  Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6756}
6757
6758void Assembler::lsls(Condition cond,
6759                     EncodingSize size,
6760                     Register rd,
6761                     Register rm,
6762                     const Operand& operand) {
6763  VIXL_ASSERT(AllowAssembler());
6764  CheckIT(cond);
6765  if (operand.IsImmediate()) {
6766    uint32_t imm = operand.GetImmediate();
6767    if (IsUsingT32()) {
6768      // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6769      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6770          (imm >= 1) && (imm <= 31)) {
6771        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6772        AdvanceIT();
6773        return;
6774      }
6775      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6776      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6777          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6778        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6779                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6780        AdvanceIT();
6781        return;
6782      }
6783    } else {
6784      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6785      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6786        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6787                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6788        return;
6789      }
6790    }
6791  }
6792  if (operand.IsPlainRegister()) {
6793    Register rs = operand.GetBaseRegister();
6794    if (IsUsingT32()) {
6795      // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6796      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6797          rs.IsLow()) {
6798        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6799        AdvanceIT();
6800        return;
6801      }
6802      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6803      if (!size.IsNarrow() &&
6804          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6805        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6806                   rs.GetCode());
6807        AdvanceIT();
6808        return;
6809      }
6810    } else {
6811      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6812      if (cond.IsNotNever() &&
6813          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6814        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6815                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6816        return;
6817      }
6818    }
6819  }
6820  Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6821}
6822
6823void Assembler::lsr(Condition cond,
6824                    EncodingSize size,
6825                    Register rd,
6826                    Register rm,
6827                    const Operand& operand) {
6828  VIXL_ASSERT(AllowAssembler());
6829  CheckIT(cond);
6830  if (operand.IsImmediate()) {
6831    uint32_t imm = operand.GetImmediate();
6832    if (IsUsingT32()) {
6833      // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6834      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6835          (imm >= 1) && (imm <= 32)) {
6836        uint32_t amount_ = imm % 32;
6837        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6838                   (amount_ << 6));
6839        AdvanceIT();
6840        return;
6841      }
6842      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6843      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6844          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6845        uint32_t amount_ = imm % 32;
6846        EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6847                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6848        AdvanceIT();
6849        return;
6850      }
6851    } else {
6852      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6853      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6854        uint32_t amount_ = imm % 32;
6855        EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6856                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6857        return;
6858      }
6859    }
6860  }
6861  if (operand.IsPlainRegister()) {
6862    Register rs = operand.GetBaseRegister();
6863    if (IsUsingT32()) {
6864      // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6865      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6866          rs.IsLow()) {
6867        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6868        AdvanceIT();
6869        return;
6870      }
6871      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6872      if (!size.IsNarrow() &&
6873          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6874        EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6875                   rs.GetCode());
6876        AdvanceIT();
6877        return;
6878      }
6879    } else {
6880      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6881      if (cond.IsNotNever() &&
6882          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6883        EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6884                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6885        return;
6886      }
6887    }
6888  }
6889  Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6890}
6891
6892void Assembler::lsrs(Condition cond,
6893                     EncodingSize size,
6894                     Register rd,
6895                     Register rm,
6896                     const Operand& operand) {
6897  VIXL_ASSERT(AllowAssembler());
6898  CheckIT(cond);
6899  if (operand.IsImmediate()) {
6900    uint32_t imm = operand.GetImmediate();
6901    if (IsUsingT32()) {
6902      // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6903      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6904          (imm >= 1) && (imm <= 32)) {
6905        uint32_t amount_ = imm % 32;
6906        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6907                   (amount_ << 6));
6908        AdvanceIT();
6909        return;
6910      }
6911      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6912      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6913          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6914        uint32_t amount_ = imm % 32;
6915        EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6916                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6917        AdvanceIT();
6918        return;
6919      }
6920    } else {
6921      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6922      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6923        uint32_t amount_ = imm % 32;
6924        EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6925                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6926        return;
6927      }
6928    }
6929  }
6930  if (operand.IsPlainRegister()) {
6931    Register rs = operand.GetBaseRegister();
6932    if (IsUsingT32()) {
6933      // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6934      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6935          rs.IsLow()) {
6936        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6937        AdvanceIT();
6938        return;
6939      }
6940      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6941      if (!size.IsNarrow() &&
6942          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6943        EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6944                   rs.GetCode());
6945        AdvanceIT();
6946        return;
6947      }
6948    } else {
6949      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6950      if (cond.IsNotNever() &&
6951          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
6952        EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6953                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6954        return;
6955      }
6956    }
6957  }
6958  Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6959}
6960
6961void Assembler::mla(
6962    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6963  VIXL_ASSERT(AllowAssembler());
6964  CheckIT(cond);
6965  if (IsUsingT32()) {
6966    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6967    if (!ra.Is(pc) &&
6968        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6969      EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6970                 rm.GetCode() | (ra.GetCode() << 12));
6971      AdvanceIT();
6972      return;
6973    }
6974  } else {
6975    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6976    if (cond.IsNotNever() &&
6977        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6978         AllowUnpredictable())) {
6979      EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6980              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6981      return;
6982    }
6983  }
6984  Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
6985}
6986
6987void Assembler::mlas(
6988    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6989  VIXL_ASSERT(AllowAssembler());
6990  CheckIT(cond);
6991  if (IsUsingA32()) {
6992    // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6993    if (cond.IsNotNever() &&
6994        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6995         AllowUnpredictable())) {
6996      EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6997              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6998      return;
6999    }
7000  }
7001  Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
7002}
7003
7004void Assembler::mls(
7005    Condition cond, Register rd, Register rn, Register rm, Register ra) {
7006  VIXL_ASSERT(AllowAssembler());
7007  CheckIT(cond);
7008  if (IsUsingT32()) {
7009    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
7010    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7011         AllowUnpredictable())) {
7012      EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7013                 rm.GetCode() | (ra.GetCode() << 12));
7014      AdvanceIT();
7015      return;
7016    }
7017  } else {
7018    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
7019    if (cond.IsNotNever() &&
7020        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7021         AllowUnpredictable())) {
7022      EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7023              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7024      return;
7025    }
7026  }
7027  Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
7028}
7029
7030void Assembler::mov(Condition cond,
7031                    EncodingSize size,
7032                    Register rd,
7033                    const Operand& operand) {
7034  VIXL_ASSERT(AllowAssembler());
7035  CheckIT(cond);
7036  if (operand.IsImmediateShiftedRegister()) {
7037    Register rm = operand.GetBaseRegister();
7038    if (operand.IsPlainRegister()) {
7039      if (IsUsingT32()) {
7040        // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
7041        if (!size.IsWide() &&
7042            ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
7043             AllowUnpredictable())) {
7044          EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
7045                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
7046          AdvanceIT();
7047          return;
7048        }
7049      }
7050    }
7051    Shift shift = operand.GetShift();
7052    uint32_t amount = operand.GetShiftAmount();
7053    if (IsUsingT32()) {
7054      // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7055      if (InITBlock() && !size.IsWide() && rd.IsLow() &&
7056          shift.IsValidAmount(amount) && rm.IsLow() &&
7057          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
7058          ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
7059        uint32_t amount_ = amount % 32;
7060        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7061                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7062        AdvanceIT();
7063        return;
7064      }
7065      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
7066      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7067          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7068        uint32_t amount_ = amount % 32;
7069        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7070                   (operand.GetTypeEncodingValue() << 4) |
7071                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7072        AdvanceIT();
7073        return;
7074      }
7075    } else {
7076      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7077      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7078        uint32_t amount_ = amount % 32;
7079        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
7080                (rd.GetCode() << 12) | rm.GetCode() |
7081                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7082        return;
7083      }
7084    }
7085  }
7086  if (operand.IsRegisterShiftedRegister()) {
7087    Register rm = operand.GetBaseRegister();
7088    Shift shift = operand.GetShift();
7089    Register rs = operand.GetShiftRegister();
7090    if (IsUsingT32()) {
7091      // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7092      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7093          shift.IsASR() && rs.IsLow()) {
7094        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
7095        AdvanceIT();
7096        return;
7097      }
7098      // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7099      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7100          shift.IsLSL() && rs.IsLow()) {
7101        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
7102        AdvanceIT();
7103        return;
7104      }
7105      // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7106      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7107          shift.IsLSR() && rs.IsLow()) {
7108        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
7109        AdvanceIT();
7110        return;
7111      }
7112      // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7113      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7114          shift.IsROR() && rs.IsLow()) {
7115        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
7116        AdvanceIT();
7117        return;
7118      }
7119      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
7120      if (!size.IsNarrow() &&
7121          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7122        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
7123                   (shift.GetType() << 21) | rs.GetCode());
7124        AdvanceIT();
7125        return;
7126      }
7127    } else {
7128      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7129      if (cond.IsNotNever() &&
7130          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7131        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
7132                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7133                (rs.GetCode() << 8));
7134        return;
7135      }
7136    }
7137  }
7138  if (operand.IsImmediate()) {
7139    uint32_t imm = operand.GetImmediate();
7140    if (IsUsingT32()) {
7141      ImmediateT32 immediate_t32(imm);
7142      // MOV<c>{<q>} <Rd>, #<imm8> ; T1
7143      if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7144        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7145        AdvanceIT();
7146        return;
7147      }
7148      // MOV{<c>}{<q>} <Rd>, #<const> ; T2
7149      if (!size.IsNarrow() && immediate_t32.IsValid() &&
7150          (!rd.IsPC() || AllowUnpredictable())) {
7151        EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
7152                   (immediate_t32.GetEncodingValue() & 0xff) |
7153                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7154                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7155        AdvanceIT();
7156        return;
7157      }
7158      // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
7159      if (!size.IsNarrow() && (imm <= 65535) &&
7160          (!rd.IsPC() || AllowUnpredictable())) {
7161        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7162                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7163                   ((imm & 0xf000) << 4));
7164        AdvanceIT();
7165        return;
7166      }
7167    } else {
7168      ImmediateA32 immediate_a32(imm);
7169      // MOV{<c>}{<q>} <Rd>, #<const> ; A1
7170      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7171        EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
7172                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7173        return;
7174      }
7175      // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
7176      if ((imm <= 65535) && cond.IsNotNever() &&
7177          (!rd.IsPC() || AllowUnpredictable())) {
7178        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7179                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7180        return;
7181      }
7182    }
7183  }
7184  Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
7185}
7186
7187void Assembler::movs(Condition cond,
7188                     EncodingSize size,
7189                     Register rd,
7190                     const Operand& operand) {
7191  VIXL_ASSERT(AllowAssembler());
7192  CheckIT(cond);
7193  if (operand.IsImmediateShiftedRegister()) {
7194    Register rm = operand.GetBaseRegister();
7195    Shift shift = operand.GetShift();
7196    uint32_t amount = operand.GetShiftAmount();
7197    if (IsUsingT32()) {
7198      // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7199      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
7200          shift.IsValidAmount(amount) && rm.IsLow() &&
7201          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
7202        uint32_t amount_ = amount % 32;
7203        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7204                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7205        AdvanceIT();
7206        return;
7207      }
7208      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
7209      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7210          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7211        uint32_t amount_ = amount % 32;
7212        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7213                   (operand.GetTypeEncodingValue() << 4) |
7214                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7215        AdvanceIT();
7216        return;
7217      }
7218    } else {
7219      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7220      if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
7221          (!rd.IsPC() || AllowUnpredictable())) {
7222        uint32_t amount_ = amount % 32;
7223        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
7224                (rd.GetCode() << 12) | rm.GetCode() |
7225                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7226        return;
7227      }
7228    }
7229  }
7230  if (operand.IsRegisterShiftedRegister()) {
7231    Register rm = operand.GetBaseRegister();
7232    Shift shift = operand.GetShift();
7233    Register rs = operand.GetShiftRegister();
7234    if (IsUsingT32()) {
7235      // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7236      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7237          shift.IsASR() && rs.IsLow()) {
7238        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
7239        AdvanceIT();
7240        return;
7241      }
7242      // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7243      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7244          shift.IsLSL() && rs.IsLow()) {
7245        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
7246        AdvanceIT();
7247        return;
7248      }
7249      // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7250      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7251          shift.IsLSR() && rs.IsLow()) {
7252        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
7253        AdvanceIT();
7254        return;
7255      }
7256      // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7257      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
7258          shift.IsROR() && rs.IsLow()) {
7259        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
7260        AdvanceIT();
7261        return;
7262      }
7263      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
7264      if (!size.IsNarrow() &&
7265          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7266        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
7267                   (shift.GetType() << 21) | rs.GetCode());
7268        AdvanceIT();
7269        return;
7270      }
7271    } else {
7272      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7273      if (cond.IsNotNever() &&
7274          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7275        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
7276                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7277                (rs.GetCode() << 8));
7278        return;
7279      }
7280    }
7281  }
7282  if (operand.IsImmediate()) {
7283    uint32_t imm = operand.GetImmediate();
7284    if (IsUsingT32()) {
7285      ImmediateT32 immediate_t32(imm);
7286      // MOVS{<q>} <Rd>, #<imm8> ; T1
7287      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7288        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7289        AdvanceIT();
7290        return;
7291      }
7292      // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
7293      if (!size.IsNarrow() && immediate_t32.IsValid() &&
7294          (!rd.IsPC() || AllowUnpredictable())) {
7295        EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
7296                   (immediate_t32.GetEncodingValue() & 0xff) |
7297                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7298                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7299        AdvanceIT();
7300        return;
7301      }
7302    } else {
7303      ImmediateA32 immediate_a32(imm);
7304      // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
7305      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7306        EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
7307                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7308        return;
7309      }
7310    }
7311  }
7312  Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
7313}
7314
7315void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
7316  VIXL_ASSERT(AllowAssembler());
7317  CheckIT(cond);
7318  if (operand.IsImmediate()) {
7319    uint32_t imm = operand.GetImmediate();
7320    if (IsUsingT32()) {
7321      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
7322      if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
7323        EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
7324                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7325                   ((imm & 0xf000) << 4));
7326        AdvanceIT();
7327        return;
7328      }
7329    } else {
7330      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
7331      if ((imm <= 65535) && cond.IsNotNever() &&
7332          (!rd.IsPC() || AllowUnpredictable())) {
7333        EmitA32(0x03400000U | (cond.GetCondition() << 28) |
7334                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7335        return;
7336      }
7337    }
7338  }
7339  Delegate(kMovt, &Assembler::movt, cond, rd, operand);
7340}
7341
7342void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
7343  VIXL_ASSERT(AllowAssembler());
7344  CheckIT(cond);
7345  if (operand.IsImmediate()) {
7346    uint32_t imm = operand.GetImmediate();
7347    if (IsUsingT32()) {
7348      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
7349      if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
7350        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7351                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7352                   ((imm & 0xf000) << 4));
7353        AdvanceIT();
7354        return;
7355      }
7356    } else {
7357      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
7358      if ((imm <= 65535) && cond.IsNotNever() &&
7359          (!rd.IsPC() || AllowUnpredictable())) {
7360        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7361                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7362        return;
7363      }
7364    }
7365  }
7366  Delegate(kMovw, &Assembler::movw, cond, rd, operand);
7367}
7368
7369void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
7370  VIXL_ASSERT(AllowAssembler());
7371  CheckIT(cond);
7372  if (IsUsingT32()) {
7373    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
7374    if ((!rd.IsPC() || AllowUnpredictable())) {
7375      EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
7376      AdvanceIT();
7377      return;
7378    }
7379  } else {
7380    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
7381    if (cond.IsNotNever() && (!rd.IsPC() || AllowUnpredictable())) {
7382      EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7383              (spec_reg.GetReg() << 22));
7384      return;
7385    }
7386  }
7387  Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
7388}
7389
7390void Assembler::msr(Condition cond,
7391                    MaskedSpecialRegister spec_reg,
7392                    const Operand& operand) {
7393  VIXL_ASSERT(AllowAssembler());
7394  CheckIT(cond);
7395  if (operand.IsImmediate()) {
7396    uint32_t imm = operand.GetImmediate();
7397    if (IsUsingA32()) {
7398      ImmediateA32 immediate_a32(imm);
7399      // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
7400      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7401        EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
7402                ((spec_reg.GetReg() & 0xf) << 16) |
7403                ((spec_reg.GetReg() & 0x10) << 18) |
7404                immediate_a32.GetEncodingValue());
7405        return;
7406      }
7407    }
7408  }
7409  if (operand.IsPlainRegister()) {
7410    Register rn = operand.GetBaseRegister();
7411    if (IsUsingT32()) {
7412      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
7413      if ((!rn.IsPC() || AllowUnpredictable())) {
7414        EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
7415                   ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
7416        AdvanceIT();
7417        return;
7418      }
7419    } else {
7420      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
7421      if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
7422        EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
7423                ((spec_reg.GetReg() & 0xf) << 16) |
7424                ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
7425        return;
7426      }
7427    }
7428  }
7429  Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
7430}
7431
7432void Assembler::mul(
7433    Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
7434  VIXL_ASSERT(AllowAssembler());
7435  CheckIT(cond);
7436  if (IsUsingT32()) {
7437    // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7438    if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
7439        rm.IsLow()) {
7440      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7441      AdvanceIT();
7442      return;
7443    }
7444    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
7445    if (!size.IsNarrow() &&
7446        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7447      EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7448                 rm.GetCode());
7449      AdvanceIT();
7450      return;
7451    }
7452  } else {
7453    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
7454    if (cond.IsNotNever() &&
7455        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7456      EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7457              rn.GetCode() | (rm.GetCode() << 8));
7458      return;
7459    }
7460  }
7461  Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
7462}
7463
7464void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
7465  VIXL_ASSERT(AllowAssembler());
7466  CheckIT(cond);
7467  if (IsUsingT32()) {
7468    // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7469    if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
7470      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7471      AdvanceIT();
7472      return;
7473    }
7474  } else {
7475    // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
7476    if (cond.IsNotNever() &&
7477        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7478      EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7479              rn.GetCode() | (rm.GetCode() << 8));
7480      return;
7481    }
7482  }
7483  Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
7484}
7485
7486void Assembler::mvn(Condition cond,
7487                    EncodingSize size,
7488                    Register rd,
7489                    const Operand& operand) {
7490  VIXL_ASSERT(AllowAssembler());
7491  CheckIT(cond);
7492  if (operand.IsImmediate()) {
7493    uint32_t imm = operand.GetImmediate();
7494    if (IsUsingT32()) {
7495      ImmediateT32 immediate_t32(imm);
7496      // MVN{<c>}{<q>} <Rd>, #<const> ; T1
7497      if (!size.IsNarrow() && immediate_t32.IsValid() &&
7498          (!rd.IsPC() || AllowUnpredictable())) {
7499        EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
7500                   (immediate_t32.GetEncodingValue() & 0xff) |
7501                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7502                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7503        AdvanceIT();
7504        return;
7505      }
7506    } else {
7507      ImmediateA32 immediate_a32(imm);
7508      // MVN{<c>}{<q>} <Rd>, #<const> ; A1
7509      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7510        EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
7511                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7512        return;
7513      }
7514    }
7515  }
7516  if (operand.IsImmediateShiftedRegister()) {
7517    Register rm = operand.GetBaseRegister();
7518    if (operand.IsPlainRegister()) {
7519      if (IsUsingT32()) {
7520        // MVN<c>{<q>} <Rd>, <Rm> ; T1
7521        if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7522          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7523          AdvanceIT();
7524          return;
7525        }
7526      }
7527    }
7528    Shift shift = operand.GetShift();
7529    uint32_t amount = operand.GetShiftAmount();
7530    if (IsUsingT32()) {
7531      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7532      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7533          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7534        uint32_t amount_ = amount % 32;
7535        EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7536                   (operand.GetTypeEncodingValue() << 4) |
7537                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7538        AdvanceIT();
7539        return;
7540      }
7541    } else {
7542      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7543      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7544        uint32_t amount_ = amount % 32;
7545        EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
7546                (rd.GetCode() << 12) | rm.GetCode() |
7547                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7548        return;
7549      }
7550    }
7551  }
7552  if (operand.IsRegisterShiftedRegister()) {
7553    Register rm = operand.GetBaseRegister();
7554    Shift shift = operand.GetShift();
7555    Register rs = operand.GetShiftRegister();
7556    if (IsUsingA32()) {
7557      // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7558      if (cond.IsNotNever() &&
7559          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7560        EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
7561                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7562                (rs.GetCode() << 8));
7563        return;
7564      }
7565    }
7566  }
7567  Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
7568}
7569
7570void Assembler::mvns(Condition cond,
7571                     EncodingSize size,
7572                     Register rd,
7573                     const Operand& operand) {
7574  VIXL_ASSERT(AllowAssembler());
7575  CheckIT(cond);
7576  if (operand.IsImmediate()) {
7577    uint32_t imm = operand.GetImmediate();
7578    if (IsUsingT32()) {
7579      ImmediateT32 immediate_t32(imm);
7580      // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
7581      if (!size.IsNarrow() && immediate_t32.IsValid() &&
7582          (!rd.IsPC() || AllowUnpredictable())) {
7583        EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
7584                   (immediate_t32.GetEncodingValue() & 0xff) |
7585                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7586                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7587        AdvanceIT();
7588        return;
7589      }
7590    } else {
7591      ImmediateA32 immediate_a32(imm);
7592      // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
7593      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7594        EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
7595                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7596        return;
7597      }
7598    }
7599  }
7600  if (operand.IsImmediateShiftedRegister()) {
7601    Register rm = operand.GetBaseRegister();
7602    if (operand.IsPlainRegister()) {
7603      if (IsUsingT32()) {
7604        // MVNS{<q>} <Rd>, <Rm> ; T1
7605        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7606          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7607          AdvanceIT();
7608          return;
7609        }
7610      }
7611    }
7612    Shift shift = operand.GetShift();
7613    uint32_t amount = operand.GetShiftAmount();
7614    if (IsUsingT32()) {
7615      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7616      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7617          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7618        uint32_t amount_ = amount % 32;
7619        EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7620                   (operand.GetTypeEncodingValue() << 4) |
7621                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7622        AdvanceIT();
7623        return;
7624      }
7625    } else {
7626      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7627      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7628        uint32_t amount_ = amount % 32;
7629        EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7630                (rd.GetCode() << 12) | rm.GetCode() |
7631                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7632        return;
7633      }
7634    }
7635  }
7636  if (operand.IsRegisterShiftedRegister()) {
7637    Register rm = operand.GetBaseRegister();
7638    Shift shift = operand.GetShift();
7639    Register rs = operand.GetShiftRegister();
7640    if (IsUsingA32()) {
7641      // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7642      if (cond.IsNotNever() &&
7643          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
7644        EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7645                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7646                (rs.GetCode() << 8));
7647        return;
7648      }
7649    }
7650  }
7651  Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7652}
7653
7654void Assembler::nop(Condition cond, EncodingSize size) {
7655  VIXL_ASSERT(AllowAssembler());
7656  CheckIT(cond);
7657  if (IsUsingT32()) {
7658    // NOP{<c>}{<q>} ; T1
7659    if (!size.IsWide()) {
7660      EmitT32_16(0xbf00);
7661      AdvanceIT();
7662      return;
7663    }
7664    // NOP{<c>}.W ; T2
7665    if (!size.IsNarrow()) {
7666      EmitT32_32(0xf3af8000U);
7667      AdvanceIT();
7668      return;
7669    }
7670  } else {
7671    // NOP{<c>}{<q>} ; A1
7672    if (cond.IsNotNever()) {
7673      EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7674      return;
7675    }
7676  }
7677  Delegate(kNop, &Assembler::nop, cond, size);
7678}
7679
7680void Assembler::orn(Condition cond,
7681                    Register rd,
7682                    Register rn,
7683                    const Operand& operand) {
7684  VIXL_ASSERT(AllowAssembler());
7685  CheckIT(cond);
7686  if (operand.IsImmediate()) {
7687    uint32_t imm = operand.GetImmediate();
7688    if (IsUsingT32()) {
7689      ImmediateT32 immediate_t32(imm);
7690      // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7691      if (immediate_t32.IsValid() && !rn.Is(pc) &&
7692          (!rd.IsPC() || AllowUnpredictable())) {
7693        EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7694                   (immediate_t32.GetEncodingValue() & 0xff) |
7695                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7696                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7697        AdvanceIT();
7698        return;
7699      }
7700    }
7701  }
7702  if (operand.IsImmediateShiftedRegister()) {
7703    Register rm = operand.GetBaseRegister();
7704    Shift shift = operand.GetShift();
7705    uint32_t amount = operand.GetShiftAmount();
7706    if (IsUsingT32()) {
7707      // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7708      if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7709          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7710        uint32_t amount_ = amount % 32;
7711        EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7712                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7713                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7714        AdvanceIT();
7715        return;
7716      }
7717    }
7718  }
7719  Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7720}
7721
7722void Assembler::orns(Condition cond,
7723                     Register rd,
7724                     Register rn,
7725                     const Operand& operand) {
7726  VIXL_ASSERT(AllowAssembler());
7727  CheckIT(cond);
7728  if (operand.IsImmediate()) {
7729    uint32_t imm = operand.GetImmediate();
7730    if (IsUsingT32()) {
7731      ImmediateT32 immediate_t32(imm);
7732      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7733      if (immediate_t32.IsValid() && !rn.Is(pc) &&
7734          (!rd.IsPC() || AllowUnpredictable())) {
7735        EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7736                   (immediate_t32.GetEncodingValue() & 0xff) |
7737                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7738                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7739        AdvanceIT();
7740        return;
7741      }
7742    }
7743  }
7744  if (operand.IsImmediateShiftedRegister()) {
7745    Register rm = operand.GetBaseRegister();
7746    Shift shift = operand.GetShift();
7747    uint32_t amount = operand.GetShiftAmount();
7748    if (IsUsingT32()) {
7749      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7750      if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7751          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7752        uint32_t amount_ = amount % 32;
7753        EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7754                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7755                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7756        AdvanceIT();
7757        return;
7758      }
7759    }
7760  }
7761  Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7762}
7763
7764void Assembler::orr(Condition cond,
7765                    EncodingSize size,
7766                    Register rd,
7767                    Register rn,
7768                    const Operand& operand) {
7769  VIXL_ASSERT(AllowAssembler());
7770  CheckIT(cond);
7771  if (operand.IsImmediate()) {
7772    uint32_t imm = operand.GetImmediate();
7773    if (IsUsingT32()) {
7774      ImmediateT32 immediate_t32(imm);
7775      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7776      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7777          (!rd.IsPC() || AllowUnpredictable())) {
7778        EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7779                   (immediate_t32.GetEncodingValue() & 0xff) |
7780                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7781                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7782        AdvanceIT();
7783        return;
7784      }
7785    } else {
7786      ImmediateA32 immediate_a32(imm);
7787      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7788      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7789        EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7790                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7791                immediate_a32.GetEncodingValue());
7792        return;
7793      }
7794    }
7795  }
7796  if (operand.IsImmediateShiftedRegister()) {
7797    Register rm = operand.GetBaseRegister();
7798    if (operand.IsPlainRegister()) {
7799      if (IsUsingT32()) {
7800        // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7801        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7802            rm.IsLow()) {
7803          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7804          AdvanceIT();
7805          return;
7806        }
7807      }
7808    }
7809    Shift shift = operand.GetShift();
7810    uint32_t amount = operand.GetShiftAmount();
7811    if (IsUsingT32()) {
7812      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7813      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7814          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7815        uint32_t amount_ = amount % 32;
7816        EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7817                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7818                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7819        AdvanceIT();
7820        return;
7821      }
7822    } else {
7823      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7824      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7825        uint32_t amount_ = amount % 32;
7826        EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7827                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7828                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7829        return;
7830      }
7831    }
7832  }
7833  if (operand.IsRegisterShiftedRegister()) {
7834    Register rm = operand.GetBaseRegister();
7835    Shift shift = operand.GetShift();
7836    Register rs = operand.GetShiftRegister();
7837    if (IsUsingA32()) {
7838      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7839      if (cond.IsNotNever() &&
7840          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7841           AllowUnpredictable())) {
7842        EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7843                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7844                (shift.GetType() << 5) | (rs.GetCode() << 8));
7845        return;
7846      }
7847    }
7848  }
7849  Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7850}
7851
7852void Assembler::orrs(Condition cond,
7853                     EncodingSize size,
7854                     Register rd,
7855                     Register rn,
7856                     const Operand& operand) {
7857  VIXL_ASSERT(AllowAssembler());
7858  CheckIT(cond);
7859  if (operand.IsImmediate()) {
7860    uint32_t imm = operand.GetImmediate();
7861    if (IsUsingT32()) {
7862      ImmediateT32 immediate_t32(imm);
7863      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7864      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7865          (!rd.IsPC() || AllowUnpredictable())) {
7866        EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7867                   (immediate_t32.GetEncodingValue() & 0xff) |
7868                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7869                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7870        AdvanceIT();
7871        return;
7872      }
7873    } else {
7874      ImmediateA32 immediate_a32(imm);
7875      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7876      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7877        EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7878                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7879                immediate_a32.GetEncodingValue());
7880        return;
7881      }
7882    }
7883  }
7884  if (operand.IsImmediateShiftedRegister()) {
7885    Register rm = operand.GetBaseRegister();
7886    if (operand.IsPlainRegister()) {
7887      if (IsUsingT32()) {
7888        // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7889        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7890            rm.IsLow()) {
7891          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7892          AdvanceIT();
7893          return;
7894        }
7895      }
7896    }
7897    Shift shift = operand.GetShift();
7898    uint32_t amount = operand.GetShiftAmount();
7899    if (IsUsingT32()) {
7900      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7901      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7902          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7903        uint32_t amount_ = amount % 32;
7904        EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7905                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7906                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7907        AdvanceIT();
7908        return;
7909      }
7910    } else {
7911      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7912      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7913        uint32_t amount_ = amount % 32;
7914        EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7915                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7916                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7917        return;
7918      }
7919    }
7920  }
7921  if (operand.IsRegisterShiftedRegister()) {
7922    Register rm = operand.GetBaseRegister();
7923    Shift shift = operand.GetShift();
7924    Register rs = operand.GetShiftRegister();
7925    if (IsUsingA32()) {
7926      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7927      if (cond.IsNotNever() &&
7928          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7929           AllowUnpredictable())) {
7930        EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7931                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7932                (shift.GetType() << 5) | (rs.GetCode() << 8));
7933        return;
7934      }
7935    }
7936  }
7937  Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7938}
7939
7940void Assembler::pkhbt(Condition cond,
7941                      Register rd,
7942                      Register rn,
7943                      const Operand& operand) {
7944  VIXL_ASSERT(AllowAssembler());
7945  CheckIT(cond);
7946  if (operand.IsImmediateShiftedRegister()) {
7947    Register rm = operand.GetBaseRegister();
7948    Shift shift = operand.GetShift();
7949    uint32_t amount = operand.GetShiftAmount();
7950    if (IsUsingT32()) {
7951      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
7952      if (shift.IsLSL() && shift.IsValidAmount(amount) &&
7953          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7954        EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7955                   rm.GetCode() | ((amount & 0x3) << 6) |
7956                   ((amount & 0x1c) << 10));
7957        AdvanceIT();
7958        return;
7959      }
7960    } else {
7961      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
7962      if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever() &&
7963          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7964        EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7965                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7966                (amount << 7));
7967        return;
7968      }
7969    }
7970  }
7971  Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7972}
7973
7974void Assembler::pkhtb(Condition cond,
7975                      Register rd,
7976                      Register rn,
7977                      const Operand& operand) {
7978  VIXL_ASSERT(AllowAssembler());
7979  CheckIT(cond);
7980  if (operand.IsImmediateShiftedRegister()) {
7981    Register rm = operand.GetBaseRegister();
7982    Shift shift = operand.GetShift();
7983    uint32_t amount = operand.GetShiftAmount();
7984    if (IsUsingT32()) {
7985      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
7986      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7987          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
7988        uint32_t amount_ = amount % 32;
7989        EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7990                   rm.GetCode() | ((amount_ & 0x3) << 6) |
7991                   ((amount_ & 0x1c) << 10));
7992        AdvanceIT();
7993        return;
7994      }
7995    } else {
7996      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
7997      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7998          cond.IsNotNever() &&
7999          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8000        uint32_t amount_ = amount % 32;
8001        EmitA32(0x06800050U | (cond.GetCondition() << 28) |
8002                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8003                (amount_ << 7));
8004        return;
8005      }
8006    }
8007  }
8008  Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
8009}
8010
8011void Assembler::pld(Condition cond, Location* location) {
8012  VIXL_ASSERT(AllowAssembler());
8013  CheckIT(cond);
8014  Location::Offset offset =
8015      location->IsBound()
8016          ? location->GetLocation() -
8017                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8018          : 0;
8019  if (IsUsingT32()) {
8020    // PLD{<c>}{<q>} <label> ; T1
8021    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8022         !location->IsBound())) {
8023      static class EmitOp : public Location::EmitOperator {
8024       public:
8025        EmitOp() : Location::EmitOperator(T32) {}
8026        virtual uint32_t Encode(uint32_t instr,
8027                                Location::Offset pc,
8028                                const Location* location) const VIXL_OVERRIDE {
8029          pc += kT32PcDelta;
8030          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
8031          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
8032          uint32_t U = (offset >= 0);
8033          int32_t target = abs(offset) | (U << 12);
8034          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8035        }
8036      } immop;
8037      EmitT32_32(Link(0xf81ff000U, location, immop, &kT32FarDataInfo));
8038      AdvanceIT();
8039      return;
8040    }
8041  } else {
8042    // PLD{<c>}{<q>} <label> ; A1
8043    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8044         !location->IsBound())) {
8045      if (cond.Is(al)) {
8046        static class EmitOp : public Location::EmitOperator {
8047         public:
8048          EmitOp() : Location::EmitOperator(A32) {}
8049          virtual uint32_t Encode(uint32_t instr,
8050                                  Location::Offset pc,
8051                                  const Location* location) const
8052              VIXL_OVERRIDE {
8053            pc += kA32PcDelta;
8054            Location::Offset offset =
8055                location->GetLocation() - AlignDown(pc, 4);
8056            VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
8057            uint32_t U = (offset >= 0);
8058            int32_t target = abs(offset) | (U << 12);
8059            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8060          }
8061        } immop;
8062        EmitA32(Link(0xf55ff000U, location, immop, &kA32FarDataInfo));
8063        return;
8064      }
8065    }
8066  }
8067  Delegate(kPld, &Assembler::pld, cond, location);
8068}
8069
8070bool Assembler::pld_info(Condition cond,
8071                         Location* location,
8072                         const struct ReferenceInfo** info) {
8073  VIXL_ASSERT(!location->IsBound());
8074  USE(location);
8075  USE(cond);
8076  if (IsUsingT32()) {
8077    // PLD{<c>}{<q>} <label> ; T1
8078    if (true) {
8079      *info = &kT32FarDataInfo;
8080      return true;
8081    }
8082  } else {
8083    // PLD{<c>}{<q>} <label> ; A1
8084    if (true) {
8085      *info = &kA32FarDataInfo;
8086      return true;
8087    }
8088  }
8089  return false;
8090}
8091
8092void Assembler::pld(Condition cond, const MemOperand& operand) {
8093  VIXL_ASSERT(AllowAssembler());
8094  CheckIT(cond);
8095  if (operand.IsImmediate()) {
8096    Register rn = operand.GetBaseRegister();
8097    int32_t offset = operand.GetOffsetImmediate();
8098    if (IsUsingT32()) {
8099      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
8100      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8101          operand.IsOffset()) {
8102        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8103        uint32_t offset_ = abs(offset);
8104        EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
8105        AdvanceIT();
8106        return;
8107      }
8108    } else {
8109      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
8110      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8111          operand.IsOffset()) {
8112        if (cond.Is(al)) {
8113          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8114          uint32_t offset_ = abs(offset);
8115          EmitA32(0xf55ff000U | offset_ | (sign << 23));
8116          return;
8117        }
8118      }
8119    }
8120  }
8121  if (operand.IsImmediate()) {
8122    Register rn = operand.GetBaseRegister();
8123    int32_t offset = operand.GetOffsetImmediate();
8124    if (IsUsingT32()) {
8125      // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
8126      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8127          ((rn.GetCode() & 0xf) != 0xf)) {
8128        EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8129        AdvanceIT();
8130        return;
8131      }
8132      // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
8133      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8134          ((rn.GetCode() & 0xf) != 0xf)) {
8135        EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8136        AdvanceIT();
8137        return;
8138      }
8139    } else {
8140      // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
8141      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
8142          ((rn.GetCode() & 0xf) != 0xf)) {
8143        if (cond.Is(al)) {
8144          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8145          uint32_t offset_ = abs(offset);
8146          EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8147          return;
8148        }
8149      }
8150    }
8151  }
8152  if (operand.IsShiftedRegister()) {
8153    Register rn = operand.GetBaseRegister();
8154    Sign sign = operand.GetSign();
8155    Register rm = operand.GetOffsetRegister();
8156    Shift shift = operand.GetShift();
8157    uint32_t amount = operand.GetShiftAmount();
8158    if (IsUsingT32()) {
8159      // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
8160      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
8161          ((rn.GetCode() & 0xf) != 0xf) &&
8162          (!rm.IsPC() || AllowUnpredictable())) {
8163        EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
8164                   (amount << 4));
8165        AdvanceIT();
8166        return;
8167      }
8168    } else {
8169      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
8170      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8171          (!rm.IsPC() || AllowUnpredictable())) {
8172        if (cond.Is(al)) {
8173          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8174          uint32_t amount_ = amount % 32;
8175          EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
8176                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8177          return;
8178        }
8179      }
8180      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
8181      if (shift.IsRRX() && operand.IsOffset() &&
8182          (!rm.IsPC() || AllowUnpredictable())) {
8183        if (cond.Is(al)) {
8184          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8185          EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
8186                  (sign_ << 23));
8187          return;
8188        }
8189      }
8190    }
8191  }
8192  Delegate(kPld, &Assembler::pld, cond, operand);
8193}
8194
8195void Assembler::pldw(Condition cond, const MemOperand& operand) {
8196  VIXL_ASSERT(AllowAssembler());
8197  CheckIT(cond);
8198  if (operand.IsImmediate()) {
8199    Register rn = operand.GetBaseRegister();
8200    int32_t offset = operand.GetOffsetImmediate();
8201    if (IsUsingT32()) {
8202      // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
8203      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8204          ((rn.GetCode() & 0xf) != 0xf)) {
8205        EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8206        AdvanceIT();
8207        return;
8208      }
8209      // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
8210      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8211          ((rn.GetCode() & 0xf) != 0xf)) {
8212        EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8213        AdvanceIT();
8214        return;
8215      }
8216    } else {
8217      // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
8218      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
8219          ((rn.GetCode() & 0xf) != 0xf)) {
8220        if (cond.Is(al)) {
8221          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8222          uint32_t offset_ = abs(offset);
8223          EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8224          return;
8225        }
8226      }
8227    }
8228  }
8229  if (operand.IsShiftedRegister()) {
8230    Register rn = operand.GetBaseRegister();
8231    Sign sign = operand.GetSign();
8232    Register rm = operand.GetOffsetRegister();
8233    Shift shift = operand.GetShift();
8234    uint32_t amount = operand.GetShiftAmount();
8235    if (IsUsingT32()) {
8236      // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
8237      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
8238          ((rn.GetCode() & 0xf) != 0xf) &&
8239          (!rm.IsPC() || AllowUnpredictable())) {
8240        EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
8241                   (amount << 4));
8242        AdvanceIT();
8243        return;
8244      }
8245    } else {
8246      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
8247      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8248          (!rm.IsPC() || AllowUnpredictable())) {
8249        if (cond.Is(al)) {
8250          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8251          uint32_t amount_ = amount % 32;
8252          EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
8253                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8254          return;
8255        }
8256      }
8257      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
8258      if (shift.IsRRX() && operand.IsOffset() &&
8259          (!rm.IsPC() || AllowUnpredictable())) {
8260        if (cond.Is(al)) {
8261          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8262          EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
8263                  (sign_ << 23));
8264          return;
8265        }
8266      }
8267    }
8268  }
8269  Delegate(kPldw, &Assembler::pldw, cond, operand);
8270}
8271
8272void Assembler::pli(Condition cond, const MemOperand& operand) {
8273  VIXL_ASSERT(AllowAssembler());
8274  CheckIT(cond);
8275  if (operand.IsImmediate()) {
8276    Register rn = operand.GetBaseRegister();
8277    int32_t offset = operand.GetOffsetImmediate();
8278    if (IsUsingT32()) {
8279      // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
8280      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8281          ((rn.GetCode() & 0xf) != 0xf)) {
8282        EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8283        AdvanceIT();
8284        return;
8285      }
8286      // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
8287      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8288          ((rn.GetCode() & 0xf) != 0xf)) {
8289        EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8290        AdvanceIT();
8291        return;
8292      }
8293    } else {
8294      // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
8295      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
8296          ((rn.GetCode() & 0xf) != 0xf)) {
8297        if (cond.Is(al)) {
8298          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8299          uint32_t offset_ = abs(offset);
8300          EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8301          return;
8302        }
8303      }
8304    }
8305  }
8306  if (operand.IsImmediate()) {
8307    Register rn = operand.GetBaseRegister();
8308    int32_t offset = operand.GetOffsetImmediate();
8309    if (IsUsingT32()) {
8310      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
8311      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8312          operand.IsOffset()) {
8313        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8314        uint32_t offset_ = abs(offset);
8315        EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
8316        AdvanceIT();
8317        return;
8318      }
8319    } else {
8320      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
8321      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8322          operand.IsOffset()) {
8323        if (cond.Is(al)) {
8324          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8325          uint32_t offset_ = abs(offset);
8326          EmitA32(0xf45ff000U | offset_ | (sign << 23));
8327          return;
8328        }
8329      }
8330    }
8331  }
8332  if (operand.IsShiftedRegister()) {
8333    Register rn = operand.GetBaseRegister();
8334    Sign sign = operand.GetSign();
8335    Register rm = operand.GetOffsetRegister();
8336    Shift shift = operand.GetShift();
8337    uint32_t amount = operand.GetShiftAmount();
8338    if (IsUsingT32()) {
8339      // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
8340      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
8341          ((rn.GetCode() & 0xf) != 0xf) &&
8342          (!rm.IsPC() || AllowUnpredictable())) {
8343        EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
8344                   (amount << 4));
8345        AdvanceIT();
8346        return;
8347      }
8348    } else {
8349      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
8350      if (shift.IsRRX() && operand.IsOffset() &&
8351          (!rm.IsPC() || AllowUnpredictable())) {
8352        if (cond.Is(al)) {
8353          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8354          EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
8355                  (sign_ << 23));
8356          return;
8357        }
8358      }
8359      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
8360      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8361          (!rm.IsPC() || AllowUnpredictable())) {
8362        if (cond.Is(al)) {
8363          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8364          uint32_t amount_ = amount % 32;
8365          EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
8366                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8367          return;
8368        }
8369      }
8370    }
8371  }
8372  Delegate(kPli, &Assembler::pli, cond, operand);
8373}
8374
8375void Assembler::pli(Condition cond, Location* location) {
8376  VIXL_ASSERT(AllowAssembler());
8377  CheckIT(cond);
8378  Location::Offset offset =
8379      location->IsBound()
8380          ? location->GetLocation() -
8381                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8382          : 0;
8383  if (IsUsingT32()) {
8384    // PLI{<c>}{<q>} <label> ; T3
8385    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8386         !location->IsBound())) {
8387      static class EmitOp : public Location::EmitOperator {
8388       public:
8389        EmitOp() : Location::EmitOperator(T32) {}
8390        virtual uint32_t Encode(uint32_t instr,
8391                                Location::Offset pc,
8392                                const Location* location) const VIXL_OVERRIDE {
8393          pc += kT32PcDelta;
8394          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
8395          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
8396          uint32_t U = (offset >= 0);
8397          int32_t target = abs(offset) | (U << 12);
8398          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8399        }
8400      } immop;
8401      EmitT32_32(Link(0xf91ff000U, location, immop, &kT32FarDataInfo));
8402      AdvanceIT();
8403      return;
8404    }
8405  } else {
8406    // PLI{<c>}{<q>} <label> ; A1
8407    if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8408         !location->IsBound())) {
8409      if (cond.Is(al)) {
8410        static class EmitOp : public Location::EmitOperator {
8411         public:
8412          EmitOp() : Location::EmitOperator(A32) {}
8413          virtual uint32_t Encode(uint32_t instr,
8414                                  Location::Offset pc,
8415                                  const Location* location) const
8416              VIXL_OVERRIDE {
8417            pc += kA32PcDelta;
8418            Location::Offset offset =
8419                location->GetLocation() - AlignDown(pc, 4);
8420            VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
8421            uint32_t U = (offset >= 0);
8422            int32_t target = abs(offset) | (U << 12);
8423            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8424          }
8425        } immop;
8426        EmitA32(Link(0xf45ff000U, location, immop, &kA32FarDataInfo));
8427        return;
8428      }
8429    }
8430  }
8431  Delegate(kPli, &Assembler::pli, cond, location);
8432}
8433
8434bool Assembler::pli_info(Condition cond,
8435                         Location* location,
8436                         const struct ReferenceInfo** info) {
8437  VIXL_ASSERT(!location->IsBound());
8438  USE(location);
8439  USE(cond);
8440  if (IsUsingT32()) {
8441    // PLI{<c>}{<q>} <label> ; T3
8442    if (true) {
8443      *info = &kT32FarDataInfo;
8444      return true;
8445    }
8446  } else {
8447    // PLI{<c>}{<q>} <label> ; A1
8448    if (true) {
8449      *info = &kA32FarDataInfo;
8450      return true;
8451    }
8452  }
8453  return false;
8454}
8455
8456void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
8457  VIXL_ASSERT(AllowAssembler());
8458  CheckIT(cond);
8459  if (IsUsingT32()) {
8460    // POP{<c>}{<q>} <registers> ; T1
8461    if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
8462      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
8463                 GetRegisterListEncoding(registers, 0, 8));
8464      AdvanceIT();
8465      return;
8466    }
8467    // POP{<c>}{<q>} <registers> ; T2
8468    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
8469      EmitT32_32(0xe8bd0000U |
8470                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
8471                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
8472                 GetRegisterListEncoding(registers, 0, 13));
8473      AdvanceIT();
8474      return;
8475    }
8476  } else {
8477    // POP{<c>}{<q>} <registers> ; A1
8478    if (cond.IsNotNever()) {
8479      EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
8480              GetRegisterListEncoding(registers, 0, 16));
8481      return;
8482    }
8483  }
8484  Delegate(kPop, &Assembler::pop, cond, size, registers);
8485}
8486
8487void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
8488  VIXL_ASSERT(AllowAssembler());
8489  CheckIT(cond);
8490  if (IsUsingT32()) {
8491    // POP{<c>}{<q>} <single_register_list> ; T4
8492    if (!size.IsNarrow() && ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
8493                             AllowUnpredictable())) {
8494      EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
8495      AdvanceIT();
8496      return;
8497    }
8498  } else {
8499    // POP{<c>}{<q>} <single_register_list> ; A1
8500    if (cond.IsNotNever()) {
8501      EmitA32(0x049d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8502      return;
8503    }
8504  }
8505  Delegate(kPop, &Assembler::pop, cond, size, rt);
8506}
8507
8508void Assembler::push(Condition cond,
8509                     EncodingSize size,
8510                     RegisterList registers) {
8511  VIXL_ASSERT(AllowAssembler());
8512  CheckIT(cond);
8513  if (IsUsingT32()) {
8514    // PUSH{<c>}{<q>} <registers> ; T1
8515    if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
8516      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
8517                 GetRegisterListEncoding(registers, 0, 8));
8518      AdvanceIT();
8519      return;
8520    }
8521    // PUSH{<c>}{<q>} <registers> ; T1
8522    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
8523      EmitT32_32(0xe92d0000U |
8524                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
8525                 GetRegisterListEncoding(registers, 0, 13));
8526      AdvanceIT();
8527      return;
8528    }
8529  } else {
8530    // PUSH{<c>}{<q>} <registers> ; A1
8531    if (cond.IsNotNever()) {
8532      EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
8533              GetRegisterListEncoding(registers, 0, 16));
8534      return;
8535    }
8536  }
8537  Delegate(kPush, &Assembler::push, cond, size, registers);
8538}
8539
8540void Assembler::push(Condition cond, EncodingSize size, Register rt) {
8541  VIXL_ASSERT(AllowAssembler());
8542  CheckIT(cond);
8543  if (IsUsingT32()) {
8544    // PUSH{<c>}{<q>} <single_register_list> ; T4
8545    if (!size.IsNarrow() && (!rt.IsPC() || AllowUnpredictable())) {
8546      EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
8547      AdvanceIT();
8548      return;
8549    }
8550  } else {
8551    // PUSH{<c>}{<q>} <single_register_list> ; A1
8552    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
8553      EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8554      return;
8555    }
8556  }
8557  Delegate(kPush, &Assembler::push, cond, size, rt);
8558}
8559
8560void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
8561  VIXL_ASSERT(AllowAssembler());
8562  CheckIT(cond);
8563  if (IsUsingT32()) {
8564    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8565    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8566      EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
8567                 (rn.GetCode() << 16));
8568      AdvanceIT();
8569      return;
8570    }
8571  } else {
8572    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8573    if (cond.IsNotNever() &&
8574        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8575      EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8576              rm.GetCode() | (rn.GetCode() << 16));
8577      return;
8578    }
8579  }
8580  Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
8581}
8582
8583void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
8584  VIXL_ASSERT(AllowAssembler());
8585  CheckIT(cond);
8586  if (IsUsingT32()) {
8587    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8588    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8589      EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8590                 rm.GetCode());
8591      AdvanceIT();
8592      return;
8593    }
8594  } else {
8595    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8596    if (cond.IsNotNever() &&
8597        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8598      EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8599              (rn.GetCode() << 16) | rm.GetCode());
8600      return;
8601    }
8602  }
8603  Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
8604}
8605
8606void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
8607  VIXL_ASSERT(AllowAssembler());
8608  CheckIT(cond);
8609  if (IsUsingT32()) {
8610    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8611    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8612      EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8613                 rm.GetCode());
8614      AdvanceIT();
8615      return;
8616    }
8617  } else {
8618    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8619    if (cond.IsNotNever() &&
8620        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8621      EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8622              (rn.GetCode() << 16) | rm.GetCode());
8623      return;
8624    }
8625  }
8626  Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
8627}
8628
8629void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
8630  VIXL_ASSERT(AllowAssembler());
8631  CheckIT(cond);
8632  if (IsUsingT32()) {
8633    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8634    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8635      EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8636                 rm.GetCode());
8637      AdvanceIT();
8638      return;
8639    }
8640  } else {
8641    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8642    if (cond.IsNotNever() &&
8643        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8644      EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8645              (rn.GetCode() << 16) | rm.GetCode());
8646      return;
8647    }
8648  }
8649  Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
8650}
8651
8652void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
8653  VIXL_ASSERT(AllowAssembler());
8654  CheckIT(cond);
8655  if (IsUsingT32()) {
8656    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8657    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8658      EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
8659                 (rn.GetCode() << 16));
8660      AdvanceIT();
8661      return;
8662    }
8663  } else {
8664    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8665    if (cond.IsNotNever() &&
8666        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8667      EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8668              rm.GetCode() | (rn.GetCode() << 16));
8669      return;
8670    }
8671  }
8672  Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
8673}
8674
8675void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
8676  VIXL_ASSERT(AllowAssembler());
8677  CheckIT(cond);
8678  if (IsUsingT32()) {
8679    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8680    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8681      EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8682                 (rn.GetCode() << 16));
8683      AdvanceIT();
8684      return;
8685    }
8686  } else {
8687    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8688    if (cond.IsNotNever() &&
8689        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8690      EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8691              rm.GetCode() | (rn.GetCode() << 16));
8692      return;
8693    }
8694  }
8695  Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
8696}
8697
8698void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
8699  VIXL_ASSERT(AllowAssembler());
8700  CheckIT(cond);
8701  if (IsUsingT32()) {
8702    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8703    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8704      EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8705                 rm.GetCode());
8706      AdvanceIT();
8707      return;
8708    }
8709  } else {
8710    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8711    if (cond.IsNotNever() &&
8712        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8713      EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8714              (rn.GetCode() << 16) | rm.GetCode());
8715      return;
8716    }
8717  }
8718  Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
8719}
8720
8721void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
8722  VIXL_ASSERT(AllowAssembler());
8723  CheckIT(cond);
8724  if (IsUsingT32()) {
8725    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
8726    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8727      EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8728                 (rn.GetCode() << 16));
8729      AdvanceIT();
8730      return;
8731    }
8732  } else {
8733    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
8734    if (cond.IsNotNever() &&
8735        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8736      EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8737              rm.GetCode() | (rn.GetCode() << 16));
8738      return;
8739    }
8740  }
8741  Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8742}
8743
8744void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
8745  VIXL_ASSERT(AllowAssembler());
8746  CheckIT(cond);
8747  if (IsUsingT32()) {
8748    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8749    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8750      EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8751                 rm.GetCode());
8752      AdvanceIT();
8753      return;
8754    }
8755  } else {
8756    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8757    if (cond.IsNotNever() &&
8758        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8759      EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8760              (rn.GetCode() << 16) | rm.GetCode());
8761      return;
8762    }
8763  }
8764  Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8765}
8766
8767void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
8768  VIXL_ASSERT(AllowAssembler());
8769  CheckIT(cond);
8770  if (IsUsingT32()) {
8771    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8772    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8773      EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8774                 rm.GetCode());
8775      AdvanceIT();
8776      return;
8777    }
8778  } else {
8779    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8780    if (cond.IsNotNever() &&
8781        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8782      EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8783              (rn.GetCode() << 16) | rm.GetCode());
8784      return;
8785    }
8786  }
8787  Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8788}
8789
8790void Assembler::rbit(Condition cond, Register rd, Register rm) {
8791  VIXL_ASSERT(AllowAssembler());
8792  CheckIT(cond);
8793  if (IsUsingT32()) {
8794    // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
8795    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8796      EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8797                 (rm.GetCode() << 16));
8798      AdvanceIT();
8799      return;
8800    }
8801  } else {
8802    // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
8803    if (cond.IsNotNever() &&
8804        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8805      EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8806              rm.GetCode());
8807      return;
8808    }
8809  }
8810  Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8811}
8812
8813void Assembler::rev(Condition cond,
8814                    EncodingSize size,
8815                    Register rd,
8816                    Register rm) {
8817  VIXL_ASSERT(AllowAssembler());
8818  CheckIT(cond);
8819  if (IsUsingT32()) {
8820    // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8821    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8822      EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8823      AdvanceIT();
8824      return;
8825    }
8826    // REV{<c>}{<q>} <Rd>, <Rm> ; T2
8827    if (!size.IsNarrow() &&
8828        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8829      EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8830                 (rm.GetCode() << 16));
8831      AdvanceIT();
8832      return;
8833    }
8834  } else {
8835    // REV{<c>}{<q>} <Rd>, <Rm> ; A1
8836    if (cond.IsNotNever() &&
8837        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8838      EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8839              rm.GetCode());
8840      return;
8841    }
8842  }
8843  Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8844}
8845
8846void Assembler::rev16(Condition cond,
8847                      EncodingSize size,
8848                      Register rd,
8849                      Register rm) {
8850  VIXL_ASSERT(AllowAssembler());
8851  CheckIT(cond);
8852  if (IsUsingT32()) {
8853    // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8854    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8855      EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8856      AdvanceIT();
8857      return;
8858    }
8859    // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
8860    if (!size.IsNarrow() &&
8861        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8862      EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8863                 (rm.GetCode() << 16));
8864      AdvanceIT();
8865      return;
8866    }
8867  } else {
8868    // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
8869    if (cond.IsNotNever() &&
8870        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8871      EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8872              rm.GetCode());
8873      return;
8874    }
8875  }
8876  Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8877}
8878
8879void Assembler::revsh(Condition cond,
8880                      EncodingSize size,
8881                      Register rd,
8882                      Register rm) {
8883  VIXL_ASSERT(AllowAssembler());
8884  CheckIT(cond);
8885  if (IsUsingT32()) {
8886    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8887    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8888      EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8889      AdvanceIT();
8890      return;
8891    }
8892    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
8893    if (!size.IsNarrow() &&
8894        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8895      EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8896                 (rm.GetCode() << 16));
8897      AdvanceIT();
8898      return;
8899    }
8900  } else {
8901    // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
8902    if (cond.IsNotNever() &&
8903        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8904      EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8905              rm.GetCode());
8906      return;
8907    }
8908  }
8909  Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8910}
8911
8912void Assembler::ror(Condition cond,
8913                    EncodingSize size,
8914                    Register rd,
8915                    Register rm,
8916                    const Operand& operand) {
8917  VIXL_ASSERT(AllowAssembler());
8918  CheckIT(cond);
8919  if (operand.IsImmediate()) {
8920    uint32_t imm = operand.GetImmediate();
8921    if (IsUsingT32()) {
8922      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8923      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8924          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8925        EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8926                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8927        AdvanceIT();
8928        return;
8929      }
8930    } else {
8931      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8932      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8933        EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8934                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8935        return;
8936      }
8937    }
8938  }
8939  if (operand.IsPlainRegister()) {
8940    Register rs = operand.GetBaseRegister();
8941    if (IsUsingT32()) {
8942      // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8943      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8944          rs.IsLow()) {
8945        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8946        AdvanceIT();
8947        return;
8948      }
8949      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8950      if (!size.IsNarrow() &&
8951          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
8952        EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8953                   rs.GetCode());
8954        AdvanceIT();
8955        return;
8956      }
8957    } else {
8958      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8959      if (cond.IsNotNever() &&
8960          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
8961        EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
8962                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8963        return;
8964      }
8965    }
8966  }
8967  Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
8968}
8969
8970void Assembler::rors(Condition cond,
8971                     EncodingSize size,
8972                     Register rd,
8973                     Register rm,
8974                     const Operand& operand) {
8975  VIXL_ASSERT(AllowAssembler());
8976  CheckIT(cond);
8977  if (operand.IsImmediate()) {
8978    uint32_t imm = operand.GetImmediate();
8979    if (IsUsingT32()) {
8980      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8981      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8982          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8983        EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8984                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8985        AdvanceIT();
8986        return;
8987      }
8988    } else {
8989      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8990      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8991        EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
8992                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8993        return;
8994      }
8995    }
8996  }
8997  if (operand.IsPlainRegister()) {
8998    Register rs = operand.GetBaseRegister();
8999    if (IsUsingT32()) {
9000      // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
9001      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
9002          rs.IsLow()) {
9003        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
9004        AdvanceIT();
9005        return;
9006      }
9007      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
9008      if (!size.IsNarrow() &&
9009          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
9010        EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
9011                   rs.GetCode());
9012        AdvanceIT();
9013        return;
9014      }
9015    } else {
9016      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
9017      if (cond.IsNotNever() &&
9018          ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
9019        EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
9020                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9021        return;
9022      }
9023    }
9024  }
9025  Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
9026}
9027
9028void Assembler::rrx(Condition cond, Register rd, Register rm) {
9029  VIXL_ASSERT(AllowAssembler());
9030  CheckIT(cond);
9031  if (IsUsingT32()) {
9032    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
9033    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9034      EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
9035      AdvanceIT();
9036      return;
9037    }
9038  } else {
9039    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
9040    if (cond.IsNotNever()) {
9041      EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9042              rm.GetCode());
9043      return;
9044    }
9045  }
9046  Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
9047}
9048
9049void Assembler::rrxs(Condition cond, Register rd, Register rm) {
9050  VIXL_ASSERT(AllowAssembler());
9051  CheckIT(cond);
9052  if (IsUsingT32()) {
9053    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
9054    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9055      EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
9056      AdvanceIT();
9057      return;
9058    }
9059  } else {
9060    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
9061    if (cond.IsNotNever()) {
9062      EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9063              rm.GetCode());
9064      return;
9065    }
9066  }
9067  Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
9068}
9069
9070void Assembler::rsb(Condition cond,
9071                    EncodingSize size,
9072                    Register rd,
9073                    Register rn,
9074                    const Operand& operand) {
9075  VIXL_ASSERT(AllowAssembler());
9076  CheckIT(cond);
9077  if (operand.IsImmediate()) {
9078    uint32_t imm = operand.GetImmediate();
9079    if (IsUsingT32()) {
9080      ImmediateT32 immediate_t32(imm);
9081      // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
9082      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9083          (imm == 0)) {
9084        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9085        AdvanceIT();
9086        return;
9087      }
9088      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
9089      if (!size.IsNarrow() && immediate_t32.IsValid() &&
9090          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9091        EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9092                   (immediate_t32.GetEncodingValue() & 0xff) |
9093                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9094                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9095        AdvanceIT();
9096        return;
9097      }
9098    } else {
9099      ImmediateA32 immediate_a32(imm);
9100      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9101      if (immediate_a32.IsValid() && cond.IsNotNever()) {
9102        EmitA32(0x02600000U | (cond.GetCondition() << 28) |
9103                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9104                immediate_a32.GetEncodingValue());
9105        return;
9106      }
9107    }
9108  }
9109  if (operand.IsImmediateShiftedRegister()) {
9110    Register rm = operand.GetBaseRegister();
9111    Shift shift = operand.GetShift();
9112    uint32_t amount = operand.GetShiftAmount();
9113    if (IsUsingT32()) {
9114      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
9115      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9116          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9117        uint32_t amount_ = amount % 32;
9118        EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9119                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9120                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9121        AdvanceIT();
9122        return;
9123      }
9124    } else {
9125      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9126      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9127        uint32_t amount_ = amount % 32;
9128        EmitA32(0x00600000U | (cond.GetCondition() << 28) |
9129                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9130                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9131        return;
9132      }
9133    }
9134  }
9135  if (operand.IsRegisterShiftedRegister()) {
9136    Register rm = operand.GetBaseRegister();
9137    Shift shift = operand.GetShift();
9138    Register rs = operand.GetShiftRegister();
9139    if (IsUsingA32()) {
9140      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9141      if (cond.IsNotNever() &&
9142          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9143           AllowUnpredictable())) {
9144        EmitA32(0x00600010U | (cond.GetCondition() << 28) |
9145                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9146                (shift.GetType() << 5) | (rs.GetCode() << 8));
9147        return;
9148      }
9149    }
9150  }
9151  Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
9152}
9153
9154void Assembler::rsbs(Condition cond,
9155                     EncodingSize size,
9156                     Register rd,
9157                     Register rn,
9158                     const Operand& operand) {
9159  VIXL_ASSERT(AllowAssembler());
9160  CheckIT(cond);
9161  if (operand.IsImmediate()) {
9162    uint32_t imm = operand.GetImmediate();
9163    if (IsUsingT32()) {
9164      ImmediateT32 immediate_t32(imm);
9165      // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
9166      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9167          (imm == 0)) {
9168        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9169        AdvanceIT();
9170        return;
9171      }
9172      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
9173      if (!size.IsNarrow() && immediate_t32.IsValid() &&
9174          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9175        EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9176                   (immediate_t32.GetEncodingValue() & 0xff) |
9177                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9178                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9179        AdvanceIT();
9180        return;
9181      }
9182    } else {
9183      ImmediateA32 immediate_a32(imm);
9184      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9185      if (immediate_a32.IsValid() && cond.IsNotNever()) {
9186        EmitA32(0x02700000U | (cond.GetCondition() << 28) |
9187                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9188                immediate_a32.GetEncodingValue());
9189        return;
9190      }
9191    }
9192  }
9193  if (operand.IsImmediateShiftedRegister()) {
9194    Register rm = operand.GetBaseRegister();
9195    Shift shift = operand.GetShift();
9196    uint32_t amount = operand.GetShiftAmount();
9197    if (IsUsingT32()) {
9198      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
9199      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9200          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9201        uint32_t amount_ = amount % 32;
9202        EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9203                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9204                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9205        AdvanceIT();
9206        return;
9207      }
9208    } else {
9209      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9210      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9211        uint32_t amount_ = amount % 32;
9212        EmitA32(0x00700000U | (cond.GetCondition() << 28) |
9213                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9214                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9215        return;
9216      }
9217    }
9218  }
9219  if (operand.IsRegisterShiftedRegister()) {
9220    Register rm = operand.GetBaseRegister();
9221    Shift shift = operand.GetShift();
9222    Register rs = operand.GetShiftRegister();
9223    if (IsUsingA32()) {
9224      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9225      if (cond.IsNotNever() &&
9226          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9227           AllowUnpredictable())) {
9228        EmitA32(0x00700010U | (cond.GetCondition() << 28) |
9229                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9230                (shift.GetType() << 5) | (rs.GetCode() << 8));
9231        return;
9232      }
9233    }
9234  }
9235  Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
9236}
9237
9238void Assembler::rsc(Condition cond,
9239                    Register rd,
9240                    Register rn,
9241                    const Operand& operand) {
9242  VIXL_ASSERT(AllowAssembler());
9243  CheckIT(cond);
9244  if (operand.IsImmediate()) {
9245    uint32_t imm = operand.GetImmediate();
9246    if (IsUsingA32()) {
9247      ImmediateA32 immediate_a32(imm);
9248      // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9249      if (immediate_a32.IsValid() && cond.IsNotNever()) {
9250        EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
9251                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9252                immediate_a32.GetEncodingValue());
9253        return;
9254      }
9255    }
9256  }
9257  if (operand.IsImmediateShiftedRegister()) {
9258    Register rm = operand.GetBaseRegister();
9259    Shift shift = operand.GetShift();
9260    uint32_t amount = operand.GetShiftAmount();
9261    if (IsUsingA32()) {
9262      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9263      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9264        uint32_t amount_ = amount % 32;
9265        EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
9266                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9267                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9268        return;
9269      }
9270    }
9271  }
9272  if (operand.IsRegisterShiftedRegister()) {
9273    Register rm = operand.GetBaseRegister();
9274    Shift shift = operand.GetShift();
9275    Register rs = operand.GetShiftRegister();
9276    if (IsUsingA32()) {
9277      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9278      if (cond.IsNotNever() &&
9279          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9280           AllowUnpredictable())) {
9281        EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
9282                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9283                (shift.GetType() << 5) | (rs.GetCode() << 8));
9284        return;
9285      }
9286    }
9287  }
9288  Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
9289}
9290
9291void Assembler::rscs(Condition cond,
9292                     Register rd,
9293                     Register rn,
9294                     const Operand& operand) {
9295  VIXL_ASSERT(AllowAssembler());
9296  CheckIT(cond);
9297  if (operand.IsImmediate()) {
9298    uint32_t imm = operand.GetImmediate();
9299    if (IsUsingA32()) {
9300      ImmediateA32 immediate_a32(imm);
9301      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9302      if (immediate_a32.IsValid() && cond.IsNotNever()) {
9303        EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
9304                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9305                immediate_a32.GetEncodingValue());
9306        return;
9307      }
9308    }
9309  }
9310  if (operand.IsImmediateShiftedRegister()) {
9311    Register rm = operand.GetBaseRegister();
9312    Shift shift = operand.GetShift();
9313    uint32_t amount = operand.GetShiftAmount();
9314    if (IsUsingA32()) {
9315      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9316      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9317        uint32_t amount_ = amount % 32;
9318        EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
9319                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9320                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9321        return;
9322      }
9323    }
9324  }
9325  if (operand.IsRegisterShiftedRegister()) {
9326    Register rm = operand.GetBaseRegister();
9327    Shift shift = operand.GetShift();
9328    Register rs = operand.GetShiftRegister();
9329    if (IsUsingA32()) {
9330      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9331      if (cond.IsNotNever() &&
9332          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9333           AllowUnpredictable())) {
9334        EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
9335                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9336                (shift.GetType() << 5) | (rs.GetCode() << 8));
9337        return;
9338      }
9339    }
9340  }
9341  Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
9342}
9343
9344void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
9345  VIXL_ASSERT(AllowAssembler());
9346  CheckIT(cond);
9347  if (IsUsingT32()) {
9348    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9349    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9350      EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9351                 rm.GetCode());
9352      AdvanceIT();
9353      return;
9354    }
9355  } else {
9356    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9357    if (cond.IsNotNever() &&
9358        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9359      EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9360              (rn.GetCode() << 16) | rm.GetCode());
9361      return;
9362    }
9363  }
9364  Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
9365}
9366
9367void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
9368  VIXL_ASSERT(AllowAssembler());
9369  CheckIT(cond);
9370  if (IsUsingT32()) {
9371    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9372    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9373      EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9374                 rm.GetCode());
9375      AdvanceIT();
9376      return;
9377    }
9378  } else {
9379    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9380    if (cond.IsNotNever() &&
9381        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9382      EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9383              (rn.GetCode() << 16) | rm.GetCode());
9384      return;
9385    }
9386  }
9387  Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
9388}
9389
9390void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
9391  VIXL_ASSERT(AllowAssembler());
9392  CheckIT(cond);
9393  if (IsUsingT32()) {
9394    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9395    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9396      EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9397                 rm.GetCode());
9398      AdvanceIT();
9399      return;
9400    }
9401  } else {
9402    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9403    if (cond.IsNotNever() &&
9404        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9405      EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9406              (rn.GetCode() << 16) | rm.GetCode());
9407      return;
9408    }
9409  }
9410  Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
9411}
9412
9413void Assembler::sbc(Condition cond,
9414                    EncodingSize size,
9415                    Register rd,
9416                    Register rn,
9417                    const Operand& operand) {
9418  VIXL_ASSERT(AllowAssembler());
9419  CheckIT(cond);
9420  if (operand.IsImmediate()) {
9421    uint32_t imm = operand.GetImmediate();
9422    if (IsUsingT32()) {
9423      ImmediateT32 immediate_t32(imm);
9424      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
9425      if (!size.IsNarrow() && immediate_t32.IsValid() &&
9426          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9427        EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9428                   (immediate_t32.GetEncodingValue() & 0xff) |
9429                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9430                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9431        AdvanceIT();
9432        return;
9433      }
9434    } else {
9435      ImmediateA32 immediate_a32(imm);
9436      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9437      if (immediate_a32.IsValid() && cond.IsNotNever()) {
9438        EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
9439                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9440                immediate_a32.GetEncodingValue());
9441        return;
9442      }
9443    }
9444  }
9445  if (operand.IsImmediateShiftedRegister()) {
9446    Register rm = operand.GetBaseRegister();
9447    if (operand.IsPlainRegister()) {
9448      if (IsUsingT32()) {
9449        // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9450        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9451            rm.IsLow()) {
9452          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9453          AdvanceIT();
9454          return;
9455        }
9456      }
9457    }
9458    Shift shift = operand.GetShift();
9459    uint32_t amount = operand.GetShiftAmount();
9460    if (IsUsingT32()) {
9461      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
9462      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9463          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9464        uint32_t amount_ = amount % 32;
9465        EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9466                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9467                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9468        AdvanceIT();
9469        return;
9470      }
9471    } else {
9472      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9473      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9474        uint32_t amount_ = amount % 32;
9475        EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
9476                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9477                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9478        return;
9479      }
9480    }
9481  }
9482  if (operand.IsRegisterShiftedRegister()) {
9483    Register rm = operand.GetBaseRegister();
9484    Shift shift = operand.GetShift();
9485    Register rs = operand.GetShiftRegister();
9486    if (IsUsingA32()) {
9487      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9488      if (cond.IsNotNever() &&
9489          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9490           AllowUnpredictable())) {
9491        EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
9492                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9493                (shift.GetType() << 5) | (rs.GetCode() << 8));
9494        return;
9495      }
9496    }
9497  }
9498  Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
9499}
9500
9501void Assembler::sbcs(Condition cond,
9502                     EncodingSize size,
9503                     Register rd,
9504                     Register rn,
9505                     const Operand& operand) {
9506  VIXL_ASSERT(AllowAssembler());
9507  CheckIT(cond);
9508  if (operand.IsImmediate()) {
9509    uint32_t imm = operand.GetImmediate();
9510    if (IsUsingT32()) {
9511      ImmediateT32 immediate_t32(imm);
9512      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
9513      if (!size.IsNarrow() && immediate_t32.IsValid() &&
9514          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
9515        EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9516                   (immediate_t32.GetEncodingValue() & 0xff) |
9517                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9518                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9519        AdvanceIT();
9520        return;
9521      }
9522    } else {
9523      ImmediateA32 immediate_a32(imm);
9524      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9525      if (immediate_a32.IsValid() && cond.IsNotNever()) {
9526        EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
9527                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9528                immediate_a32.GetEncodingValue());
9529        return;
9530      }
9531    }
9532  }
9533  if (operand.IsImmediateShiftedRegister()) {
9534    Register rm = operand.GetBaseRegister();
9535    if (operand.IsPlainRegister()) {
9536      if (IsUsingT32()) {
9537        // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9538        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9539            rm.IsLow()) {
9540          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9541          AdvanceIT();
9542          return;
9543        }
9544      }
9545    }
9546    Shift shift = operand.GetShift();
9547    uint32_t amount = operand.GetShiftAmount();
9548    if (IsUsingT32()) {
9549      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
9550      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9551          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9552        uint32_t amount_ = amount % 32;
9553        EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9554                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9555                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9556        AdvanceIT();
9557        return;
9558      }
9559    } else {
9560      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9561      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9562        uint32_t amount_ = amount % 32;
9563        EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
9564                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9565                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9566        return;
9567      }
9568    }
9569  }
9570  if (operand.IsRegisterShiftedRegister()) {
9571    Register rm = operand.GetBaseRegister();
9572    Shift shift = operand.GetShift();
9573    Register rs = operand.GetShiftRegister();
9574    if (IsUsingA32()) {
9575      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
9576      if (cond.IsNotNever() &&
9577          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9578           AllowUnpredictable())) {
9579        EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
9580                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9581                (shift.GetType() << 5) | (rs.GetCode() << 8));
9582        return;
9583      }
9584    }
9585  }
9586  Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
9587}
9588
9589void Assembler::sbfx(
9590    Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
9591  VIXL_ASSERT(AllowAssembler());
9592  CheckIT(cond);
9593  if (IsUsingT32()) {
9594    // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
9595    if ((lsb <= 31) &&
9596        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9597         AllowUnpredictable())) {
9598      uint32_t widthm1 = width - 1;
9599      EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9600                 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
9601      AdvanceIT();
9602      return;
9603    }
9604  } else {
9605    // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
9606    if ((lsb <= 31) && cond.IsNotNever() &&
9607        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9608         AllowUnpredictable())) {
9609      uint32_t widthm1 = width - 1;
9610      EmitA32(0x07a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9611              rn.GetCode() | (lsb << 7) | (widthm1 << 16));
9612      return;
9613    }
9614  }
9615  Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, width);
9616}
9617
9618void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
9619  VIXL_ASSERT(AllowAssembler());
9620  CheckIT(cond);
9621  if (IsUsingT32()) {
9622    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9623    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9624      EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9625                 rm.GetCode());
9626      AdvanceIT();
9627      return;
9628    }
9629  } else {
9630    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9631    if (cond.IsNotNever() &&
9632        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9633      EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9634              rn.GetCode() | (rm.GetCode() << 8));
9635      return;
9636    }
9637  }
9638  Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
9639}
9640
9641void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
9642  VIXL_ASSERT(AllowAssembler());
9643  CheckIT(cond);
9644  if (IsUsingT32()) {
9645    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9646    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9647      EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9648                 rm.GetCode());
9649      AdvanceIT();
9650      return;
9651    }
9652  } else {
9653    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9654    if (cond.IsNotNever() &&
9655        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9656      EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9657              (rn.GetCode() << 16) | rm.GetCode());
9658      return;
9659    }
9660  }
9661  Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
9662}
9663
9664void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
9665  VIXL_ASSERT(AllowAssembler());
9666  CheckIT(cond);
9667  if (IsUsingT32()) {
9668    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9669    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9670      EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9671                 rm.GetCode());
9672      AdvanceIT();
9673      return;
9674    }
9675  } else {
9676    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9677    if (cond.IsNotNever() &&
9678        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9679      EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9680              (rn.GetCode() << 16) | rm.GetCode());
9681      return;
9682    }
9683  }
9684  Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
9685}
9686
9687void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
9688  VIXL_ASSERT(AllowAssembler());
9689  CheckIT(cond);
9690  if (IsUsingT32()) {
9691    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9692    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9693      EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9694                 rm.GetCode());
9695      AdvanceIT();
9696      return;
9697    }
9698  } else {
9699    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9700    if (cond.IsNotNever() &&
9701        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9702      EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9703              (rn.GetCode() << 16) | rm.GetCode());
9704      return;
9705    }
9706  }
9707  Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
9708}
9709
9710void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
9711  VIXL_ASSERT(AllowAssembler());
9712  CheckIT(cond);
9713  if (IsUsingT32()) {
9714    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9715    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9716      EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9717                 rm.GetCode());
9718      AdvanceIT();
9719      return;
9720    }
9721  } else {
9722    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9723    if (cond.IsNotNever() &&
9724        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9725      EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9726              (rn.GetCode() << 16) | rm.GetCode());
9727      return;
9728    }
9729  }
9730  Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
9731}
9732
9733void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
9734  VIXL_ASSERT(AllowAssembler());
9735  CheckIT(cond);
9736  if (IsUsingT32()) {
9737    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9738    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9739      EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9740                 rm.GetCode());
9741      AdvanceIT();
9742      return;
9743    }
9744  } else {
9745    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9746    if (cond.IsNotNever() &&
9747        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9748      EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9749              (rn.GetCode() << 16) | rm.GetCode());
9750      return;
9751    }
9752  }
9753  Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
9754}
9755
9756void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
9757  VIXL_ASSERT(AllowAssembler());
9758  CheckIT(cond);
9759  if (IsUsingT32()) {
9760    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9761    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9762      EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9763                 rm.GetCode());
9764      AdvanceIT();
9765      return;
9766    }
9767  } else {
9768    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9769    if (cond.IsNotNever() &&
9770        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9771      EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9772              (rn.GetCode() << 16) | rm.GetCode());
9773      return;
9774    }
9775  }
9776  Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
9777}
9778
9779void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
9780  VIXL_ASSERT(AllowAssembler());
9781  CheckIT(cond);
9782  if (IsUsingT32()) {
9783    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9784    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9785      EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9786                 rm.GetCode());
9787      AdvanceIT();
9788      return;
9789    }
9790  } else {
9791    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9792    if (cond.IsNotNever() &&
9793        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9794      EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9795              (rn.GetCode() << 16) | rm.GetCode());
9796      return;
9797    }
9798  }
9799  Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
9800}
9801
9802void Assembler::smlabb(
9803    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9804  VIXL_ASSERT(AllowAssembler());
9805  CheckIT(cond);
9806  if (IsUsingT32()) {
9807    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9808    if (!ra.Is(pc) &&
9809        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9810      EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9811                 rm.GetCode() | (ra.GetCode() << 12));
9812      AdvanceIT();
9813      return;
9814    }
9815  } else {
9816    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9817    if (cond.IsNotNever() &&
9818        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9819         AllowUnpredictable())) {
9820      EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9821              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9822      return;
9823    }
9824  }
9825  Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9826}
9827
9828void Assembler::smlabt(
9829    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9830  VIXL_ASSERT(AllowAssembler());
9831  CheckIT(cond);
9832  if (IsUsingT32()) {
9833    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9834    if (!ra.Is(pc) &&
9835        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9836      EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9837                 rm.GetCode() | (ra.GetCode() << 12));
9838      AdvanceIT();
9839      return;
9840    }
9841  } else {
9842    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9843    if (cond.IsNotNever() &&
9844        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9845         AllowUnpredictable())) {
9846      EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9847              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9848      return;
9849    }
9850  }
9851  Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9852}
9853
9854void Assembler::smlad(
9855    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9856  VIXL_ASSERT(AllowAssembler());
9857  CheckIT(cond);
9858  if (IsUsingT32()) {
9859    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9860    if (!ra.Is(pc) &&
9861        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9862      EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9863                 rm.GetCode() | (ra.GetCode() << 12));
9864      AdvanceIT();
9865      return;
9866    }
9867  } else {
9868    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9869    if (cond.IsNotNever() && !ra.Is(pc) &&
9870        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9871      EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9872              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9873      return;
9874    }
9875  }
9876  Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9877}
9878
9879void Assembler::smladx(
9880    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9881  VIXL_ASSERT(AllowAssembler());
9882  CheckIT(cond);
9883  if (IsUsingT32()) {
9884    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9885    if (!ra.Is(pc) &&
9886        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9887      EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9888                 rm.GetCode() | (ra.GetCode() << 12));
9889      AdvanceIT();
9890      return;
9891    }
9892  } else {
9893    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9894    if (cond.IsNotNever() && !ra.Is(pc) &&
9895        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9896      EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9897              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9898      return;
9899    }
9900  }
9901  Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9902}
9903
9904void Assembler::smlal(
9905    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9906  VIXL_ASSERT(AllowAssembler());
9907  CheckIT(cond);
9908  if (IsUsingT32()) {
9909    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9910    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9911         AllowUnpredictable())) {
9912      EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9913                 (rn.GetCode() << 16) | rm.GetCode());
9914      AdvanceIT();
9915      return;
9916    }
9917  } else {
9918    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9919    if (cond.IsNotNever() &&
9920        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9921         AllowUnpredictable())) {
9922      EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9923              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9924              (rm.GetCode() << 8));
9925      return;
9926    }
9927  }
9928  Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9929}
9930
9931void Assembler::smlalbb(
9932    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9933  VIXL_ASSERT(AllowAssembler());
9934  CheckIT(cond);
9935  if (IsUsingT32()) {
9936    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9937    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9938         AllowUnpredictable())) {
9939      EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9940                 (rn.GetCode() << 16) | rm.GetCode());
9941      AdvanceIT();
9942      return;
9943    }
9944  } else {
9945    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9946    if (cond.IsNotNever() &&
9947        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9948         AllowUnpredictable())) {
9949      EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9950              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9951              (rm.GetCode() << 8));
9952      return;
9953    }
9954  }
9955  Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9956}
9957
9958void Assembler::smlalbt(
9959    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9960  VIXL_ASSERT(AllowAssembler());
9961  CheckIT(cond);
9962  if (IsUsingT32()) {
9963    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9964    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9965         AllowUnpredictable())) {
9966      EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9967                 (rn.GetCode() << 16) | rm.GetCode());
9968      AdvanceIT();
9969      return;
9970    }
9971  } else {
9972    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9973    if (cond.IsNotNever() &&
9974        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9975         AllowUnpredictable())) {
9976      EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
9977              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9978              (rm.GetCode() << 8));
9979      return;
9980    }
9981  }
9982  Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
9983}
9984
9985void Assembler::smlald(
9986    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9987  VIXL_ASSERT(AllowAssembler());
9988  CheckIT(cond);
9989  if (IsUsingT32()) {
9990    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9991    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9992         AllowUnpredictable())) {
9993      EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9994                 (rn.GetCode() << 16) | rm.GetCode());
9995      AdvanceIT();
9996      return;
9997    }
9998  } else {
9999    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10000    if (cond.IsNotNever() &&
10001        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10002         AllowUnpredictable())) {
10003      EmitA32(0x07400010U | (cond.GetCondition() << 28) |
10004              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10005              (rm.GetCode() << 8));
10006      return;
10007    }
10008  }
10009  Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
10010}
10011
10012void Assembler::smlaldx(
10013    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10014  VIXL_ASSERT(AllowAssembler());
10015  CheckIT(cond);
10016  if (IsUsingT32()) {
10017    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10018    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10019         AllowUnpredictable())) {
10020      EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10021                 (rn.GetCode() << 16) | rm.GetCode());
10022      AdvanceIT();
10023      return;
10024    }
10025  } else {
10026    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10027    if (cond.IsNotNever() &&
10028        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10029         AllowUnpredictable())) {
10030      EmitA32(0x07400030U | (cond.GetCondition() << 28) |
10031              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10032              (rm.GetCode() << 8));
10033      return;
10034    }
10035  }
10036  Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
10037}
10038
10039void Assembler::smlals(
10040    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10041  VIXL_ASSERT(AllowAssembler());
10042  CheckIT(cond);
10043  if (IsUsingA32()) {
10044    // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10045    if (cond.IsNotNever() &&
10046        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10047         AllowUnpredictable())) {
10048      EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
10049              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10050              (rm.GetCode() << 8));
10051      return;
10052    }
10053  }
10054  Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
10055}
10056
10057void Assembler::smlaltb(
10058    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10059  VIXL_ASSERT(AllowAssembler());
10060  CheckIT(cond);
10061  if (IsUsingT32()) {
10062    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10063    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10064         AllowUnpredictable())) {
10065      EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10066                 (rn.GetCode() << 16) | rm.GetCode());
10067      AdvanceIT();
10068      return;
10069    }
10070  } else {
10071    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10072    if (cond.IsNotNever() &&
10073        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10074         AllowUnpredictable())) {
10075      EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
10076              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10077              (rm.GetCode() << 8));
10078      return;
10079    }
10080  }
10081  Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
10082}
10083
10084void Assembler::smlaltt(
10085    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10086  VIXL_ASSERT(AllowAssembler());
10087  CheckIT(cond);
10088  if (IsUsingT32()) {
10089    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10090    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10091         AllowUnpredictable())) {
10092      EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10093                 (rn.GetCode() << 16) | rm.GetCode());
10094      AdvanceIT();
10095      return;
10096    }
10097  } else {
10098    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10099    if (cond.IsNotNever() &&
10100        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10101         AllowUnpredictable())) {
10102      EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
10103              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10104              (rm.GetCode() << 8));
10105      return;
10106    }
10107  }
10108  Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
10109}
10110
10111void Assembler::smlatb(
10112    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10113  VIXL_ASSERT(AllowAssembler());
10114  CheckIT(cond);
10115  if (IsUsingT32()) {
10116    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10117    if (!ra.Is(pc) &&
10118        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10119      EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10120                 rm.GetCode() | (ra.GetCode() << 12));
10121      AdvanceIT();
10122      return;
10123    }
10124  } else {
10125    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10126    if (cond.IsNotNever() &&
10127        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10128         AllowUnpredictable())) {
10129      EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10130              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10131      return;
10132    }
10133  }
10134  Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
10135}
10136
10137void Assembler::smlatt(
10138    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10139  VIXL_ASSERT(AllowAssembler());
10140  CheckIT(cond);
10141  if (IsUsingT32()) {
10142    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10143    if (!ra.Is(pc) &&
10144        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10145      EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10146                 rm.GetCode() | (ra.GetCode() << 12));
10147      AdvanceIT();
10148      return;
10149    }
10150  } else {
10151    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10152    if (cond.IsNotNever() &&
10153        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10154         AllowUnpredictable())) {
10155      EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10156              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10157      return;
10158    }
10159  }
10160  Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
10161}
10162
10163void Assembler::smlawb(
10164    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10165  VIXL_ASSERT(AllowAssembler());
10166  CheckIT(cond);
10167  if (IsUsingT32()) {
10168    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10169    if (!ra.Is(pc) &&
10170        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10171      EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10172                 rm.GetCode() | (ra.GetCode() << 12));
10173      AdvanceIT();
10174      return;
10175    }
10176  } else {
10177    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10178    if (cond.IsNotNever() &&
10179        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10180         AllowUnpredictable())) {
10181      EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10182              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10183      return;
10184    }
10185  }
10186  Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
10187}
10188
10189void Assembler::smlawt(
10190    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10191  VIXL_ASSERT(AllowAssembler());
10192  CheckIT(cond);
10193  if (IsUsingT32()) {
10194    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10195    if (!ra.Is(pc) &&
10196        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10197      EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10198                 rm.GetCode() | (ra.GetCode() << 12));
10199      AdvanceIT();
10200      return;
10201    }
10202  } else {
10203    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10204    if (cond.IsNotNever() &&
10205        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10206         AllowUnpredictable())) {
10207      EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10208              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10209      return;
10210    }
10211  }
10212  Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
10213}
10214
10215void Assembler::smlsd(
10216    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10217  VIXL_ASSERT(AllowAssembler());
10218  CheckIT(cond);
10219  if (IsUsingT32()) {
10220    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10221    if (!ra.Is(pc) &&
10222        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10223      EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10224                 rm.GetCode() | (ra.GetCode() << 12));
10225      AdvanceIT();
10226      return;
10227    }
10228  } else {
10229    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10230    if (cond.IsNotNever() && !ra.Is(pc) &&
10231        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10232      EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10233              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10234      return;
10235    }
10236  }
10237  Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
10238}
10239
10240void Assembler::smlsdx(
10241    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10242  VIXL_ASSERT(AllowAssembler());
10243  CheckIT(cond);
10244  if (IsUsingT32()) {
10245    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10246    if (!ra.Is(pc) &&
10247        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10248      EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10249                 rm.GetCode() | (ra.GetCode() << 12));
10250      AdvanceIT();
10251      return;
10252    }
10253  } else {
10254    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10255    if (cond.IsNotNever() && !ra.Is(pc) &&
10256        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10257      EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10258              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10259      return;
10260    }
10261  }
10262  Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
10263}
10264
10265void Assembler::smlsld(
10266    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10267  VIXL_ASSERT(AllowAssembler());
10268  CheckIT(cond);
10269  if (IsUsingT32()) {
10270    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10271    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10272         AllowUnpredictable())) {
10273      EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10274                 (rn.GetCode() << 16) | rm.GetCode());
10275      AdvanceIT();
10276      return;
10277    }
10278  } else {
10279    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10280    if (cond.IsNotNever() &&
10281        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10282         AllowUnpredictable())) {
10283      EmitA32(0x07400050U | (cond.GetCondition() << 28) |
10284              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10285              (rm.GetCode() << 8));
10286      return;
10287    }
10288  }
10289  Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
10290}
10291
10292void Assembler::smlsldx(
10293    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10294  VIXL_ASSERT(AllowAssembler());
10295  CheckIT(cond);
10296  if (IsUsingT32()) {
10297    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10298    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10299         AllowUnpredictable())) {
10300      EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10301                 (rn.GetCode() << 16) | rm.GetCode());
10302      AdvanceIT();
10303      return;
10304    }
10305  } else {
10306    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10307    if (cond.IsNotNever() &&
10308        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10309         AllowUnpredictable())) {
10310      EmitA32(0x07400070U | (cond.GetCondition() << 28) |
10311              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10312              (rm.GetCode() << 8));
10313      return;
10314    }
10315  }
10316  Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
10317}
10318
10319void Assembler::smmla(
10320    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10321  VIXL_ASSERT(AllowAssembler());
10322  CheckIT(cond);
10323  if (IsUsingT32()) {
10324    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10325    if (!ra.Is(pc) &&
10326        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10327      EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10328                 rm.GetCode() | (ra.GetCode() << 12));
10329      AdvanceIT();
10330      return;
10331    }
10332  } else {
10333    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10334    if (cond.IsNotNever() && !ra.Is(pc) &&
10335        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10336      EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10337              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10338      return;
10339    }
10340  }
10341  Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
10342}
10343
10344void Assembler::smmlar(
10345    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10346  VIXL_ASSERT(AllowAssembler());
10347  CheckIT(cond);
10348  if (IsUsingT32()) {
10349    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10350    if (!ra.Is(pc) &&
10351        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10352      EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10353                 rm.GetCode() | (ra.GetCode() << 12));
10354      AdvanceIT();
10355      return;
10356    }
10357  } else {
10358    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10359    if (cond.IsNotNever() && !ra.Is(pc) &&
10360        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10361      EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10362              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10363      return;
10364    }
10365  }
10366  Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
10367}
10368
10369void Assembler::smmls(
10370    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10371  VIXL_ASSERT(AllowAssembler());
10372  CheckIT(cond);
10373  if (IsUsingT32()) {
10374    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10375    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10376         AllowUnpredictable())) {
10377      EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10378                 rm.GetCode() | (ra.GetCode() << 12));
10379      AdvanceIT();
10380      return;
10381    }
10382  } else {
10383    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10384    if (cond.IsNotNever() &&
10385        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10386         AllowUnpredictable())) {
10387      EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10388              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10389      return;
10390    }
10391  }
10392  Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
10393}
10394
10395void Assembler::smmlsr(
10396    Condition cond, Register rd, Register rn, Register rm, Register ra) {
10397  VIXL_ASSERT(AllowAssembler());
10398  CheckIT(cond);
10399  if (IsUsingT32()) {
10400    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
10401    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10402         AllowUnpredictable())) {
10403      EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10404                 rm.GetCode() | (ra.GetCode() << 12));
10405      AdvanceIT();
10406      return;
10407    }
10408  } else {
10409    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
10410    if (cond.IsNotNever() &&
10411        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10412         AllowUnpredictable())) {
10413      EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10414              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10415      return;
10416    }
10417  }
10418  Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
10419}
10420
10421void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
10422  VIXL_ASSERT(AllowAssembler());
10423  CheckIT(cond);
10424  if (IsUsingT32()) {
10425    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10426    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10427      EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10428                 rm.GetCode());
10429      AdvanceIT();
10430      return;
10431    }
10432  } else {
10433    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10434    if (cond.IsNotNever() &&
10435        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10436      EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10437              rn.GetCode() | (rm.GetCode() << 8));
10438      return;
10439    }
10440  }
10441  Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
10442}
10443
10444void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
10445  VIXL_ASSERT(AllowAssembler());
10446  CheckIT(cond);
10447  if (IsUsingT32()) {
10448    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10449    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10450      EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10451                 rm.GetCode());
10452      AdvanceIT();
10453      return;
10454    }
10455  } else {
10456    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10457    if (cond.IsNotNever() &&
10458        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10459      EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10460              rn.GetCode() | (rm.GetCode() << 8));
10461      return;
10462    }
10463  }
10464  Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
10465}
10466
10467void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
10468  VIXL_ASSERT(AllowAssembler());
10469  CheckIT(cond);
10470  if (IsUsingT32()) {
10471    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10472    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10473      EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10474                 rm.GetCode());
10475      AdvanceIT();
10476      return;
10477    }
10478  } else {
10479    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10480    if (cond.IsNotNever() &&
10481        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10482      EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10483              rn.GetCode() | (rm.GetCode() << 8));
10484      return;
10485    }
10486  }
10487  Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
10488}
10489
10490void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
10491  VIXL_ASSERT(AllowAssembler());
10492  CheckIT(cond);
10493  if (IsUsingT32()) {
10494    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10495    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10496      EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10497                 rm.GetCode());
10498      AdvanceIT();
10499      return;
10500    }
10501  } else {
10502    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10503    if (cond.IsNotNever() &&
10504        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10505      EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10506              rn.GetCode() | (rm.GetCode() << 8));
10507      return;
10508    }
10509  }
10510  Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
10511}
10512
10513void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
10514  VIXL_ASSERT(AllowAssembler());
10515  CheckIT(cond);
10516  if (IsUsingT32()) {
10517    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10518    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10519      EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10520                 rm.GetCode());
10521      AdvanceIT();
10522      return;
10523    }
10524  } else {
10525    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10526    if (cond.IsNotNever() &&
10527        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10528      EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10529              rn.GetCode() | (rm.GetCode() << 8));
10530      return;
10531    }
10532  }
10533  Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
10534}
10535
10536void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
10537  VIXL_ASSERT(AllowAssembler());
10538  CheckIT(cond);
10539  if (IsUsingT32()) {
10540    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10541    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10542      EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10543                 rm.GetCode());
10544      AdvanceIT();
10545      return;
10546    }
10547  } else {
10548    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10549    if (cond.IsNotNever() &&
10550        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10551      EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10552              rn.GetCode() | (rm.GetCode() << 8));
10553      return;
10554    }
10555  }
10556  Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
10557}
10558
10559void Assembler::smull(
10560    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10561  VIXL_ASSERT(AllowAssembler());
10562  CheckIT(cond);
10563  if (IsUsingT32()) {
10564    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
10565    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10566         AllowUnpredictable())) {
10567      EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10568                 (rn.GetCode() << 16) | rm.GetCode());
10569      AdvanceIT();
10570      return;
10571    }
10572  } else {
10573    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10574    if (cond.IsNotNever() &&
10575        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10576         AllowUnpredictable())) {
10577      EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
10578              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10579              (rm.GetCode() << 8));
10580      return;
10581    }
10582  }
10583  Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
10584}
10585
10586void Assembler::smulls(
10587    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
10588  VIXL_ASSERT(AllowAssembler());
10589  CheckIT(cond);
10590  if (IsUsingA32()) {
10591    // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
10592    if (cond.IsNotNever() &&
10593        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10594         AllowUnpredictable())) {
10595      EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
10596              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10597              (rm.GetCode() << 8));
10598      return;
10599    }
10600  }
10601  Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
10602}
10603
10604void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
10605  VIXL_ASSERT(AllowAssembler());
10606  CheckIT(cond);
10607  if (IsUsingT32()) {
10608    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10609    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10610      EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10611                 rm.GetCode());
10612      AdvanceIT();
10613      return;
10614    }
10615  } else {
10616    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10617    if (cond.IsNotNever() &&
10618        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10619      EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10620              rn.GetCode() | (rm.GetCode() << 8));
10621      return;
10622    }
10623  }
10624  Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
10625}
10626
10627void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
10628  VIXL_ASSERT(AllowAssembler());
10629  CheckIT(cond);
10630  if (IsUsingT32()) {
10631    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10632    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10633      EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10634                 rm.GetCode());
10635      AdvanceIT();
10636      return;
10637    }
10638  } else {
10639    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10640    if (cond.IsNotNever() &&
10641        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10642      EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10643              rn.GetCode() | (rm.GetCode() << 8));
10644      return;
10645    }
10646  }
10647  Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
10648}
10649
10650void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
10651  VIXL_ASSERT(AllowAssembler());
10652  CheckIT(cond);
10653  if (IsUsingT32()) {
10654    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10655    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10656      EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10657                 rm.GetCode());
10658      AdvanceIT();
10659      return;
10660    }
10661  } else {
10662    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10663    if (cond.IsNotNever() &&
10664        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10665      EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10666              rn.GetCode() | (rm.GetCode() << 8));
10667      return;
10668    }
10669  }
10670  Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
10671}
10672
10673void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
10674  VIXL_ASSERT(AllowAssembler());
10675  CheckIT(cond);
10676  if (IsUsingT32()) {
10677    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10678    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10679      EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10680                 rm.GetCode());
10681      AdvanceIT();
10682      return;
10683    }
10684  } else {
10685    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10686    if (cond.IsNotNever() &&
10687        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10688      EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10689              rn.GetCode() | (rm.GetCode() << 8));
10690      return;
10691    }
10692  }
10693  Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
10694}
10695
10696void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
10697  VIXL_ASSERT(AllowAssembler());
10698  CheckIT(cond);
10699  if (IsUsingT32()) {
10700    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10701    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10702      EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10703                 rm.GetCode());
10704      AdvanceIT();
10705      return;
10706    }
10707  } else {
10708    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10709    if (cond.IsNotNever() &&
10710        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10711      EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10712              rn.GetCode() | (rm.GetCode() << 8));
10713      return;
10714    }
10715  }
10716  Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
10717}
10718
10719void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
10720  VIXL_ASSERT(AllowAssembler());
10721  CheckIT(cond);
10722  if (IsUsingT32()) {
10723    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10724    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10725      EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10726                 rm.GetCode());
10727      AdvanceIT();
10728      return;
10729    }
10730  } else {
10731    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10732    if (cond.IsNotNever() &&
10733        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10734      EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10735              rn.GetCode() | (rm.GetCode() << 8));
10736      return;
10737    }
10738  }
10739  Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
10740}
10741
10742void Assembler::ssat(Condition cond,
10743                     Register rd,
10744                     uint32_t imm,
10745                     const Operand& operand) {
10746  VIXL_ASSERT(AllowAssembler());
10747  CheckIT(cond);
10748  if (operand.IsImmediateShiftedRegister()) {
10749    Register rn = operand.GetBaseRegister();
10750    Shift shift = operand.GetShift();
10751    uint32_t amount = operand.GetShiftAmount();
10752    if (IsUsingT32()) {
10753      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
10754      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
10755          (amount <= 31) &&
10756          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10757        uint32_t imm_ = imm - 1;
10758        EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10759                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10760                   ((amount & 0x1c) << 10));
10761        AdvanceIT();
10762        return;
10763      }
10764      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
10765      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10766          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10767        uint32_t imm_ = imm - 1;
10768        EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
10769                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10770                   ((amount & 0x1c) << 10));
10771        AdvanceIT();
10772        return;
10773      }
10774    } else {
10775      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
10776      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
10777          (amount <= 32) && cond.IsNotNever() &&
10778          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10779        uint32_t imm_ = imm - 1;
10780        uint32_t amount_ = amount % 32;
10781        EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
10782                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10783                (amount_ << 7));
10784        return;
10785      }
10786      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
10787      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10788          cond.IsNotNever() &&
10789          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10790        uint32_t imm_ = imm - 1;
10791        EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
10792                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10793                (amount << 7));
10794        return;
10795      }
10796    }
10797  }
10798  Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
10799}
10800
10801void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
10802  VIXL_ASSERT(AllowAssembler());
10803  CheckIT(cond);
10804  if (IsUsingT32()) {
10805    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
10806    if ((imm >= 1) && (imm <= 16) &&
10807        ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10808      uint32_t imm_ = imm - 1;
10809      EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10810                 (rn.GetCode() << 16));
10811      AdvanceIT();
10812      return;
10813    }
10814  } else {
10815    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
10816    if ((imm >= 1) && (imm <= 16) && cond.IsNotNever() &&
10817        ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10818      uint32_t imm_ = imm - 1;
10819      EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10820              (imm_ << 16) | rn.GetCode());
10821      return;
10822    }
10823  }
10824  Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
10825}
10826
10827void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
10828  VIXL_ASSERT(AllowAssembler());
10829  CheckIT(cond);
10830  if (IsUsingT32()) {
10831    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10832    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10833      EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10834                 rm.GetCode());
10835      AdvanceIT();
10836      return;
10837    }
10838  } else {
10839    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10840    if (cond.IsNotNever() &&
10841        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10842      EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10843              (rn.GetCode() << 16) | rm.GetCode());
10844      return;
10845    }
10846  }
10847  Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
10848}
10849
10850void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
10851  VIXL_ASSERT(AllowAssembler());
10852  CheckIT(cond);
10853  if (IsUsingT32()) {
10854    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10855    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10856      EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10857                 rm.GetCode());
10858      AdvanceIT();
10859      return;
10860    }
10861  } else {
10862    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10863    if (cond.IsNotNever() &&
10864        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10865      EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10866              (rn.GetCode() << 16) | rm.GetCode());
10867      return;
10868    }
10869  }
10870  Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
10871}
10872
10873void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
10874  VIXL_ASSERT(AllowAssembler());
10875  CheckIT(cond);
10876  if (IsUsingT32()) {
10877    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
10878    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10879      EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10880                 rm.GetCode());
10881      AdvanceIT();
10882      return;
10883    }
10884  } else {
10885    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
10886    if (cond.IsNotNever() &&
10887        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10888      EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10889              (rn.GetCode() << 16) | rm.GetCode());
10890      return;
10891    }
10892  }
10893  Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
10894}
10895
10896void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
10897  VIXL_ASSERT(AllowAssembler());
10898  CheckIT(cond);
10899  if (operand.IsImmediateZero()) {
10900    Register rn = operand.GetBaseRegister();
10901    if (IsUsingT32()) {
10902      // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
10903      if (operand.IsOffset() &&
10904          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10905        EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10906        AdvanceIT();
10907        return;
10908      }
10909    } else {
10910      // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
10911      if (operand.IsOffset() && cond.IsNotNever() &&
10912          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10913        EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10914                (rn.GetCode() << 16));
10915        return;
10916      }
10917    }
10918  }
10919  Delegate(kStl, &Assembler::stl, cond, rt, operand);
10920}
10921
10922void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
10923  VIXL_ASSERT(AllowAssembler());
10924  CheckIT(cond);
10925  if (operand.IsImmediateZero()) {
10926    Register rn = operand.GetBaseRegister();
10927    if (IsUsingT32()) {
10928      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
10929      if (operand.IsOffset() &&
10930          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10931        EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10932        AdvanceIT();
10933        return;
10934      }
10935    } else {
10936      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
10937      if (operand.IsOffset() && cond.IsNotNever() &&
10938          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10939        EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10940                (rn.GetCode() << 16));
10941        return;
10942      }
10943    }
10944  }
10945  Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
10946}
10947
10948void Assembler::stlex(Condition cond,
10949                      Register rd,
10950                      Register rt,
10951                      const MemOperand& operand) {
10952  VIXL_ASSERT(AllowAssembler());
10953  CheckIT(cond);
10954  if (operand.IsImmediateZero()) {
10955    Register rn = operand.GetBaseRegister();
10956    if (IsUsingT32()) {
10957      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10958      if (operand.IsOffset() &&
10959          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10960        EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
10961                   (rn.GetCode() << 16));
10962        AdvanceIT();
10963        return;
10964      }
10965    } else {
10966      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10967      if (operand.IsOffset() && cond.IsNotNever() &&
10968          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10969        EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
10970                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10971        return;
10972      }
10973    }
10974  }
10975  Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
10976}
10977
10978void Assembler::stlexb(Condition cond,
10979                       Register rd,
10980                       Register rt,
10981                       const MemOperand& operand) {
10982  VIXL_ASSERT(AllowAssembler());
10983  CheckIT(cond);
10984  if (operand.IsImmediateZero()) {
10985    Register rn = operand.GetBaseRegister();
10986    if (IsUsingT32()) {
10987      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10988      if (operand.IsOffset() &&
10989          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10990        EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
10991                   (rn.GetCode() << 16));
10992        AdvanceIT();
10993        return;
10994      }
10995    } else {
10996      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10997      if (operand.IsOffset() && cond.IsNotNever() &&
10998          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
10999        EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
11000                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11001        return;
11002      }
11003    }
11004  }
11005  Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
11006}
11007
11008void Assembler::stlexd(Condition cond,
11009                       Register rd,
11010                       Register rt,
11011                       Register rt2,
11012                       const MemOperand& operand) {
11013  VIXL_ASSERT(AllowAssembler());
11014  CheckIT(cond);
11015  if (operand.IsImmediateZero()) {
11016    Register rn = operand.GetBaseRegister();
11017    if (IsUsingT32()) {
11018      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
11019      if (operand.IsOffset() &&
11020          ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11021           AllowUnpredictable())) {
11022        EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
11023                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11024        AdvanceIT();
11025        return;
11026      }
11027    } else {
11028      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11029      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11030          operand.IsOffset() && cond.IsNotNever() &&
11031          ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11032            !rn.IsPC()) ||
11033           AllowUnpredictable())) {
11034        EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
11035                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11036        return;
11037      }
11038    }
11039  }
11040  Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
11041}
11042
11043void Assembler::stlexh(Condition cond,
11044                       Register rd,
11045                       Register rt,
11046                       const MemOperand& operand) {
11047  VIXL_ASSERT(AllowAssembler());
11048  CheckIT(cond);
11049  if (operand.IsImmediateZero()) {
11050    Register rn = operand.GetBaseRegister();
11051    if (IsUsingT32()) {
11052      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11053      if (operand.IsOffset() &&
11054          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11055        EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
11056                   (rn.GetCode() << 16));
11057        AdvanceIT();
11058        return;
11059      }
11060    } else {
11061      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11062      if (operand.IsOffset() && cond.IsNotNever() &&
11063          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11064        EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
11065                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11066        return;
11067      }
11068    }
11069  }
11070  Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
11071}
11072
11073void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
11074  VIXL_ASSERT(AllowAssembler());
11075  CheckIT(cond);
11076  if (operand.IsImmediateZero()) {
11077    Register rn = operand.GetBaseRegister();
11078    if (IsUsingT32()) {
11079      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
11080      if (operand.IsOffset() &&
11081          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11082        EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
11083        AdvanceIT();
11084        return;
11085      }
11086    } else {
11087      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
11088      if (operand.IsOffset() && cond.IsNotNever() &&
11089          ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11090        EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
11091                (rn.GetCode() << 16));
11092        return;
11093      }
11094    }
11095  }
11096  Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
11097}
11098
11099void Assembler::stm(Condition cond,
11100                    EncodingSize size,
11101                    Register rn,
11102                    WriteBack write_back,
11103                    RegisterList registers) {
11104  VIXL_ASSERT(AllowAssembler());
11105  CheckIT(cond);
11106  if (IsUsingT32()) {
11107    // STM{<c>}{<q>} <Rn>!, <registers> ; T1
11108    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11109        ((registers.GetList() & ~0xff) == 0)) {
11110      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11111                 GetRegisterListEncoding(registers, 0, 8));
11112      AdvanceIT();
11113      return;
11114    }
11115    // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
11116    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11117        (!rn.IsPC() || AllowUnpredictable())) {
11118      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11119                 (write_back.GetWriteBackUint32() << 21) |
11120                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11121                 GetRegisterListEncoding(registers, 0, 13));
11122      AdvanceIT();
11123      return;
11124    }
11125  } else {
11126    // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
11127    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11128      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11129              (write_back.GetWriteBackUint32() << 21) |
11130              GetRegisterListEncoding(registers, 0, 16));
11131      return;
11132    }
11133  }
11134  Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
11135}
11136
11137void Assembler::stmda(Condition cond,
11138                      Register rn,
11139                      WriteBack write_back,
11140                      RegisterList registers) {
11141  VIXL_ASSERT(AllowAssembler());
11142  CheckIT(cond);
11143  if (IsUsingA32()) {
11144    // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
11145    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11146      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11147              (write_back.GetWriteBackUint32() << 21) |
11148              GetRegisterListEncoding(registers, 0, 16));
11149      return;
11150    }
11151  }
11152  Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
11153}
11154
11155void Assembler::stmdb(Condition cond,
11156                      EncodingSize size,
11157                      Register rn,
11158                      WriteBack write_back,
11159                      RegisterList registers) {
11160  VIXL_ASSERT(AllowAssembler());
11161  CheckIT(cond);
11162  if (IsUsingT32()) {
11163    // STMDB{<c>}{<q>} SP!, <registers> ; T1
11164    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
11165        ((registers.GetList() & ~0x40ff) == 0)) {
11166      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
11167                 GetRegisterListEncoding(registers, 0, 8));
11168      AdvanceIT();
11169      return;
11170    }
11171    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
11172    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11173        (!rn.IsPC() || AllowUnpredictable())) {
11174      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11175                 (write_back.GetWriteBackUint32() << 21) |
11176                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11177                 GetRegisterListEncoding(registers, 0, 13));
11178      AdvanceIT();
11179      return;
11180    }
11181  } else {
11182    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
11183    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11184      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11185              (write_back.GetWriteBackUint32() << 21) |
11186              GetRegisterListEncoding(registers, 0, 16));
11187      return;
11188    }
11189  }
11190  Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
11191}
11192
11193void Assembler::stmea(Condition cond,
11194                      EncodingSize size,
11195                      Register rn,
11196                      WriteBack write_back,
11197                      RegisterList registers) {
11198  VIXL_ASSERT(AllowAssembler());
11199  CheckIT(cond);
11200  if (IsUsingT32()) {
11201    // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
11202    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11203        ((registers.GetList() & ~0xff) == 0)) {
11204      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11205                 GetRegisterListEncoding(registers, 0, 8));
11206      AdvanceIT();
11207      return;
11208    }
11209    // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
11210    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11211        (!rn.IsPC() || AllowUnpredictable())) {
11212      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11213                 (write_back.GetWriteBackUint32() << 21) |
11214                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11215                 GetRegisterListEncoding(registers, 0, 13));
11216      AdvanceIT();
11217      return;
11218    }
11219    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
11220    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11221        (!rn.IsPC() || AllowUnpredictable())) {
11222      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11223                 (write_back.GetWriteBackUint32() << 21) |
11224                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11225                 GetRegisterListEncoding(registers, 0, 13));
11226      AdvanceIT();
11227      return;
11228    }
11229  } else {
11230    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
11231    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11232      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11233              (write_back.GetWriteBackUint32() << 21) |
11234              GetRegisterListEncoding(registers, 0, 16));
11235      return;
11236    }
11237  }
11238  Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
11239}
11240
11241void Assembler::stmed(Condition cond,
11242                      Register rn,
11243                      WriteBack write_back,
11244                      RegisterList registers) {
11245  VIXL_ASSERT(AllowAssembler());
11246  CheckIT(cond);
11247  if (IsUsingA32()) {
11248    // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
11249    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11250      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11251              (write_back.GetWriteBackUint32() << 21) |
11252              GetRegisterListEncoding(registers, 0, 16));
11253      return;
11254    }
11255  }
11256  Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
11257}
11258
11259void Assembler::stmfa(Condition cond,
11260                      Register rn,
11261                      WriteBack write_back,
11262                      RegisterList registers) {
11263  VIXL_ASSERT(AllowAssembler());
11264  CheckIT(cond);
11265  if (IsUsingA32()) {
11266    // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
11267    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11268      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11269              (write_back.GetWriteBackUint32() << 21) |
11270              GetRegisterListEncoding(registers, 0, 16));
11271      return;
11272    }
11273  }
11274  Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
11275}
11276
11277void Assembler::stmfd(Condition cond,
11278                      Register rn,
11279                      WriteBack write_back,
11280                      RegisterList registers) {
11281  VIXL_ASSERT(AllowAssembler());
11282  CheckIT(cond);
11283  if (IsUsingT32()) {
11284    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
11285    if (((registers.GetList() & ~0x5fff) == 0) &&
11286        (!rn.IsPC() || AllowUnpredictable())) {
11287      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11288                 (write_back.GetWriteBackUint32() << 21) |
11289                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11290                 GetRegisterListEncoding(registers, 0, 13));
11291      AdvanceIT();
11292      return;
11293    }
11294  } else {
11295    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
11296    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11297      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11298              (write_back.GetWriteBackUint32() << 21) |
11299              GetRegisterListEncoding(registers, 0, 16));
11300      return;
11301    }
11302  }
11303  Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
11304}
11305
11306void Assembler::stmib(Condition cond,
11307                      Register rn,
11308                      WriteBack write_back,
11309                      RegisterList registers) {
11310  VIXL_ASSERT(AllowAssembler());
11311  CheckIT(cond);
11312  if (IsUsingA32()) {
11313    // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
11314    if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
11315      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11316              (write_back.GetWriteBackUint32() << 21) |
11317              GetRegisterListEncoding(registers, 0, 16));
11318      return;
11319    }
11320  }
11321  Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
11322}
11323
11324void Assembler::str(Condition cond,
11325                    EncodingSize size,
11326                    Register rt,
11327                    const MemOperand& operand) {
11328  VIXL_ASSERT(AllowAssembler());
11329  CheckIT(cond);
11330  if (operand.IsImmediate()) {
11331    Register rn = operand.GetBaseRegister();
11332    int32_t offset = operand.GetOffsetImmediate();
11333    if (IsUsingT32()) {
11334      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11335      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
11336          (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
11337        int32_t offset_ = offset >> 2;
11338        EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
11339                   ((offset_ & 0x1f) << 6));
11340        AdvanceIT();
11341        return;
11342      }
11343      // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
11344      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
11345          ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
11346        int32_t offset_ = offset >> 2;
11347        EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
11348        AdvanceIT();
11349        return;
11350      }
11351      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
11352      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
11353          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11354          (!rt.IsPC() || AllowUnpredictable())) {
11355        EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11356                   (offset & 0xfff));
11357        AdvanceIT();
11358        return;
11359      }
11360      // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
11361      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
11362          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11363          (!rt.IsPC() || AllowUnpredictable())) {
11364        EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11365                   (-offset & 0xff));
11366        AdvanceIT();
11367        return;
11368      }
11369      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
11370      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11371          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11372          (!rt.IsPC() || AllowUnpredictable())) {
11373        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11374        uint32_t offset_ = abs(offset);
11375        EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11376                   offset_ | (sign << 9));
11377        AdvanceIT();
11378        return;
11379      }
11380      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
11381      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11382          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11383          (!rt.IsPC() || AllowUnpredictable())) {
11384        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11385        uint32_t offset_ = abs(offset);
11386        EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11387                   offset_ | (sign << 9));
11388        AdvanceIT();
11389        return;
11390      }
11391    } else {
11392      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
11393      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11394          cond.IsNotNever()) {
11395        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11396        uint32_t offset_ = abs(offset);
11397        EmitA32(0x05000000U | (cond.GetCondition() << 28) |
11398                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11399                (sign << 23));
11400        return;
11401      }
11402      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11403      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11404          cond.IsNotNever()) {
11405        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11406        uint32_t offset_ = abs(offset);
11407        EmitA32(0x04000000U | (cond.GetCondition() << 28) |
11408                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11409                (sign << 23));
11410        return;
11411      }
11412      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11413      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11414          cond.IsNotNever()) {
11415        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11416        uint32_t offset_ = abs(offset);
11417        EmitA32(0x05200000U | (cond.GetCondition() << 28) |
11418                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11419                (sign << 23));
11420        return;
11421      }
11422    }
11423  }
11424  if (operand.IsPlainRegister()) {
11425    Register rn = operand.GetBaseRegister();
11426    Sign sign = operand.GetSign();
11427    Register rm = operand.GetOffsetRegister();
11428    if (IsUsingT32()) {
11429      // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11430      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11431          sign.IsPlus() && operand.IsOffset()) {
11432        EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
11433                   (rm.GetCode() << 6));
11434        AdvanceIT();
11435        return;
11436      }
11437    }
11438  }
11439  if (operand.IsShiftedRegister()) {
11440    Register rn = operand.GetBaseRegister();
11441    Sign sign = operand.GetSign();
11442    Register rm = operand.GetOffsetRegister();
11443    Shift shift = operand.GetShift();
11444    uint32_t amount = operand.GetShiftAmount();
11445    if (IsUsingT32()) {
11446      // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11447      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11448          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11449          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11450        EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11451                   rm.GetCode() | (amount << 4));
11452        AdvanceIT();
11453        return;
11454      }
11455    } else {
11456      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
11457      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11458          (!rm.IsPC() || AllowUnpredictable())) {
11459        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11460        uint32_t shift_ = TypeEncodingValue(shift);
11461        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11462        EmitA32(0x07000000U | (cond.GetCondition() << 28) |
11463                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11464                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11465        return;
11466      }
11467      // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
11468      if (operand.IsShiftValid() && operand.IsPostIndex() &&
11469          cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
11470        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11471        uint32_t shift_ = TypeEncodingValue(shift);
11472        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11473        EmitA32(0x06000000U | (cond.GetCondition() << 28) |
11474                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11475                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11476        return;
11477      }
11478      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
11479      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11480          (!rm.IsPC() || AllowUnpredictable())) {
11481        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11482        uint32_t shift_ = TypeEncodingValue(shift);
11483        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11484        EmitA32(0x07200000U | (cond.GetCondition() << 28) |
11485                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11486                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11487        return;
11488      }
11489    }
11490  }
11491  Delegate(kStr, &Assembler::str, cond, size, rt, operand);
11492}
11493
11494void Assembler::strb(Condition cond,
11495                     EncodingSize size,
11496                     Register rt,
11497                     const MemOperand& operand) {
11498  VIXL_ASSERT(AllowAssembler());
11499  CheckIT(cond);
11500  if (operand.IsImmediate()) {
11501    Register rn = operand.GetBaseRegister();
11502    int32_t offset = operand.GetOffsetImmediate();
11503    if (IsUsingT32()) {
11504      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11505      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
11506          (offset <= 31) && operand.IsOffset()) {
11507        EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
11508                   ((offset & 0x1f) << 6));
11509        AdvanceIT();
11510        return;
11511      }
11512      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11513      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
11514          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11515          (!rt.IsPC() || AllowUnpredictable())) {
11516        EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11517                   (offset & 0xfff));
11518        AdvanceIT();
11519        return;
11520      }
11521      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11522      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
11523          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11524          (!rt.IsPC() || AllowUnpredictable())) {
11525        EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11526                   (-offset & 0xff));
11527        AdvanceIT();
11528        return;
11529      }
11530      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11531      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11532          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11533          (!rt.IsPC() || AllowUnpredictable())) {
11534        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11535        uint32_t offset_ = abs(offset);
11536        EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11537                   offset_ | (sign << 9));
11538        AdvanceIT();
11539        return;
11540      }
11541      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11542      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11543          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11544          (!rt.IsPC() || AllowUnpredictable())) {
11545        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11546        uint32_t offset_ = abs(offset);
11547        EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11548                   offset_ | (sign << 9));
11549        AdvanceIT();
11550        return;
11551      }
11552    } else {
11553      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
11554      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11555          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11556        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11557        uint32_t offset_ = abs(offset);
11558        EmitA32(0x05400000U | (cond.GetCondition() << 28) |
11559                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11560                (sign << 23));
11561        return;
11562      }
11563      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11564      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11565          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11566        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11567        uint32_t offset_ = abs(offset);
11568        EmitA32(0x04400000U | (cond.GetCondition() << 28) |
11569                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11570                (sign << 23));
11571        return;
11572      }
11573      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11574      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11575          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11576        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11577        uint32_t offset_ = abs(offset);
11578        EmitA32(0x05600000U | (cond.GetCondition() << 28) |
11579                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11580                (sign << 23));
11581        return;
11582      }
11583    }
11584  }
11585  if (operand.IsPlainRegister()) {
11586    Register rn = operand.GetBaseRegister();
11587    Sign sign = operand.GetSign();
11588    Register rm = operand.GetOffsetRegister();
11589    if (IsUsingT32()) {
11590      // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11591      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11592          sign.IsPlus() && operand.IsOffset()) {
11593        EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
11594                   (rm.GetCode() << 6));
11595        AdvanceIT();
11596        return;
11597      }
11598    }
11599  }
11600  if (operand.IsShiftedRegister()) {
11601    Register rn = operand.GetBaseRegister();
11602    Sign sign = operand.GetSign();
11603    Register rm = operand.GetOffsetRegister();
11604    Shift shift = operand.GetShift();
11605    uint32_t amount = operand.GetShiftAmount();
11606    if (IsUsingT32()) {
11607      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11608      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11609          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11610          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11611        EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11612                   rm.GetCode() | (amount << 4));
11613        AdvanceIT();
11614        return;
11615      }
11616    } else {
11617      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
11618      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11619          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11620        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11621        uint32_t shift_ = TypeEncodingValue(shift);
11622        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11623        EmitA32(0x07400000U | (cond.GetCondition() << 28) |
11624                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11625                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11626        return;
11627      }
11628      // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
11629      if (operand.IsShiftValid() && operand.IsPostIndex() &&
11630          cond.IsNotNever() &&
11631          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11632        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11633        uint32_t shift_ = TypeEncodingValue(shift);
11634        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11635        EmitA32(0x06400000U | (cond.GetCondition() << 28) |
11636                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11637                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11638        return;
11639      }
11640      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
11641      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11642          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
11643        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11644        uint32_t shift_ = TypeEncodingValue(shift);
11645        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11646        EmitA32(0x07600000U | (cond.GetCondition() << 28) |
11647                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11648                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11649        return;
11650      }
11651    }
11652  }
11653  Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
11654}
11655
11656void Assembler::strd(Condition cond,
11657                     Register rt,
11658                     Register rt2,
11659                     const MemOperand& operand) {
11660  VIXL_ASSERT(AllowAssembler());
11661  CheckIT(cond);
11662  if (operand.IsImmediate()) {
11663    Register rn = operand.GetBaseRegister();
11664    int32_t offset = operand.GetOffsetImmediate();
11665    if (IsUsingT32()) {
11666      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
11667      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
11668          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11669          ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
11670        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11671        uint32_t offset_ = abs(offset) >> 2;
11672        EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11673                   (rn.GetCode() << 16) | offset_ | (sign << 23));
11674        AdvanceIT();
11675        return;
11676      }
11677      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
11678      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
11679          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11680          ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
11681        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11682        uint32_t offset_ = abs(offset) >> 2;
11683        EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11684                   (rn.GetCode() << 16) | offset_ | (sign << 23));
11685        AdvanceIT();
11686        return;
11687      }
11688      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
11689      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
11690          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11691          ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
11692        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11693        uint32_t offset_ = abs(offset) >> 2;
11694        EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11695                   (rn.GetCode() << 16) | offset_ | (sign << 23));
11696        AdvanceIT();
11697        return;
11698      }
11699    } else {
11700      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
11701      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11702          (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
11703          cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11704                                AllowUnpredictable())) {
11705        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11706        uint32_t offset_ = abs(offset);
11707        EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
11708                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11709                ((offset_ & 0xf0) << 4) | (sign << 23));
11710        return;
11711      }
11712      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
11713      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11714          (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
11715          cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11716                                AllowUnpredictable())) {
11717        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11718        uint32_t offset_ = abs(offset);
11719        EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
11720                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11721                ((offset_ & 0xf0) << 4) | (sign << 23));
11722        return;
11723      }
11724      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
11725      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11726          (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
11727          cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11728                                AllowUnpredictable())) {
11729        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11730        uint32_t offset_ = abs(offset);
11731        EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
11732                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11733                ((offset_ & 0xf0) << 4) | (sign << 23));
11734        return;
11735      }
11736    }
11737  }
11738  if (operand.IsPlainRegister()) {
11739    Register rn = operand.GetBaseRegister();
11740    Sign sign = operand.GetSign();
11741    Register rm = operand.GetOffsetRegister();
11742    if (IsUsingA32()) {
11743      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
11744      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11745          operand.IsOffset() && cond.IsNotNever() &&
11746          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
11747           AllowUnpredictable())) {
11748        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11749        EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
11750                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11751                (sign_ << 23));
11752        return;
11753      }
11754      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
11755      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11756          operand.IsPostIndex() && cond.IsNotNever() &&
11757          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
11758           AllowUnpredictable())) {
11759        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11760        EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
11761                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11762                (sign_ << 23));
11763        return;
11764      }
11765      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
11766      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11767          operand.IsPreIndex() && cond.IsNotNever() &&
11768          ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
11769           AllowUnpredictable())) {
11770        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11771        EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
11772                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11773                (sign_ << 23));
11774        return;
11775      }
11776    }
11777  }
11778  Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
11779}
11780
11781void Assembler::strex(Condition cond,
11782                      Register rd,
11783                      Register rt,
11784                      const MemOperand& operand) {
11785  VIXL_ASSERT(AllowAssembler());
11786  CheckIT(cond);
11787  if (operand.IsImmediate()) {
11788    Register rn = operand.GetBaseRegister();
11789    int32_t offset = operand.GetOffsetImmediate();
11790    if (IsUsingT32()) {
11791      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
11792      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
11793          operand.IsOffset() &&
11794          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11795        int32_t offset_ = offset >> 2;
11796        EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
11797                   (rn.GetCode() << 16) | (offset_ & 0xff));
11798        AdvanceIT();
11799        return;
11800      }
11801    } else {
11802      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
11803      if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
11804          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11805        EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
11806                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11807        return;
11808      }
11809    }
11810  }
11811  Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
11812}
11813
11814void Assembler::strexb(Condition cond,
11815                       Register rd,
11816                       Register rt,
11817                       const MemOperand& operand) {
11818  VIXL_ASSERT(AllowAssembler());
11819  CheckIT(cond);
11820  if (operand.IsImmediateZero()) {
11821    Register rn = operand.GetBaseRegister();
11822    if (IsUsingT32()) {
11823      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11824      if (operand.IsOffset() &&
11825          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11826        EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
11827                   (rn.GetCode() << 16));
11828        AdvanceIT();
11829        return;
11830      }
11831    } else {
11832      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11833      if (operand.IsOffset() && cond.IsNotNever() &&
11834          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11835        EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
11836                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11837        return;
11838      }
11839    }
11840  }
11841  Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
11842}
11843
11844void Assembler::strexd(Condition cond,
11845                       Register rd,
11846                       Register rt,
11847                       Register rt2,
11848                       const MemOperand& operand) {
11849  VIXL_ASSERT(AllowAssembler());
11850  CheckIT(cond);
11851  if (operand.IsImmediateZero()) {
11852    Register rn = operand.GetBaseRegister();
11853    if (IsUsingT32()) {
11854      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
11855      if (operand.IsOffset() &&
11856          ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11857           AllowUnpredictable())) {
11858        EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
11859                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11860        AdvanceIT();
11861        return;
11862      }
11863    } else {
11864      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11865      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
11866          operand.IsOffset() && cond.IsNotNever() &&
11867          ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11868            !rn.IsPC()) ||
11869           AllowUnpredictable())) {
11870        EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
11871                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11872        return;
11873      }
11874    }
11875  }
11876  Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
11877}
11878
11879void Assembler::strexh(Condition cond,
11880                       Register rd,
11881                       Register rt,
11882                       const MemOperand& operand) {
11883  VIXL_ASSERT(AllowAssembler());
11884  CheckIT(cond);
11885  if (operand.IsImmediateZero()) {
11886    Register rn = operand.GetBaseRegister();
11887    if (IsUsingT32()) {
11888      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
11889      if (operand.IsOffset() &&
11890          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11891        EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
11892                   (rn.GetCode() << 16));
11893        AdvanceIT();
11894        return;
11895      }
11896    } else {
11897      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
11898      if (operand.IsOffset() && cond.IsNotNever() &&
11899          ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
11900        EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
11901                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11902        return;
11903      }
11904    }
11905  }
11906  Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
11907}
11908
11909void Assembler::strh(Condition cond,
11910                     EncodingSize size,
11911                     Register rt,
11912                     const MemOperand& operand) {
11913  VIXL_ASSERT(AllowAssembler());
11914  CheckIT(cond);
11915  if (operand.IsImmediate()) {
11916    Register rn = operand.GetBaseRegister();
11917    int32_t offset = operand.GetOffsetImmediate();
11918    if (IsUsingT32()) {
11919      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11920      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
11921          (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
11922        int32_t offset_ = offset >> 1;
11923        EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
11924                   ((offset_ & 0x1f) << 6));
11925        AdvanceIT();
11926        return;
11927      }
11928      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11929      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
11930          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11931          (!rt.IsPC() || AllowUnpredictable())) {
11932        EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11933                   (offset & 0xfff));
11934        AdvanceIT();
11935        return;
11936      }
11937      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11938      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
11939          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11940          (!rt.IsPC() || AllowUnpredictable())) {
11941        EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11942                   (-offset & 0xff));
11943        AdvanceIT();
11944        return;
11945      }
11946      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11947      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11948          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11949          (!rt.IsPC() || AllowUnpredictable())) {
11950        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11951        uint32_t offset_ = abs(offset);
11952        EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11953                   offset_ | (sign << 9));
11954        AdvanceIT();
11955        return;
11956      }
11957      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11958      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
11959          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11960          (!rt.IsPC() || AllowUnpredictable())) {
11961        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11962        uint32_t offset_ = abs(offset);
11963        EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11964                   offset_ | (sign << 9));
11965        AdvanceIT();
11966        return;
11967      }
11968    } else {
11969      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
11970      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
11971          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11972        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11973        uint32_t offset_ = abs(offset);
11974        EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
11975                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11976                ((offset_ & 0xf0) << 4) | (sign << 23));
11977        return;
11978      }
11979      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11980      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
11981          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11982        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11983        uint32_t offset_ = abs(offset);
11984        EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
11985                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11986                ((offset_ & 0xf0) << 4) | (sign << 23));
11987        return;
11988      }
11989      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11990      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
11991          cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
11992        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11993        uint32_t offset_ = abs(offset);
11994        EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
11995                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11996                ((offset_ & 0xf0) << 4) | (sign << 23));
11997        return;
11998      }
11999    }
12000  }
12001  if (operand.IsPlainRegister()) {
12002    Register rn = operand.GetBaseRegister();
12003    Sign sign = operand.GetSign();
12004    Register rm = operand.GetOffsetRegister();
12005    if (IsUsingT32()) {
12006      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
12007      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
12008          sign.IsPlus() && operand.IsOffset()) {
12009        EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
12010                   (rm.GetCode() << 6));
12011        AdvanceIT();
12012        return;
12013      }
12014    } else {
12015      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
12016      if (operand.IsOffset() && cond.IsNotNever() &&
12017          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12018        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12019        EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
12020                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12021                (sign_ << 23));
12022        return;
12023      }
12024      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
12025      if (operand.IsPostIndex() && cond.IsNotNever() &&
12026          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12027        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12028        EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
12029                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12030                (sign_ << 23));
12031        return;
12032      }
12033      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
12034      if (operand.IsPreIndex() && cond.IsNotNever() &&
12035          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12036        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12037        EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
12038                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12039                (sign_ << 23));
12040        return;
12041      }
12042    }
12043  }
12044  if (operand.IsShiftedRegister()) {
12045    Register rn = operand.GetBaseRegister();
12046    Sign sign = operand.GetSign();
12047    Register rm = operand.GetOffsetRegister();
12048    Shift shift = operand.GetShift();
12049    uint32_t amount = operand.GetShiftAmount();
12050    if (IsUsingT32()) {
12051      // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
12052      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
12053          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
12054          ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12055        EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12056                   rm.GetCode() | (amount << 4));
12057        AdvanceIT();
12058        return;
12059      }
12060    }
12061  }
12062  Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
12063}
12064
12065void Assembler::sub(Condition cond,
12066                    EncodingSize size,
12067                    Register rd,
12068                    Register rn,
12069                    const Operand& operand) {
12070  VIXL_ASSERT(AllowAssembler());
12071  CheckIT(cond);
12072  if (operand.IsImmediate()) {
12073    uint32_t imm = operand.GetImmediate();
12074    if (IsUsingT32()) {
12075      ImmediateT32 immediate_t32(imm);
12076      // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
12077      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12078          (imm <= 7)) {
12079        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12080        AdvanceIT();
12081        return;
12082      }
12083      // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12084      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12085          (imm <= 255)) {
12086        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12087        AdvanceIT();
12088        return;
12089      }
12090      // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
12091      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
12092          ((imm % 4) == 0)) {
12093        uint32_t imm_ = imm >> 2;
12094        EmitT32_16(0xb080 | imm_);
12095        AdvanceIT();
12096        return;
12097      }
12098      // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
12099      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
12100          (!rd.IsPC() || AllowUnpredictable())) {
12101        EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12102                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12103        AdvanceIT();
12104        return;
12105      }
12106      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12107      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12108          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
12109        EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12110                   (immediate_t32.GetEncodingValue() & 0xff) |
12111                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12112                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12113        AdvanceIT();
12114        return;
12115      }
12116      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
12117      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12118          (!rd.IsPC() || AllowUnpredictable())) {
12119        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12120                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12121        AdvanceIT();
12122        return;
12123      }
12124      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12125      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12126          (!rd.IsPC() || AllowUnpredictable())) {
12127        EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
12128                   (immediate_t32.GetEncodingValue() & 0xff) |
12129                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12130                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12131        AdvanceIT();
12132        return;
12133      }
12134      // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
12135      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
12136          (!rd.IsPC() || AllowUnpredictable())) {
12137        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12138                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12139        AdvanceIT();
12140        return;
12141      }
12142    } else {
12143      ImmediateA32 immediate_a32(imm);
12144      // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
12145      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
12146        EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
12147                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12148        return;
12149      }
12150      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12151      if (immediate_a32.IsValid() && cond.IsNotNever() &&
12152          ((rn.GetCode() & 0xd) != 0xd)) {
12153        EmitA32(0x02400000U | (cond.GetCondition() << 28) |
12154                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12155                immediate_a32.GetEncodingValue());
12156        return;
12157      }
12158      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12159      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12160        EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
12161                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12162        return;
12163      }
12164    }
12165  }
12166  if (operand.IsImmediateShiftedRegister()) {
12167    Register rm = operand.GetBaseRegister();
12168    if (operand.IsPlainRegister()) {
12169      if (IsUsingT32()) {
12170        // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
12171        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12172            rm.IsLow()) {
12173          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12174                     (rm.GetCode() << 6));
12175          AdvanceIT();
12176          return;
12177        }
12178        // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
12179        if (rn.Is(sp) && ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12180          EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
12181          AdvanceIT();
12182          return;
12183        }
12184      }
12185    }
12186    Shift shift = operand.GetShift();
12187    uint32_t amount = operand.GetShiftAmount();
12188    if (IsUsingT32()) {
12189      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12190      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12191          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12192        uint32_t amount_ = amount % 32;
12193        EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12194                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12195                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12196        AdvanceIT();
12197        return;
12198      }
12199      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12200      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12201          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12202        uint32_t amount_ = amount % 32;
12203        EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
12204                   (operand.GetTypeEncodingValue() << 4) |
12205                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12206        AdvanceIT();
12207        return;
12208      }
12209    } else {
12210      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12211      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12212        uint32_t amount_ = amount % 32;
12213        EmitA32(0x00400000U | (cond.GetCondition() << 28) |
12214                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12215                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12216        return;
12217      }
12218      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12219      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12220        uint32_t amount_ = amount % 32;
12221        EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
12222                (rd.GetCode() << 12) | rm.GetCode() |
12223                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12224        return;
12225      }
12226    }
12227  }
12228  if (operand.IsRegisterShiftedRegister()) {
12229    Register rm = operand.GetBaseRegister();
12230    Shift shift = operand.GetShift();
12231    Register rs = operand.GetShiftRegister();
12232    if (IsUsingA32()) {
12233      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
12234      if (cond.IsNotNever() &&
12235          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12236           AllowUnpredictable())) {
12237        EmitA32(0x00400010U | (cond.GetCondition() << 28) |
12238                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12239                (shift.GetType() << 5) | (rs.GetCode() << 8));
12240        return;
12241      }
12242    }
12243  }
12244  Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
12245}
12246
12247void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
12248  VIXL_ASSERT(AllowAssembler());
12249  CheckIT(cond);
12250  if (operand.IsImmediate()) {
12251    uint32_t imm = operand.GetImmediate();
12252    if (IsUsingT32()) {
12253      // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
12254      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
12255        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12256        AdvanceIT();
12257        return;
12258      }
12259    }
12260  }
12261  Delegate(kSub, &Assembler::sub, cond, rd, operand);
12262}
12263
12264void Assembler::subs(Condition cond,
12265                     EncodingSize size,
12266                     Register rd,
12267                     Register rn,
12268                     const Operand& operand) {
12269  VIXL_ASSERT(AllowAssembler());
12270  CheckIT(cond);
12271  if (operand.IsImmediate()) {
12272    uint32_t imm = operand.GetImmediate();
12273    if (IsUsingT32()) {
12274      ImmediateT32 immediate_t32(imm);
12275      // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
12276      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12277          (imm <= 7)) {
12278        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12279        AdvanceIT();
12280        return;
12281      }
12282      // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12283      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12284          (imm <= 255)) {
12285        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12286        AdvanceIT();
12287        return;
12288      }
12289      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12290      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12291          !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
12292        EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12293                   (immediate_t32.GetEncodingValue() & 0xff) |
12294                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12295                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12296        AdvanceIT();
12297        return;
12298      }
12299      // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
12300      if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255) &&
12301          (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
12302        EmitT32_32(0xf3de8f00U | imm);
12303        AdvanceIT();
12304        return;
12305      }
12306      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12307      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12308          !rd.Is(pc)) {
12309        EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
12310                   (immediate_t32.GetEncodingValue() & 0xff) |
12311                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12312                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12313        AdvanceIT();
12314        return;
12315      }
12316    } else {
12317      ImmediateA32 immediate_a32(imm);
12318      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12319      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
12320        EmitA32(0x02500000U | (cond.GetCondition() << 28) |
12321                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12322                immediate_a32.GetEncodingValue());
12323        return;
12324      }
12325      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12326      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12327        EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
12328                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12329        return;
12330      }
12331    }
12332  }
12333  if (operand.IsImmediateShiftedRegister()) {
12334    Register rm = operand.GetBaseRegister();
12335    if (operand.IsPlainRegister()) {
12336      if (IsUsingT32()) {
12337        // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12338        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12339            rm.IsLow()) {
12340          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12341                     (rm.GetCode() << 6));
12342          AdvanceIT();
12343          return;
12344        }
12345      }
12346    }
12347    Shift shift = operand.GetShift();
12348    uint32_t amount = operand.GetShiftAmount();
12349    if (IsUsingT32()) {
12350      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12351      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12352          !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12353        uint32_t amount_ = amount % 32;
12354        EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12355                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12356                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12357        AdvanceIT();
12358        return;
12359      }
12360      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12361      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12362          !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
12363        uint32_t amount_ = amount % 32;
12364        EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
12365                   (operand.GetTypeEncodingValue() << 4) |
12366                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12367        AdvanceIT();
12368        return;
12369      }
12370    } else {
12371      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12372      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12373        uint32_t amount_ = amount % 32;
12374        EmitA32(0x00500000U | (cond.GetCondition() << 28) |
12375                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12376                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12377        return;
12378      }
12379      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12380      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12381        uint32_t amount_ = amount % 32;
12382        EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
12383                (rd.GetCode() << 12) | rm.GetCode() |
12384                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12385        return;
12386      }
12387    }
12388  }
12389  if (operand.IsRegisterShiftedRegister()) {
12390    Register rm = operand.GetBaseRegister();
12391    Shift shift = operand.GetShift();
12392    Register rs = operand.GetShiftRegister();
12393    if (IsUsingA32()) {
12394      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
12395      if (cond.IsNotNever() &&
12396          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12397           AllowUnpredictable())) {
12398        EmitA32(0x00500010U | (cond.GetCondition() << 28) |
12399                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12400                (shift.GetType() << 5) | (rs.GetCode() << 8));
12401        return;
12402      }
12403    }
12404  }
12405  Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
12406}
12407
12408void Assembler::subs(Register rd, const Operand& operand) {
12409  VIXL_ASSERT(AllowAssembler());
12410  CheckIT(al);
12411  if (operand.IsImmediate()) {
12412    uint32_t imm = operand.GetImmediate();
12413    if (IsUsingT32()) {
12414      // SUBS{<q>} <Rdn>, #<imm8> ; T2
12415      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
12416        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12417        AdvanceIT();
12418        return;
12419      }
12420    }
12421  }
12422  Delegate(kSubs, &Assembler::subs, rd, operand);
12423}
12424
12425void Assembler::subw(Condition cond,
12426                     Register rd,
12427                     Register rn,
12428                     const Operand& operand) {
12429  VIXL_ASSERT(AllowAssembler());
12430  CheckIT(cond);
12431  if (operand.IsImmediate()) {
12432    uint32_t imm = operand.GetImmediate();
12433    if (IsUsingT32()) {
12434      // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
12435      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12436          (!rd.IsPC() || AllowUnpredictable())) {
12437        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12438                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12439        AdvanceIT();
12440        return;
12441      }
12442      // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
12443      if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
12444        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12445                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12446        AdvanceIT();
12447        return;
12448      }
12449    }
12450  }
12451  Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
12452}
12453
12454void Assembler::svc(Condition cond, uint32_t imm) {
12455  VIXL_ASSERT(AllowAssembler());
12456  CheckIT(cond);
12457  if (IsUsingT32()) {
12458    // SVC{<c>}{<q>} {#}<imm> ; T1
12459    if ((imm <= 255)) {
12460      EmitT32_16(0xdf00 | imm);
12461      AdvanceIT();
12462      return;
12463    }
12464  } else {
12465    // SVC{<c>}{<q>} {#}<imm> ; A1
12466    if ((imm <= 16777215) && cond.IsNotNever()) {
12467      EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
12468      return;
12469    }
12470  }
12471  Delegate(kSvc, &Assembler::svc, cond, imm);
12472}
12473
12474void Assembler::sxtab(Condition cond,
12475                      Register rd,
12476                      Register rn,
12477                      const Operand& operand) {
12478  VIXL_ASSERT(AllowAssembler());
12479  CheckIT(cond);
12480  if (operand.IsImmediateShiftedRegister()) {
12481    Register rm = operand.GetBaseRegister();
12482    Shift shift = operand.GetShift();
12483    uint32_t amount = operand.GetShiftAmount();
12484    if (IsUsingT32()) {
12485      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12486      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12487          ((amount % 8) == 0) && !rn.Is(pc) &&
12488          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12489        uint32_t amount_ = amount / 8;
12490        EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12491                   rm.GetCode() | (amount_ << 4));
12492        AdvanceIT();
12493        return;
12494      }
12495    } else {
12496      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12497      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12498          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12499          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12500        uint32_t amount_ = amount / 8;
12501        EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
12502                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12503                (amount_ << 10));
12504        return;
12505      }
12506    }
12507  }
12508  Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
12509}
12510
12511void Assembler::sxtab16(Condition cond,
12512                        Register rd,
12513                        Register rn,
12514                        const Operand& operand) {
12515  VIXL_ASSERT(AllowAssembler());
12516  CheckIT(cond);
12517  if (operand.IsImmediateShiftedRegister()) {
12518    Register rm = operand.GetBaseRegister();
12519    Shift shift = operand.GetShift();
12520    uint32_t amount = operand.GetShiftAmount();
12521    if (IsUsingT32()) {
12522      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12523      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12524          ((amount % 8) == 0) && !rn.Is(pc) &&
12525          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12526        uint32_t amount_ = amount / 8;
12527        EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12528                   rm.GetCode() | (amount_ << 4));
12529        AdvanceIT();
12530        return;
12531      }
12532    } else {
12533      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12534      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12535          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12536          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12537        uint32_t amount_ = amount / 8;
12538        EmitA32(0x06800070U | (cond.GetCondition() << 28) |
12539                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12540                (amount_ << 10));
12541        return;
12542      }
12543    }
12544  }
12545  Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
12546}
12547
12548void Assembler::sxtah(Condition cond,
12549                      Register rd,
12550                      Register rn,
12551                      const Operand& operand) {
12552  VIXL_ASSERT(AllowAssembler());
12553  CheckIT(cond);
12554  if (operand.IsImmediateShiftedRegister()) {
12555    Register rm = operand.GetBaseRegister();
12556    Shift shift = operand.GetShift();
12557    uint32_t amount = operand.GetShiftAmount();
12558    if (IsUsingT32()) {
12559      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12560      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12561          ((amount % 8) == 0) && !rn.Is(pc) &&
12562          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12563        uint32_t amount_ = amount / 8;
12564        EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12565                   rm.GetCode() | (amount_ << 4));
12566        AdvanceIT();
12567        return;
12568      }
12569    } else {
12570      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12571      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12572          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12573          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12574        uint32_t amount_ = amount / 8;
12575        EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
12576                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12577                (amount_ << 10));
12578        return;
12579      }
12580    }
12581  }
12582  Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
12583}
12584
12585void Assembler::sxtb(Condition cond,
12586                     EncodingSize size,
12587                     Register rd,
12588                     const Operand& operand) {
12589  VIXL_ASSERT(AllowAssembler());
12590  CheckIT(cond);
12591  if (operand.IsImmediateShiftedRegister()) {
12592    Register rm = operand.GetBaseRegister();
12593    if (operand.IsPlainRegister()) {
12594      if (IsUsingT32()) {
12595        // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12596        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12597          EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
12598          AdvanceIT();
12599          return;
12600        }
12601      }
12602    }
12603    Shift shift = operand.GetShift();
12604    uint32_t amount = operand.GetShiftAmount();
12605    if (IsUsingT32()) {
12606      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12607      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12608          (amount <= 24) && ((amount % 8) == 0) &&
12609          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12610        uint32_t amount_ = amount / 8;
12611        EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12612                   (amount_ << 4));
12613        AdvanceIT();
12614        return;
12615      }
12616    } else {
12617      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12618      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12619          ((amount % 8) == 0) && cond.IsNotNever() &&
12620          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12621        uint32_t amount_ = amount / 8;
12622        EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
12623                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12624        return;
12625      }
12626    }
12627  }
12628  Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
12629}
12630
12631void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
12632  VIXL_ASSERT(AllowAssembler());
12633  CheckIT(cond);
12634  if (operand.IsImmediateShiftedRegister()) {
12635    Register rm = operand.GetBaseRegister();
12636    Shift shift = operand.GetShift();
12637    uint32_t amount = operand.GetShiftAmount();
12638    if (IsUsingT32()) {
12639      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12640      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12641          ((amount % 8) == 0) &&
12642          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12643        uint32_t amount_ = amount / 8;
12644        EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12645                   (amount_ << 4));
12646        AdvanceIT();
12647        return;
12648      }
12649    } else {
12650      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12651      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12652          ((amount % 8) == 0) && cond.IsNotNever() &&
12653          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12654        uint32_t amount_ = amount / 8;
12655        EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
12656                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12657        return;
12658      }
12659    }
12660  }
12661  Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
12662}
12663
12664void Assembler::sxth(Condition cond,
12665                     EncodingSize size,
12666                     Register rd,
12667                     const Operand& operand) {
12668  VIXL_ASSERT(AllowAssembler());
12669  CheckIT(cond);
12670  if (operand.IsImmediateShiftedRegister()) {
12671    Register rm = operand.GetBaseRegister();
12672    if (operand.IsPlainRegister()) {
12673      if (IsUsingT32()) {
12674        // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12675        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12676          EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
12677          AdvanceIT();
12678          return;
12679        }
12680      }
12681    }
12682    Shift shift = operand.GetShift();
12683    uint32_t amount = operand.GetShiftAmount();
12684    if (IsUsingT32()) {
12685      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12686      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12687          (amount <= 24) && ((amount % 8) == 0) &&
12688          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12689        uint32_t amount_ = amount / 8;
12690        EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12691                   (amount_ << 4));
12692        AdvanceIT();
12693        return;
12694      }
12695    } else {
12696      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12697      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12698          ((amount % 8) == 0) && cond.IsNotNever() &&
12699          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12700        uint32_t amount_ = amount / 8;
12701        EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
12702                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12703        return;
12704      }
12705    }
12706  }
12707  Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
12708}
12709
12710void Assembler::tbb(Condition cond, Register rn, Register rm) {
12711  VIXL_ASSERT(AllowAssembler());
12712  CheckIT(cond);
12713  if (IsUsingT32()) {
12714    // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
12715    if (OutsideITBlockAndAlOrLast(cond) &&
12716        (!rm.IsPC() || AllowUnpredictable())) {
12717      EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
12718      AdvanceIT();
12719      return;
12720    }
12721  }
12722  Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
12723}
12724
12725void Assembler::tbh(Condition cond, Register rn, Register rm) {
12726  VIXL_ASSERT(AllowAssembler());
12727  CheckIT(cond);
12728  if (IsUsingT32()) {
12729    // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
12730    if (OutsideITBlockAndAlOrLast(cond) &&
12731        (!rm.IsPC() || AllowUnpredictable())) {
12732      EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
12733      AdvanceIT();
12734      return;
12735    }
12736  }
12737  Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
12738}
12739
12740void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
12741  VIXL_ASSERT(AllowAssembler());
12742  CheckIT(cond);
12743  if (operand.IsImmediate()) {
12744    uint32_t imm = operand.GetImmediate();
12745    if (IsUsingT32()) {
12746      ImmediateT32 immediate_t32(imm);
12747      // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
12748      if (immediate_t32.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
12749        EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
12750                   (immediate_t32.GetEncodingValue() & 0xff) |
12751                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12752                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12753        AdvanceIT();
12754        return;
12755      }
12756    } else {
12757      ImmediateA32 immediate_a32(imm);
12758      // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
12759      if (immediate_a32.IsValid() && cond.IsNotNever()) {
12760        EmitA32(0x03300000U | (cond.GetCondition() << 28) |
12761                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12762        return;
12763      }
12764    }
12765  }
12766  if (operand.IsImmediateShiftedRegister()) {
12767    Register rm = operand.GetBaseRegister();
12768    Shift shift = operand.GetShift();
12769    uint32_t amount = operand.GetShiftAmount();
12770    if (IsUsingT32()) {
12771      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
12772      if (shift.IsValidAmount(amount) &&
12773          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12774        uint32_t amount_ = amount % 32;
12775        EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
12776                   (operand.GetTypeEncodingValue() << 4) |
12777                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12778        AdvanceIT();
12779        return;
12780      }
12781    } else {
12782      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12783      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12784        uint32_t amount_ = amount % 32;
12785        EmitA32(0x01300000U | (cond.GetCondition() << 28) |
12786                (rn.GetCode() << 16) | rm.GetCode() |
12787                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12788        return;
12789      }
12790    }
12791  }
12792  if (operand.IsRegisterShiftedRegister()) {
12793    Register rm = operand.GetBaseRegister();
12794    Shift shift = operand.GetShift();
12795    Register rs = operand.GetShiftRegister();
12796    if (IsUsingA32()) {
12797      // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
12798      if (cond.IsNotNever() &&
12799          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
12800        EmitA32(0x01300010U | (cond.GetCondition() << 28) |
12801                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
12802                (rs.GetCode() << 8));
12803        return;
12804      }
12805    }
12806  }
12807  Delegate(kTeq, &Assembler::teq, cond, rn, operand);
12808}
12809
12810void Assembler::tst(Condition cond,
12811                    EncodingSize size,
12812                    Register rn,
12813                    const Operand& operand) {
12814  VIXL_ASSERT(AllowAssembler());
12815  CheckIT(cond);
12816  if (operand.IsImmediate()) {
12817    uint32_t imm = operand.GetImmediate();
12818    if (IsUsingT32()) {
12819      ImmediateT32 immediate_t32(imm);
12820      // TST{<c>}{<q>} <Rn>, #<const> ; T1
12821      if (!size.IsNarrow() && immediate_t32.IsValid() &&
12822          (!rn.IsPC() || AllowUnpredictable())) {
12823        EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
12824                   (immediate_t32.GetEncodingValue() & 0xff) |
12825                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12826                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12827        AdvanceIT();
12828        return;
12829      }
12830    } else {
12831      ImmediateA32 immediate_a32(imm);
12832      // TST{<c>}{<q>} <Rn>, #<const> ; A1
12833      if (immediate_a32.IsValid() && cond.IsNotNever()) {
12834        EmitA32(0x03100000U | (cond.GetCondition() << 28) |
12835                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12836        return;
12837      }
12838    }
12839  }
12840  if (operand.IsImmediateShiftedRegister()) {
12841    Register rm = operand.GetBaseRegister();
12842    if (operand.IsPlainRegister()) {
12843      if (IsUsingT32()) {
12844        // TST{<c>}{<q>} <Rn>, <Rm> ; T1
12845        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
12846          EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
12847          AdvanceIT();
12848          return;
12849        }
12850      }
12851    }
12852    Shift shift = operand.GetShift();
12853    uint32_t amount = operand.GetShiftAmount();
12854    if (IsUsingT32()) {
12855      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
12856      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
12857          ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12858        uint32_t amount_ = amount % 32;
12859        EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
12860                   (operand.GetTypeEncodingValue() << 4) |
12861                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12862        AdvanceIT();
12863        return;
12864      }
12865    } else {
12866      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12867      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12868        uint32_t amount_ = amount % 32;
12869        EmitA32(0x01100000U | (cond.GetCondition() << 28) |
12870                (rn.GetCode() << 16) | rm.GetCode() |
12871                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12872        return;
12873      }
12874    }
12875  }
12876  if (operand.IsRegisterShiftedRegister()) {
12877    Register rm = operand.GetBaseRegister();
12878    Shift shift = operand.GetShift();
12879    Register rs = operand.GetShiftRegister();
12880    if (IsUsingA32()) {
12881      // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
12882      if (cond.IsNotNever() &&
12883          ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
12884        EmitA32(0x01100010U | (cond.GetCondition() << 28) |
12885                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
12886                (rs.GetCode() << 8));
12887        return;
12888      }
12889    }
12890  }
12891  Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
12892}
12893
12894void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
12895  VIXL_ASSERT(AllowAssembler());
12896  CheckIT(cond);
12897  if (IsUsingT32()) {
12898    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12899    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12900      EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12901                 rm.GetCode());
12902      AdvanceIT();
12903      return;
12904    }
12905  } else {
12906    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12907    if (cond.IsNotNever() &&
12908        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12909      EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12910              (rn.GetCode() << 16) | rm.GetCode());
12911      return;
12912    }
12913  }
12914  Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
12915}
12916
12917void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
12918  VIXL_ASSERT(AllowAssembler());
12919  CheckIT(cond);
12920  if (IsUsingT32()) {
12921    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12922    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12923      EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12924                 rm.GetCode());
12925      AdvanceIT();
12926      return;
12927    }
12928  } else {
12929    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12930    if (cond.IsNotNever() &&
12931        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12932      EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12933              (rn.GetCode() << 16) | rm.GetCode());
12934      return;
12935    }
12936  }
12937  Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
12938}
12939
12940void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
12941  VIXL_ASSERT(AllowAssembler());
12942  CheckIT(cond);
12943  if (IsUsingT32()) {
12944    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12945    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12946      EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12947                 rm.GetCode());
12948      AdvanceIT();
12949      return;
12950    }
12951  } else {
12952    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12953    if (cond.IsNotNever() &&
12954        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12955      EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12956              (rn.GetCode() << 16) | rm.GetCode());
12957      return;
12958    }
12959  }
12960  Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
12961}
12962
12963void Assembler::ubfx(
12964    Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
12965  VIXL_ASSERT(AllowAssembler());
12966  CheckIT(cond);
12967  if (IsUsingT32()) {
12968    // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
12969    if ((lsb <= 31) &&
12970        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
12971         AllowUnpredictable())) {
12972      uint32_t widthm1 = width - 1;
12973      EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12974                 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
12975      AdvanceIT();
12976      return;
12977    }
12978  } else {
12979    // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
12980    if ((lsb <= 31) && cond.IsNotNever() &&
12981        (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
12982         AllowUnpredictable())) {
12983      uint32_t widthm1 = width - 1;
12984      EmitA32(0x07e00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12985              rn.GetCode() | (lsb << 7) | (widthm1 << 16));
12986      return;
12987    }
12988  }
12989  Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, width);
12990}
12991
12992void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
12993  VIXL_ASSERT(AllowAssembler());
12994  CheckIT(cond);
12995  if (IsUsingT32()) {
12996    // UDF{<c>}{<q>} {#}<imm> ; T1
12997    if (!size.IsWide() && (imm <= 255)) {
12998      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12999        EmitT32_16(0xde00 | imm);
13000        AdvanceIT();
13001        return;
13002      }
13003    }
13004    // UDF{<c>}{<q>} {#}<imm> ; T2
13005    if (!size.IsNarrow() && (imm <= 65535)) {
13006      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13007        EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
13008        AdvanceIT();
13009        return;
13010      }
13011    }
13012  } else {
13013    // UDF{<c>}{<q>} {#}<imm> ; A1
13014    if ((imm <= 65535)) {
13015      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13016        EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
13017        return;
13018      }
13019    }
13020  }
13021  Delegate(kUdf, &Assembler::udf, cond, size, imm);
13022}
13023
13024void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
13025  VIXL_ASSERT(AllowAssembler());
13026  CheckIT(cond);
13027  if (IsUsingT32()) {
13028    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13029    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13030      EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13031                 rm.GetCode());
13032      AdvanceIT();
13033      return;
13034    }
13035  } else {
13036    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13037    if (cond.IsNotNever() &&
13038        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13039      EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13040              rn.GetCode() | (rm.GetCode() << 8));
13041      return;
13042    }
13043  }
13044  Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
13045}
13046
13047void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
13048  VIXL_ASSERT(AllowAssembler());
13049  CheckIT(cond);
13050  if (IsUsingT32()) {
13051    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13052    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13053      EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13054                 rm.GetCode());
13055      AdvanceIT();
13056      return;
13057    }
13058  } else {
13059    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13060    if (cond.IsNotNever() &&
13061        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13062      EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13063              (rn.GetCode() << 16) | rm.GetCode());
13064      return;
13065    }
13066  }
13067  Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
13068}
13069
13070void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
13071  VIXL_ASSERT(AllowAssembler());
13072  CheckIT(cond);
13073  if (IsUsingT32()) {
13074    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13075    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13076      EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13077                 rm.GetCode());
13078      AdvanceIT();
13079      return;
13080    }
13081  } else {
13082    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13083    if (cond.IsNotNever() &&
13084        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13085      EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13086              (rn.GetCode() << 16) | rm.GetCode());
13087      return;
13088    }
13089  }
13090  Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
13091}
13092
13093void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
13094  VIXL_ASSERT(AllowAssembler());
13095  CheckIT(cond);
13096  if (IsUsingT32()) {
13097    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13098    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13099      EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13100                 rm.GetCode());
13101      AdvanceIT();
13102      return;
13103    }
13104  } else {
13105    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13106    if (cond.IsNotNever() &&
13107        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13108      EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13109              (rn.GetCode() << 16) | rm.GetCode());
13110      return;
13111    }
13112  }
13113  Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
13114}
13115
13116void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
13117  VIXL_ASSERT(AllowAssembler());
13118  CheckIT(cond);
13119  if (IsUsingT32()) {
13120    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13121    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13122      EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13123                 rm.GetCode());
13124      AdvanceIT();
13125      return;
13126    }
13127  } else {
13128    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13129    if (cond.IsNotNever() &&
13130        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13131      EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13132              (rn.GetCode() << 16) | rm.GetCode());
13133      return;
13134    }
13135  }
13136  Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
13137}
13138
13139void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
13140  VIXL_ASSERT(AllowAssembler());
13141  CheckIT(cond);
13142  if (IsUsingT32()) {
13143    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13144    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13145      EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13146                 rm.GetCode());
13147      AdvanceIT();
13148      return;
13149    }
13150  } else {
13151    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13152    if (cond.IsNotNever() &&
13153        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13154      EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13155              (rn.GetCode() << 16) | rm.GetCode());
13156      return;
13157    }
13158  }
13159  Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
13160}
13161
13162void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
13163  VIXL_ASSERT(AllowAssembler());
13164  CheckIT(cond);
13165  if (IsUsingT32()) {
13166    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13167    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13168      EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13169                 rm.GetCode());
13170      AdvanceIT();
13171      return;
13172    }
13173  } else {
13174    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13175    if (cond.IsNotNever() &&
13176        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13177      EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13178              (rn.GetCode() << 16) | rm.GetCode());
13179      return;
13180    }
13181  }
13182  Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
13183}
13184
13185void Assembler::umaal(
13186    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13187  VIXL_ASSERT(AllowAssembler());
13188  CheckIT(cond);
13189  if (IsUsingT32()) {
13190    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
13191    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13192         AllowUnpredictable())) {
13193      EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13194                 (rn.GetCode() << 16) | rm.GetCode());
13195      AdvanceIT();
13196      return;
13197    }
13198  } else {
13199    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13200    if (cond.IsNotNever() &&
13201        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13202         AllowUnpredictable())) {
13203      EmitA32(0x00400090U | (cond.GetCondition() << 28) |
13204              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13205              (rm.GetCode() << 8));
13206      return;
13207    }
13208  }
13209  Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
13210}
13211
13212void Assembler::umlal(
13213    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13214  VIXL_ASSERT(AllowAssembler());
13215  CheckIT(cond);
13216  if (IsUsingT32()) {
13217    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
13218    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13219         AllowUnpredictable())) {
13220      EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13221                 (rn.GetCode() << 16) | rm.GetCode());
13222      AdvanceIT();
13223      return;
13224    }
13225  } else {
13226    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13227    if (cond.IsNotNever() &&
13228        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13229         AllowUnpredictable())) {
13230      EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
13231              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13232              (rm.GetCode() << 8));
13233      return;
13234    }
13235  }
13236  Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
13237}
13238
13239void Assembler::umlals(
13240    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13241  VIXL_ASSERT(AllowAssembler());
13242  CheckIT(cond);
13243  if (IsUsingA32()) {
13244    // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13245    if (cond.IsNotNever() &&
13246        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13247         AllowUnpredictable())) {
13248      EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
13249              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13250              (rm.GetCode() << 8));
13251      return;
13252    }
13253  }
13254  Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
13255}
13256
13257void Assembler::umull(
13258    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13259  VIXL_ASSERT(AllowAssembler());
13260  CheckIT(cond);
13261  if (IsUsingT32()) {
13262    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
13263    if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13264         AllowUnpredictable())) {
13265      EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13266                 (rn.GetCode() << 16) | rm.GetCode());
13267      AdvanceIT();
13268      return;
13269    }
13270  } else {
13271    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13272    if (cond.IsNotNever() &&
13273        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13274         AllowUnpredictable())) {
13275      EmitA32(0x00800090U | (cond.GetCondition() << 28) |
13276              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13277              (rm.GetCode() << 8));
13278      return;
13279    }
13280  }
13281  Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
13282}
13283
13284void Assembler::umulls(
13285    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
13286  VIXL_ASSERT(AllowAssembler());
13287  CheckIT(cond);
13288  if (IsUsingA32()) {
13289    // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
13290    if (cond.IsNotNever() &&
13291        ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13292         AllowUnpredictable())) {
13293      EmitA32(0x00900090U | (cond.GetCondition() << 28) |
13294              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13295              (rm.GetCode() << 8));
13296      return;
13297    }
13298  }
13299  Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
13300}
13301
13302void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
13303  VIXL_ASSERT(AllowAssembler());
13304  CheckIT(cond);
13305  if (IsUsingT32()) {
13306    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13307    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13308      EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13309                 rm.GetCode());
13310      AdvanceIT();
13311      return;
13312    }
13313  } else {
13314    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13315    if (cond.IsNotNever() &&
13316        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13317      EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13318              (rn.GetCode() << 16) | rm.GetCode());
13319      return;
13320    }
13321  }
13322  Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
13323}
13324
13325void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
13326  VIXL_ASSERT(AllowAssembler());
13327  CheckIT(cond);
13328  if (IsUsingT32()) {
13329    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13330    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13331      EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13332                 rm.GetCode());
13333      AdvanceIT();
13334      return;
13335    }
13336  } else {
13337    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13338    if (cond.IsNotNever() &&
13339        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13340      EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13341              (rn.GetCode() << 16) | rm.GetCode());
13342      return;
13343    }
13344  }
13345  Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
13346}
13347
13348void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
13349  VIXL_ASSERT(AllowAssembler());
13350  CheckIT(cond);
13351  if (IsUsingT32()) {
13352    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13353    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13354      EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13355                 rm.GetCode());
13356      AdvanceIT();
13357      return;
13358    }
13359  } else {
13360    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13361    if (cond.IsNotNever() &&
13362        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13363      EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13364              (rn.GetCode() << 16) | rm.GetCode());
13365      return;
13366    }
13367  }
13368  Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
13369}
13370
13371void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
13372  VIXL_ASSERT(AllowAssembler());
13373  CheckIT(cond);
13374  if (IsUsingT32()) {
13375    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13376    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13377      EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13378                 rm.GetCode());
13379      AdvanceIT();
13380      return;
13381    }
13382  } else {
13383    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13384    if (cond.IsNotNever() &&
13385        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13386      EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13387              (rn.GetCode() << 16) | rm.GetCode());
13388      return;
13389    }
13390  }
13391  Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
13392}
13393
13394void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
13395  VIXL_ASSERT(AllowAssembler());
13396  CheckIT(cond);
13397  if (IsUsingT32()) {
13398    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13399    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13400      EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13401                 rm.GetCode());
13402      AdvanceIT();
13403      return;
13404    }
13405  } else {
13406    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13407    if (cond.IsNotNever() &&
13408        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13409      EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13410              (rn.GetCode() << 16) | rm.GetCode());
13411      return;
13412    }
13413  }
13414  Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
13415}
13416
13417void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
13418  VIXL_ASSERT(AllowAssembler());
13419  CheckIT(cond);
13420  if (IsUsingT32()) {
13421    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13422    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13423      EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13424                 rm.GetCode());
13425      AdvanceIT();
13426      return;
13427    }
13428  } else {
13429    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13430    if (cond.IsNotNever() &&
13431        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13432      EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13433              (rn.GetCode() << 16) | rm.GetCode());
13434      return;
13435    }
13436  }
13437  Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
13438}
13439
13440void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
13441  VIXL_ASSERT(AllowAssembler());
13442  CheckIT(cond);
13443  if (IsUsingT32()) {
13444    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13445    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13446      EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13447                 rm.GetCode());
13448      AdvanceIT();
13449      return;
13450    }
13451  } else {
13452    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13453    if (cond.IsNotNever() &&
13454        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13455      EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13456              rn.GetCode() | (rm.GetCode() << 8));
13457      return;
13458    }
13459  }
13460  Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
13461}
13462
13463void Assembler::usada8(
13464    Condition cond, Register rd, Register rn, Register rm, Register ra) {
13465  VIXL_ASSERT(AllowAssembler());
13466  CheckIT(cond);
13467  if (IsUsingT32()) {
13468    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
13469    if (!ra.Is(pc) &&
13470        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13471      EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13472                 rm.GetCode() | (ra.GetCode() << 12));
13473      AdvanceIT();
13474      return;
13475    }
13476  } else {
13477    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
13478    if (cond.IsNotNever() && !ra.Is(pc) &&
13479        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13480      EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13481              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
13482      return;
13483    }
13484  }
13485  Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
13486}
13487
13488void Assembler::usat(Condition cond,
13489                     Register rd,
13490                     uint32_t imm,
13491                     const Operand& operand) {
13492  VIXL_ASSERT(AllowAssembler());
13493  CheckIT(cond);
13494  if (operand.IsImmediateShiftedRegister()) {
13495    Register rn = operand.GetBaseRegister();
13496    Shift shift = operand.GetShift();
13497    uint32_t amount = operand.GetShiftAmount();
13498    if (IsUsingT32()) {
13499      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
13500      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31) &&
13501          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13502        EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13503                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13504                   ((amount & 0x1c) << 10));
13505        AdvanceIT();
13506        return;
13507      }
13508      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
13509      if ((imm <= 31) && shift.IsLSL() && (amount <= 31) &&
13510          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13511        EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
13512                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13513                   ((amount & 0x1c) << 10));
13514        AdvanceIT();
13515        return;
13516      }
13517    } else {
13518      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
13519      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
13520          cond.IsNotNever() &&
13521          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13522        uint32_t amount_ = amount % 32;
13523        EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
13524                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13525                (amount_ << 7));
13526        return;
13527      }
13528      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
13529      if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever() &&
13530          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13531        EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
13532                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13533                (amount << 7));
13534        return;
13535      }
13536    }
13537  }
13538  Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
13539}
13540
13541void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
13542  VIXL_ASSERT(AllowAssembler());
13543  CheckIT(cond);
13544  if (IsUsingT32()) {
13545    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
13546    if ((imm <= 15) && ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13547      EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13548                 (rn.GetCode() << 16));
13549      AdvanceIT();
13550      return;
13551    }
13552  } else {
13553    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
13554    if ((imm <= 15) && cond.IsNotNever() &&
13555        ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
13556      EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13557              (imm << 16) | rn.GetCode());
13558      return;
13559    }
13560  }
13561  Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
13562}
13563
13564void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
13565  VIXL_ASSERT(AllowAssembler());
13566  CheckIT(cond);
13567  if (IsUsingT32()) {
13568    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13569    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13570      EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13571                 rm.GetCode());
13572      AdvanceIT();
13573      return;
13574    }
13575  } else {
13576    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13577    if (cond.IsNotNever() &&
13578        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13579      EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13580              (rn.GetCode() << 16) | rm.GetCode());
13581      return;
13582    }
13583  }
13584  Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
13585}
13586
13587void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
13588  VIXL_ASSERT(AllowAssembler());
13589  CheckIT(cond);
13590  if (IsUsingT32()) {
13591    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13592    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13593      EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13594                 rm.GetCode());
13595      AdvanceIT();
13596      return;
13597    }
13598  } else {
13599    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13600    if (cond.IsNotNever() &&
13601        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13602      EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13603              (rn.GetCode() << 16) | rm.GetCode());
13604      return;
13605    }
13606  }
13607  Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
13608}
13609
13610void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
13611  VIXL_ASSERT(AllowAssembler());
13612  CheckIT(cond);
13613  if (IsUsingT32()) {
13614    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
13615    if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13616      EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13617                 rm.GetCode());
13618      AdvanceIT();
13619      return;
13620    }
13621  } else {
13622    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
13623    if (cond.IsNotNever() &&
13624        ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13625      EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13626              (rn.GetCode() << 16) | rm.GetCode());
13627      return;
13628    }
13629  }
13630  Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
13631}
13632
13633void Assembler::uxtab(Condition cond,
13634                      Register rd,
13635                      Register rn,
13636                      const Operand& operand) {
13637  VIXL_ASSERT(AllowAssembler());
13638  CheckIT(cond);
13639  if (operand.IsImmediateShiftedRegister()) {
13640    Register rm = operand.GetBaseRegister();
13641    Shift shift = operand.GetShift();
13642    uint32_t amount = operand.GetShiftAmount();
13643    if (IsUsingT32()) {
13644      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13645      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13646          ((amount % 8) == 0) && !rn.Is(pc) &&
13647          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13648        uint32_t amount_ = amount / 8;
13649        EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13650                   rm.GetCode() | (amount_ << 4));
13651        AdvanceIT();
13652        return;
13653      }
13654    } else {
13655      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13656      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13657          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13658          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13659        uint32_t amount_ = amount / 8;
13660        EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
13661                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13662                (amount_ << 10));
13663        return;
13664      }
13665    }
13666  }
13667  Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
13668}
13669
13670void Assembler::uxtab16(Condition cond,
13671                        Register rd,
13672                        Register rn,
13673                        const Operand& operand) {
13674  VIXL_ASSERT(AllowAssembler());
13675  CheckIT(cond);
13676  if (operand.IsImmediateShiftedRegister()) {
13677    Register rm = operand.GetBaseRegister();
13678    Shift shift = operand.GetShift();
13679    uint32_t amount = operand.GetShiftAmount();
13680    if (IsUsingT32()) {
13681      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13682      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13683          ((amount % 8) == 0) && !rn.Is(pc) &&
13684          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13685        uint32_t amount_ = amount / 8;
13686        EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13687                   rm.GetCode() | (amount_ << 4));
13688        AdvanceIT();
13689        return;
13690      }
13691    } else {
13692      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13693      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13694          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13695          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13696        uint32_t amount_ = amount / 8;
13697        EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
13698                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13699                (amount_ << 10));
13700        return;
13701      }
13702    }
13703  }
13704  Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
13705}
13706
13707void Assembler::uxtah(Condition cond,
13708                      Register rd,
13709                      Register rn,
13710                      const Operand& operand) {
13711  VIXL_ASSERT(AllowAssembler());
13712  CheckIT(cond);
13713  if (operand.IsImmediateShiftedRegister()) {
13714    Register rm = operand.GetBaseRegister();
13715    Shift shift = operand.GetShift();
13716    uint32_t amount = operand.GetShiftAmount();
13717    if (IsUsingT32()) {
13718      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13719      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13720          ((amount % 8) == 0) && !rn.Is(pc) &&
13721          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13722        uint32_t amount_ = amount / 8;
13723        EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13724                   rm.GetCode() | (amount_ << 4));
13725        AdvanceIT();
13726        return;
13727      }
13728    } else {
13729      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13730      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13731          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13732          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13733        uint32_t amount_ = amount / 8;
13734        EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
13735                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13736                (amount_ << 10));
13737        return;
13738      }
13739    }
13740  }
13741  Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
13742}
13743
13744void Assembler::uxtb(Condition cond,
13745                     EncodingSize size,
13746                     Register rd,
13747                     const Operand& operand) {
13748  VIXL_ASSERT(AllowAssembler());
13749  CheckIT(cond);
13750  if (operand.IsImmediateShiftedRegister()) {
13751    Register rm = operand.GetBaseRegister();
13752    if (operand.IsPlainRegister()) {
13753      if (IsUsingT32()) {
13754        // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
13755        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13756          EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
13757          AdvanceIT();
13758          return;
13759        }
13760      }
13761    }
13762    Shift shift = operand.GetShift();
13763    uint32_t amount = operand.GetShiftAmount();
13764    if (IsUsingT32()) {
13765      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13766      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
13767          (amount <= 24) && ((amount % 8) == 0) &&
13768          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13769        uint32_t amount_ = amount / 8;
13770        EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13771                   (amount_ << 4));
13772        AdvanceIT();
13773        return;
13774      }
13775    } else {
13776      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13777      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13778          ((amount % 8) == 0) && cond.IsNotNever() &&
13779          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13780        uint32_t amount_ = amount / 8;
13781        EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
13782                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13783        return;
13784      }
13785    }
13786  }
13787  Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
13788}
13789
13790void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
13791  VIXL_ASSERT(AllowAssembler());
13792  CheckIT(cond);
13793  if (operand.IsImmediateShiftedRegister()) {
13794    Register rm = operand.GetBaseRegister();
13795    Shift shift = operand.GetShift();
13796    uint32_t amount = operand.GetShiftAmount();
13797    if (IsUsingT32()) {
13798      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
13799      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13800          ((amount % 8) == 0) &&
13801          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13802        uint32_t amount_ = amount / 8;
13803        EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13804                   (amount_ << 4));
13805        AdvanceIT();
13806        return;
13807      }
13808    } else {
13809      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13810      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13811          ((amount % 8) == 0) && cond.IsNotNever() &&
13812          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13813        uint32_t amount_ = amount / 8;
13814        EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
13815                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13816        return;
13817      }
13818    }
13819  }
13820  Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
13821}
13822
13823void Assembler::uxth(Condition cond,
13824                     EncodingSize size,
13825                     Register rd,
13826                     const Operand& operand) {
13827  VIXL_ASSERT(AllowAssembler());
13828  CheckIT(cond);
13829  if (operand.IsImmediateShiftedRegister()) {
13830    Register rm = operand.GetBaseRegister();
13831    if (operand.IsPlainRegister()) {
13832      if (IsUsingT32()) {
13833        // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
13834        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13835          EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
13836          AdvanceIT();
13837          return;
13838        }
13839      }
13840    }
13841    Shift shift = operand.GetShift();
13842    uint32_t amount = operand.GetShiftAmount();
13843    if (IsUsingT32()) {
13844      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13845      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
13846          (amount <= 24) && ((amount % 8) == 0) &&
13847          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13848        uint32_t amount_ = amount / 8;
13849        EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13850                   (amount_ << 4));
13851        AdvanceIT();
13852        return;
13853      }
13854    } else {
13855      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13856      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
13857          ((amount % 8) == 0) && cond.IsNotNever() &&
13858          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13859        uint32_t amount_ = amount / 8;
13860        EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
13861                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13862        return;
13863      }
13864    }
13865  }
13866  Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
13867}
13868
13869void Assembler::vaba(
13870    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13871  VIXL_ASSERT(AllowAssembler());
13872  CheckIT(cond);
13873  Dt_U_size_1 encoded_dt(dt);
13874  if (IsUsingT32()) {
13875    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
13876    if (encoded_dt.IsValid()) {
13877      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13878        EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13879                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13880                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13881        AdvanceIT();
13882        return;
13883      }
13884    }
13885  } else {
13886    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
13887    if (encoded_dt.IsValid()) {
13888      if (cond.Is(al)) {
13889        EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13890                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13891                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13892        return;
13893      }
13894    }
13895  }
13896  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13897}
13898
13899void Assembler::vaba(
13900    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13901  VIXL_ASSERT(AllowAssembler());
13902  CheckIT(cond);
13903  Dt_U_size_1 encoded_dt(dt);
13904  if (IsUsingT32()) {
13905    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
13906    if (encoded_dt.IsValid()) {
13907      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13908        EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13909                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13910                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13911        AdvanceIT();
13912        return;
13913      }
13914    }
13915  } else {
13916    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
13917    if (encoded_dt.IsValid()) {
13918      if (cond.Is(al)) {
13919        EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13920                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13921                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13922        return;
13923      }
13924    }
13925  }
13926  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13927}
13928
13929void Assembler::vabal(
13930    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
13931  VIXL_ASSERT(AllowAssembler());
13932  CheckIT(cond);
13933  Dt_U_size_1 encoded_dt(dt);
13934  if (IsUsingT32()) {
13935    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13936    if (encoded_dt.IsValid()) {
13937      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13938        EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13939                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13940                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13941        AdvanceIT();
13942        return;
13943      }
13944    }
13945  } else {
13946    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13947    if (encoded_dt.IsValid()) {
13948      if (cond.Is(al)) {
13949        EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13950                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13951                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13952        return;
13953      }
13954    }
13955  }
13956  Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
13957}
13958
13959void Assembler::vabd(
13960    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13961  VIXL_ASSERT(AllowAssembler());
13962  CheckIT(cond);
13963  Dt_U_size_1 encoded_dt(dt);
13964  if (IsUsingT32()) {
13965    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13966    if (dt.Is(F32)) {
13967      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13968        EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13969                   rm.Encode(5, 0));
13970        AdvanceIT();
13971        return;
13972      }
13973    }
13974    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13975    if (encoded_dt.IsValid()) {
13976      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13977        EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13978                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13979                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13980        AdvanceIT();
13981        return;
13982      }
13983    }
13984  } else {
13985    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13986    if (dt.Is(F32)) {
13987      if (cond.Is(al)) {
13988        EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13989                rm.Encode(5, 0));
13990        return;
13991      }
13992    }
13993    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13994    if (encoded_dt.IsValid()) {
13995      if (cond.Is(al)) {
13996        EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13997                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13998                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13999        return;
14000      }
14001    }
14002  }
14003  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14004}
14005
14006void Assembler::vabd(
14007    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14008  VIXL_ASSERT(AllowAssembler());
14009  CheckIT(cond);
14010  Dt_U_size_1 encoded_dt(dt);
14011  if (IsUsingT32()) {
14012    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14013    if (dt.Is(F32)) {
14014      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14015        EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14016                   rm.Encode(5, 0));
14017        AdvanceIT();
14018        return;
14019      }
14020    }
14021    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14022    if (encoded_dt.IsValid()) {
14023      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14024        EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14025                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14026                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14027        AdvanceIT();
14028        return;
14029      }
14030    }
14031  } else {
14032    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14033    if (dt.Is(F32)) {
14034      if (cond.Is(al)) {
14035        EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14036                rm.Encode(5, 0));
14037        return;
14038      }
14039    }
14040    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14041    if (encoded_dt.IsValid()) {
14042      if (cond.Is(al)) {
14043        EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14044                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14045                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14046        return;
14047      }
14048    }
14049  }
14050  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14051}
14052
14053void Assembler::vabdl(
14054    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
14055  VIXL_ASSERT(AllowAssembler());
14056  CheckIT(cond);
14057  Dt_U_size_1 encoded_dt(dt);
14058  if (IsUsingT32()) {
14059    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14060    if (encoded_dt.IsValid()) {
14061      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14062        EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14063                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14064                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14065        AdvanceIT();
14066        return;
14067      }
14068    }
14069  } else {
14070    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14071    if (encoded_dt.IsValid()) {
14072      if (cond.Is(al)) {
14073        EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14074                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14075                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14076        return;
14077      }
14078    }
14079  }
14080  Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
14081}
14082
14083void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14084  VIXL_ASSERT(AllowAssembler());
14085  CheckIT(cond);
14086  Dt_F_size_1 encoded_dt(dt);
14087  if (IsUsingT32()) {
14088    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14089    if (encoded_dt.IsValid()) {
14090      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14091        EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14092                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14093                   rd.Encode(22, 12) | rm.Encode(5, 0));
14094        AdvanceIT();
14095        return;
14096      }
14097    }
14098    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
14099    if (dt.Is(F64)) {
14100      EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14101      AdvanceIT();
14102      return;
14103    }
14104  } else {
14105    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14106    if (encoded_dt.IsValid()) {
14107      if (cond.Is(al)) {
14108        EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14109                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14110                rd.Encode(22, 12) | rm.Encode(5, 0));
14111        return;
14112      }
14113    }
14114    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
14115    if (dt.Is(F64) && cond.IsNotNever()) {
14116      EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14117              rm.Encode(5, 0));
14118      return;
14119    }
14120  }
14121  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14122}
14123
14124void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
14125  VIXL_ASSERT(AllowAssembler());
14126  CheckIT(cond);
14127  Dt_F_size_1 encoded_dt(dt);
14128  if (IsUsingT32()) {
14129    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14130    if (encoded_dt.IsValid()) {
14131      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14132        EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14133                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14134                   rd.Encode(22, 12) | rm.Encode(5, 0));
14135        AdvanceIT();
14136        return;
14137      }
14138    }
14139  } else {
14140    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14141    if (encoded_dt.IsValid()) {
14142      if (cond.Is(al)) {
14143        EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14144                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14145                rd.Encode(22, 12) | rm.Encode(5, 0));
14146        return;
14147      }
14148    }
14149  }
14150  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14151}
14152
14153void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
14154  VIXL_ASSERT(AllowAssembler());
14155  CheckIT(cond);
14156  if (IsUsingT32()) {
14157    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
14158    if (dt.Is(F32)) {
14159      EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14160      AdvanceIT();
14161      return;
14162    }
14163  } else {
14164    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
14165    if (dt.Is(F32) && cond.IsNotNever()) {
14166      EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14167              rm.Encode(5, 0));
14168      return;
14169    }
14170  }
14171  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14172}
14173
14174void Assembler::vacge(
14175    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14176  VIXL_ASSERT(AllowAssembler());
14177  CheckIT(cond);
14178  if (IsUsingT32()) {
14179    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14180    if (dt.Is(F32)) {
14181      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14182        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14183                   rm.Encode(5, 0));
14184        AdvanceIT();
14185        return;
14186      }
14187    }
14188  } else {
14189    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14190    if (dt.Is(F32)) {
14191      if (cond.Is(al)) {
14192        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14193                rm.Encode(5, 0));
14194        return;
14195      }
14196    }
14197  }
14198  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14199}
14200
14201void Assembler::vacge(
14202    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14203  VIXL_ASSERT(AllowAssembler());
14204  CheckIT(cond);
14205  if (IsUsingT32()) {
14206    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14207    if (dt.Is(F32)) {
14208      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14209        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14210                   rm.Encode(5, 0));
14211        AdvanceIT();
14212        return;
14213      }
14214    }
14215  } else {
14216    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14217    if (dt.Is(F32)) {
14218      if (cond.Is(al)) {
14219        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14220                rm.Encode(5, 0));
14221        return;
14222      }
14223    }
14224  }
14225  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14226}
14227
14228void Assembler::vacgt(
14229    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14230  VIXL_ASSERT(AllowAssembler());
14231  CheckIT(cond);
14232  if (IsUsingT32()) {
14233    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14234    if (dt.Is(F32)) {
14235      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14236        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14237                   rm.Encode(5, 0));
14238        AdvanceIT();
14239        return;
14240      }
14241    }
14242  } else {
14243    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14244    if (dt.Is(F32)) {
14245      if (cond.Is(al)) {
14246        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14247                rm.Encode(5, 0));
14248        return;
14249      }
14250    }
14251  }
14252  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14253}
14254
14255void Assembler::vacgt(
14256    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14257  VIXL_ASSERT(AllowAssembler());
14258  CheckIT(cond);
14259  if (IsUsingT32()) {
14260    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14261    if (dt.Is(F32)) {
14262      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14263        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14264                   rm.Encode(5, 0));
14265        AdvanceIT();
14266        return;
14267      }
14268    }
14269  } else {
14270    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14271    if (dt.Is(F32)) {
14272      if (cond.Is(al)) {
14273        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14274                rm.Encode(5, 0));
14275        return;
14276      }
14277    }
14278  }
14279  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14280}
14281
14282void Assembler::vacle(
14283    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14284  VIXL_ASSERT(AllowAssembler());
14285  CheckIT(cond);
14286  if (IsUsingT32()) {
14287    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14288    if (dt.Is(F32)) {
14289      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14290        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14291                   rm.Encode(5, 0));
14292        AdvanceIT();
14293        return;
14294      }
14295    }
14296  } else {
14297    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14298    if (dt.Is(F32)) {
14299      if (cond.Is(al)) {
14300        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14301                rm.Encode(5, 0));
14302        return;
14303      }
14304    }
14305  }
14306  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14307}
14308
14309void Assembler::vacle(
14310    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14311  VIXL_ASSERT(AllowAssembler());
14312  CheckIT(cond);
14313  if (IsUsingT32()) {
14314    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14315    if (dt.Is(F32)) {
14316      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14317        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14318                   rm.Encode(5, 0));
14319        AdvanceIT();
14320        return;
14321      }
14322    }
14323  } else {
14324    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14325    if (dt.Is(F32)) {
14326      if (cond.Is(al)) {
14327        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14328                rm.Encode(5, 0));
14329        return;
14330      }
14331    }
14332  }
14333  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14334}
14335
14336void Assembler::vaclt(
14337    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14338  VIXL_ASSERT(AllowAssembler());
14339  CheckIT(cond);
14340  if (IsUsingT32()) {
14341    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14342    if (dt.Is(F32)) {
14343      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14344        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14345                   rm.Encode(5, 0));
14346        AdvanceIT();
14347        return;
14348      }
14349    }
14350  } else {
14351    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14352    if (dt.Is(F32)) {
14353      if (cond.Is(al)) {
14354        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14355                rm.Encode(5, 0));
14356        return;
14357      }
14358    }
14359  }
14360  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14361}
14362
14363void Assembler::vaclt(
14364    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14365  VIXL_ASSERT(AllowAssembler());
14366  CheckIT(cond);
14367  if (IsUsingT32()) {
14368    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14369    if (dt.Is(F32)) {
14370      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14371        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14372                   rm.Encode(5, 0));
14373        AdvanceIT();
14374        return;
14375      }
14376    }
14377  } else {
14378    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14379    if (dt.Is(F32)) {
14380      if (cond.Is(al)) {
14381        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14382                rm.Encode(5, 0));
14383        return;
14384      }
14385    }
14386  }
14387  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14388}
14389
14390void Assembler::vadd(
14391    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14392  VIXL_ASSERT(AllowAssembler());
14393  CheckIT(cond);
14394  Dt_size_2 encoded_dt(dt);
14395  if (IsUsingT32()) {
14396    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14397    if (dt.Is(F32)) {
14398      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14399        EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14400                   rm.Encode(5, 0));
14401        AdvanceIT();
14402        return;
14403      }
14404    }
14405    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
14406    if (dt.Is(F64)) {
14407      EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14408                 rm.Encode(5, 0));
14409      AdvanceIT();
14410      return;
14411    }
14412    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14413    if (encoded_dt.IsValid()) {
14414      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14415        EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
14416                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14417        AdvanceIT();
14418        return;
14419      }
14420    }
14421  } else {
14422    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14423    if (dt.Is(F32)) {
14424      if (cond.Is(al)) {
14425        EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14426                rm.Encode(5, 0));
14427        return;
14428      }
14429    }
14430    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
14431    if (dt.Is(F64) && cond.IsNotNever()) {
14432      EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14433              rn.Encode(7, 16) | rm.Encode(5, 0));
14434      return;
14435    }
14436    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14437    if (encoded_dt.IsValid()) {
14438      if (cond.Is(al)) {
14439        EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
14440                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14441        return;
14442      }
14443    }
14444  }
14445  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14446}
14447
14448void Assembler::vadd(
14449    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14450  VIXL_ASSERT(AllowAssembler());
14451  CheckIT(cond);
14452  Dt_size_2 encoded_dt(dt);
14453  if (IsUsingT32()) {
14454    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14455    if (dt.Is(F32)) {
14456      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14457        EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14458                   rm.Encode(5, 0));
14459        AdvanceIT();
14460        return;
14461      }
14462    }
14463    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14464    if (encoded_dt.IsValid()) {
14465      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14466        EmitT32_32(0xef000840U | (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 {<Qd>}, <Qn>, <Qm> ; A1
14474    if (dt.Is(F32)) {
14475      if (cond.Is(al)) {
14476        EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14477                rm.Encode(5, 0));
14478        return;
14479      }
14480    }
14481    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14482    if (encoded_dt.IsValid()) {
14483      if (cond.Is(al)) {
14484        EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
14485                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14486        return;
14487      }
14488    }
14489  }
14490  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14491}
14492
14493void Assembler::vadd(
14494    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
14495  VIXL_ASSERT(AllowAssembler());
14496  CheckIT(cond);
14497  if (IsUsingT32()) {
14498    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
14499    if (dt.Is(F32)) {
14500      EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14501                 rm.Encode(5, 0));
14502      AdvanceIT();
14503      return;
14504    }
14505  } else {
14506    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
14507    if (dt.Is(F32) && cond.IsNotNever()) {
14508      EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14509              rn.Encode(7, 16) | rm.Encode(5, 0));
14510      return;
14511    }
14512  }
14513  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14514}
14515
14516void Assembler::vaddhn(
14517    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
14518  VIXL_ASSERT(AllowAssembler());
14519  CheckIT(cond);
14520  Dt_size_3 encoded_dt(dt);
14521  if (IsUsingT32()) {
14522    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
14523    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14524      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14525        EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
14526                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14527        AdvanceIT();
14528        return;
14529      }
14530    }
14531  } else {
14532    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
14533    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14534      if (cond.Is(al)) {
14535        EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
14536                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14537        return;
14538      }
14539    }
14540  }
14541  Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
14542}
14543
14544void Assembler::vaddl(
14545    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
14546  VIXL_ASSERT(AllowAssembler());
14547  CheckIT(cond);
14548  Dt_U_size_1 encoded_dt(dt);
14549  if (IsUsingT32()) {
14550    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14551    if (encoded_dt.IsValid()) {
14552      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14553        EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14554                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14555                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14556        AdvanceIT();
14557        return;
14558      }
14559    }
14560  } else {
14561    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14562    if (encoded_dt.IsValid()) {
14563      if (cond.Is(al)) {
14564        EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14565                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14566                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14567        return;
14568      }
14569    }
14570  }
14571  Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
14572}
14573
14574void Assembler::vaddw(
14575    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
14576  VIXL_ASSERT(AllowAssembler());
14577  CheckIT(cond);
14578  Dt_U_size_1 encoded_dt(dt);
14579  if (IsUsingT32()) {
14580    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
14581    if (encoded_dt.IsValid()) {
14582      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14583        EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14584                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14585                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14586        AdvanceIT();
14587        return;
14588      }
14589    }
14590  } else {
14591    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
14592    if (encoded_dt.IsValid()) {
14593      if (cond.Is(al)) {
14594        EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14595                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14596                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14597        return;
14598      }
14599    }
14600  }
14601  Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
14602}
14603
14604void Assembler::vand(Condition cond,
14605                     DataType dt,
14606                     DRegister rd,
14607                     DRegister rn,
14608                     const DOperand& operand) {
14609  VIXL_ASSERT(AllowAssembler());
14610  CheckIT(cond);
14611  if (operand.IsImmediate()) {
14612    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
14613    if (IsUsingT32()) {
14614      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14615      if (encoded_dt.IsValid() && rd.Is(rn)) {
14616        if (cond.Is(al) || AllowStronglyDiscouraged()) {
14617          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14618                     rd.Encode(22, 12) |
14619                     (encoded_dt.GetEncodedImmediate() & 0xf) |
14620                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14621                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14622          AdvanceIT();
14623          return;
14624        }
14625      }
14626    } else {
14627      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14628      if (encoded_dt.IsValid() && rd.Is(rn)) {
14629        if (cond.Is(al)) {
14630          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14631                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14632                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14633                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14634          return;
14635        }
14636      }
14637    }
14638  }
14639  if (operand.IsRegister()) {
14640    DRegister rm = operand.GetRegister();
14641    USE(dt);
14642    if (IsUsingT32()) {
14643      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14644      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14645        EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14646                   rm.Encode(5, 0));
14647        AdvanceIT();
14648        return;
14649      }
14650    } else {
14651      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14652      if (cond.Is(al)) {
14653        EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14654                rm.Encode(5, 0));
14655        return;
14656      }
14657    }
14658  }
14659  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14660}
14661
14662void Assembler::vand(Condition cond,
14663                     DataType dt,
14664                     QRegister rd,
14665                     QRegister rn,
14666                     const QOperand& operand) {
14667  VIXL_ASSERT(AllowAssembler());
14668  CheckIT(cond);
14669  if (operand.IsImmediate()) {
14670    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
14671    if (IsUsingT32()) {
14672      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14673      if (encoded_dt.IsValid() && rd.Is(rn)) {
14674        if (cond.Is(al) || AllowStronglyDiscouraged()) {
14675          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14676                     rd.Encode(22, 12) |
14677                     (encoded_dt.GetEncodedImmediate() & 0xf) |
14678                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14679                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14680          AdvanceIT();
14681          return;
14682        }
14683      }
14684    } else {
14685      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14686      if (encoded_dt.IsValid() && rd.Is(rn)) {
14687        if (cond.Is(al)) {
14688          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14689                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14690                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14691                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14692          return;
14693        }
14694      }
14695    }
14696  }
14697  if (operand.IsRegister()) {
14698    QRegister rm = operand.GetRegister();
14699    USE(dt);
14700    if (IsUsingT32()) {
14701      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14702      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14703        EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14704                   rm.Encode(5, 0));
14705        AdvanceIT();
14706        return;
14707      }
14708    } else {
14709      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14710      if (cond.Is(al)) {
14711        EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14712                rm.Encode(5, 0));
14713        return;
14714      }
14715    }
14716  }
14717  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14718}
14719
14720void Assembler::vbic(Condition cond,
14721                     DataType dt,
14722                     DRegister rd,
14723                     DRegister rn,
14724                     const DOperand& operand) {
14725  VIXL_ASSERT(AllowAssembler());
14726  CheckIT(cond);
14727  if (operand.IsImmediate()) {
14728    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
14729    if (IsUsingT32()) {
14730      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14731      if (encoded_dt.IsValid() && rd.Is(rn)) {
14732        if (cond.Is(al) || AllowStronglyDiscouraged()) {
14733          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14734                     rd.Encode(22, 12) |
14735                     (encoded_dt.GetEncodedImmediate() & 0xf) |
14736                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14737                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14738          AdvanceIT();
14739          return;
14740        }
14741      }
14742    } else {
14743      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14744      if (encoded_dt.IsValid() && rd.Is(rn)) {
14745        if (cond.Is(al)) {
14746          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14747                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14748                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14749                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14750          return;
14751        }
14752      }
14753    }
14754  }
14755  if (operand.IsRegister()) {
14756    DRegister rm = operand.GetRegister();
14757    USE(dt);
14758    if (IsUsingT32()) {
14759      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14760      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14761        EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14762                   rm.Encode(5, 0));
14763        AdvanceIT();
14764        return;
14765      }
14766    } else {
14767      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14768      if (cond.Is(al)) {
14769        EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14770                rm.Encode(5, 0));
14771        return;
14772      }
14773    }
14774  }
14775  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14776}
14777
14778void Assembler::vbic(Condition cond,
14779                     DataType dt,
14780                     QRegister rd,
14781                     QRegister rn,
14782                     const QOperand& operand) {
14783  VIXL_ASSERT(AllowAssembler());
14784  CheckIT(cond);
14785  if (operand.IsImmediate()) {
14786    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
14787    if (IsUsingT32()) {
14788      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14789      if (encoded_dt.IsValid() && rd.Is(rn)) {
14790        if (cond.Is(al) || AllowStronglyDiscouraged()) {
14791          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14792                     rd.Encode(22, 12) |
14793                     (encoded_dt.GetEncodedImmediate() & 0xf) |
14794                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14795                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14796          AdvanceIT();
14797          return;
14798        }
14799      }
14800    } else {
14801      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14802      if (encoded_dt.IsValid() && rd.Is(rn)) {
14803        if (cond.Is(al)) {
14804          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14805                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14806                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14807                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14808          return;
14809        }
14810      }
14811    }
14812  }
14813  if (operand.IsRegister()) {
14814    QRegister rm = operand.GetRegister();
14815    USE(dt);
14816    if (IsUsingT32()) {
14817      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14818      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14819        EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14820                   rm.Encode(5, 0));
14821        AdvanceIT();
14822        return;
14823      }
14824    } else {
14825      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14826      if (cond.Is(al)) {
14827        EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14828                rm.Encode(5, 0));
14829        return;
14830      }
14831    }
14832  }
14833  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14834}
14835
14836void Assembler::vbif(
14837    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14838  VIXL_ASSERT(AllowAssembler());
14839  CheckIT(cond);
14840  USE(dt);
14841  if (IsUsingT32()) {
14842    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14843    if (cond.Is(al) || AllowStronglyDiscouraged()) {
14844      EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14845                 rm.Encode(5, 0));
14846      AdvanceIT();
14847      return;
14848    }
14849  } else {
14850    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14851    if (cond.Is(al)) {
14852      EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14853              rm.Encode(5, 0));
14854      return;
14855    }
14856  }
14857  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14858}
14859
14860void Assembler::vbif(
14861    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14862  VIXL_ASSERT(AllowAssembler());
14863  CheckIT(cond);
14864  USE(dt);
14865  if (IsUsingT32()) {
14866    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14867    if (cond.Is(al) || AllowStronglyDiscouraged()) {
14868      EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14869                 rm.Encode(5, 0));
14870      AdvanceIT();
14871      return;
14872    }
14873  } else {
14874    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14875    if (cond.Is(al)) {
14876      EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14877              rm.Encode(5, 0));
14878      return;
14879    }
14880  }
14881  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14882}
14883
14884void Assembler::vbit(
14885    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14886  VIXL_ASSERT(AllowAssembler());
14887  CheckIT(cond);
14888  USE(dt);
14889  if (IsUsingT32()) {
14890    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14891    if (cond.Is(al) || AllowStronglyDiscouraged()) {
14892      EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14893                 rm.Encode(5, 0));
14894      AdvanceIT();
14895      return;
14896    }
14897  } else {
14898    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14899    if (cond.Is(al)) {
14900      EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14901              rm.Encode(5, 0));
14902      return;
14903    }
14904  }
14905  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14906}
14907
14908void Assembler::vbit(
14909    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14910  VIXL_ASSERT(AllowAssembler());
14911  CheckIT(cond);
14912  USE(dt);
14913  if (IsUsingT32()) {
14914    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14915    if (cond.Is(al) || AllowStronglyDiscouraged()) {
14916      EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14917                 rm.Encode(5, 0));
14918      AdvanceIT();
14919      return;
14920    }
14921  } else {
14922    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14923    if (cond.Is(al)) {
14924      EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14925              rm.Encode(5, 0));
14926      return;
14927    }
14928  }
14929  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14930}
14931
14932void Assembler::vbsl(
14933    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14934  VIXL_ASSERT(AllowAssembler());
14935  CheckIT(cond);
14936  USE(dt);
14937  if (IsUsingT32()) {
14938    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14939    if (cond.Is(al) || AllowStronglyDiscouraged()) {
14940      EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14941                 rm.Encode(5, 0));
14942      AdvanceIT();
14943      return;
14944    }
14945  } else {
14946    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14947    if (cond.Is(al)) {
14948      EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14949              rm.Encode(5, 0));
14950      return;
14951    }
14952  }
14953  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14954}
14955
14956void Assembler::vbsl(
14957    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14958  VIXL_ASSERT(AllowAssembler());
14959  CheckIT(cond);
14960  USE(dt);
14961  if (IsUsingT32()) {
14962    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14963    if (cond.Is(al) || AllowStronglyDiscouraged()) {
14964      EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14965                 rm.Encode(5, 0));
14966      AdvanceIT();
14967      return;
14968    }
14969  } else {
14970    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14971    if (cond.Is(al)) {
14972      EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14973              rm.Encode(5, 0));
14974      return;
14975    }
14976  }
14977  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14978}
14979
14980void Assembler::vceq(Condition cond,
14981                     DataType dt,
14982                     DRegister rd,
14983                     DRegister rm,
14984                     const DOperand& operand) {
14985  VIXL_ASSERT(AllowAssembler());
14986  CheckIT(cond);
14987  if (operand.IsImmediate()) {
14988    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14989      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14990      Dt_F_size_2 encoded_dt(dt);
14991      if (IsUsingT32()) {
14992        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14993        if (encoded_dt.IsValid() && (imm == 0)) {
14994          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14995            EmitT32_32(0xffb10100U |
14996                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14997                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14998                       rd.Encode(22, 12) | rm.Encode(5, 0));
14999            AdvanceIT();
15000            return;
15001          }
15002        }
15003      } else {
15004        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15005        if (encoded_dt.IsValid() && (imm == 0)) {
15006          if (cond.Is(al)) {
15007            EmitA32(0xf3b10100U |
15008                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15009                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15010                    rd.Encode(22, 12) | rm.Encode(5, 0));
15011            return;
15012          }
15013        }
15014      }
15015    }
15016  }
15017  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15018}
15019
15020void Assembler::vceq(Condition cond,
15021                     DataType dt,
15022                     QRegister rd,
15023                     QRegister rm,
15024                     const QOperand& operand) {
15025  VIXL_ASSERT(AllowAssembler());
15026  CheckIT(cond);
15027  if (operand.IsImmediate()) {
15028    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15029      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15030      Dt_F_size_2 encoded_dt(dt);
15031      if (IsUsingT32()) {
15032        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15033        if (encoded_dt.IsValid() && (imm == 0)) {
15034          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15035            EmitT32_32(0xffb10140U |
15036                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15037                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15038                       rd.Encode(22, 12) | rm.Encode(5, 0));
15039            AdvanceIT();
15040            return;
15041          }
15042        }
15043      } else {
15044        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15045        if (encoded_dt.IsValid() && (imm == 0)) {
15046          if (cond.Is(al)) {
15047            EmitA32(0xf3b10140U |
15048                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15049                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15050                    rd.Encode(22, 12) | rm.Encode(5, 0));
15051            return;
15052          }
15053        }
15054      }
15055    }
15056  }
15057  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15058}
15059
15060void Assembler::vceq(
15061    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15062  VIXL_ASSERT(AllowAssembler());
15063  CheckIT(cond);
15064  Dt_size_4 encoded_dt(dt);
15065  Dt_sz_1 encoded_dt_2(dt);
15066  if (IsUsingT32()) {
15067    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15068    if (encoded_dt.IsValid()) {
15069      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15070        EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
15071                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15072        AdvanceIT();
15073        return;
15074      }
15075    }
15076    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
15077    if (encoded_dt_2.IsValid()) {
15078      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15079        EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15080                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15081        AdvanceIT();
15082        return;
15083      }
15084    }
15085  } else {
15086    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15087    if (encoded_dt.IsValid()) {
15088      if (cond.Is(al)) {
15089        EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
15090                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15091        return;
15092      }
15093    }
15094    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
15095    if (encoded_dt_2.IsValid()) {
15096      if (cond.Is(al)) {
15097        EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15098                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15099        return;
15100      }
15101    }
15102  }
15103  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15104}
15105
15106void Assembler::vceq(
15107    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15108  VIXL_ASSERT(AllowAssembler());
15109  CheckIT(cond);
15110  Dt_size_4 encoded_dt(dt);
15111  Dt_sz_1 encoded_dt_2(dt);
15112  if (IsUsingT32()) {
15113    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15114    if (encoded_dt.IsValid()) {
15115      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15116        EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
15117                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15118        AdvanceIT();
15119        return;
15120      }
15121    }
15122    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
15123    if (encoded_dt_2.IsValid()) {
15124      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15125        EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15126                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15127        AdvanceIT();
15128        return;
15129      }
15130    }
15131  } else {
15132    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15133    if (encoded_dt.IsValid()) {
15134      if (cond.Is(al)) {
15135        EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
15136                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15137        return;
15138      }
15139    }
15140    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
15141    if (encoded_dt_2.IsValid()) {
15142      if (cond.Is(al)) {
15143        EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15144                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15145        return;
15146      }
15147    }
15148  }
15149  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15150}
15151
15152void Assembler::vcge(Condition cond,
15153                     DataType dt,
15154                     DRegister rd,
15155                     DRegister rm,
15156                     const DOperand& operand) {
15157  VIXL_ASSERT(AllowAssembler());
15158  CheckIT(cond);
15159  if (operand.IsImmediate()) {
15160    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15161      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15162      Dt_F_size_1 encoded_dt(dt);
15163      if (IsUsingT32()) {
15164        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15165        if (encoded_dt.IsValid() && (imm == 0)) {
15166          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15167            EmitT32_32(0xffb10080U |
15168                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15169                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15170                       rd.Encode(22, 12) | rm.Encode(5, 0));
15171            AdvanceIT();
15172            return;
15173          }
15174        }
15175      } else {
15176        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15177        if (encoded_dt.IsValid() && (imm == 0)) {
15178          if (cond.Is(al)) {
15179            EmitA32(0xf3b10080U |
15180                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15181                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15182                    rd.Encode(22, 12) | rm.Encode(5, 0));
15183            return;
15184          }
15185        }
15186      }
15187    }
15188  }
15189  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15190}
15191
15192void Assembler::vcge(Condition cond,
15193                     DataType dt,
15194                     QRegister rd,
15195                     QRegister rm,
15196                     const QOperand& operand) {
15197  VIXL_ASSERT(AllowAssembler());
15198  CheckIT(cond);
15199  if (operand.IsImmediate()) {
15200    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15201      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15202      Dt_F_size_1 encoded_dt(dt);
15203      if (IsUsingT32()) {
15204        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15205        if (encoded_dt.IsValid() && (imm == 0)) {
15206          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15207            EmitT32_32(0xffb100c0U |
15208                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15209                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15210                       rd.Encode(22, 12) | rm.Encode(5, 0));
15211            AdvanceIT();
15212            return;
15213          }
15214        }
15215      } else {
15216        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15217        if (encoded_dt.IsValid() && (imm == 0)) {
15218          if (cond.Is(al)) {
15219            EmitA32(0xf3b100c0U |
15220                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15221                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15222                    rd.Encode(22, 12) | rm.Encode(5, 0));
15223            return;
15224          }
15225        }
15226      }
15227    }
15228  }
15229  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15230}
15231
15232void Assembler::vcge(
15233    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15234  VIXL_ASSERT(AllowAssembler());
15235  CheckIT(cond);
15236  Dt_U_size_1 encoded_dt(dt);
15237  if (IsUsingT32()) {
15238    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15239    if (encoded_dt.IsValid()) {
15240      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15241        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15242                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15243                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15244        AdvanceIT();
15245        return;
15246      }
15247    }
15248    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15249    if (dt.Is(F32)) {
15250      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15251        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15252                   rm.Encode(5, 0));
15253        AdvanceIT();
15254        return;
15255      }
15256    }
15257  } else {
15258    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15259    if (encoded_dt.IsValid()) {
15260      if (cond.Is(al)) {
15261        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15262                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15263                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15264        return;
15265      }
15266    }
15267    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15268    if (dt.Is(F32)) {
15269      if (cond.Is(al)) {
15270        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15271                rm.Encode(5, 0));
15272        return;
15273      }
15274    }
15275  }
15276  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15277}
15278
15279void Assembler::vcge(
15280    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15281  VIXL_ASSERT(AllowAssembler());
15282  CheckIT(cond);
15283  Dt_U_size_1 encoded_dt(dt);
15284  if (IsUsingT32()) {
15285    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15286    if (encoded_dt.IsValid()) {
15287      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15288        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15289                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15290                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15291        AdvanceIT();
15292        return;
15293      }
15294    }
15295    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15296    if (dt.Is(F32)) {
15297      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15298        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15299                   rm.Encode(5, 0));
15300        AdvanceIT();
15301        return;
15302      }
15303    }
15304  } else {
15305    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15306    if (encoded_dt.IsValid()) {
15307      if (cond.Is(al)) {
15308        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15309                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15310                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15311        return;
15312      }
15313    }
15314    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15315    if (dt.Is(F32)) {
15316      if (cond.Is(al)) {
15317        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15318                rm.Encode(5, 0));
15319        return;
15320      }
15321    }
15322  }
15323  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15324}
15325
15326void Assembler::vcgt(Condition cond,
15327                     DataType dt,
15328                     DRegister rd,
15329                     DRegister rm,
15330                     const DOperand& operand) {
15331  VIXL_ASSERT(AllowAssembler());
15332  CheckIT(cond);
15333  if (operand.IsImmediate()) {
15334    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15335      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15336      Dt_F_size_1 encoded_dt(dt);
15337      if (IsUsingT32()) {
15338        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15339        if (encoded_dt.IsValid() && (imm == 0)) {
15340          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15341            EmitT32_32(0xffb10000U |
15342                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15343                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15344                       rd.Encode(22, 12) | rm.Encode(5, 0));
15345            AdvanceIT();
15346            return;
15347          }
15348        }
15349      } else {
15350        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15351        if (encoded_dt.IsValid() && (imm == 0)) {
15352          if (cond.Is(al)) {
15353            EmitA32(0xf3b10000U |
15354                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15355                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15356                    rd.Encode(22, 12) | rm.Encode(5, 0));
15357            return;
15358          }
15359        }
15360      }
15361    }
15362  }
15363  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15364}
15365
15366void Assembler::vcgt(Condition cond,
15367                     DataType dt,
15368                     QRegister rd,
15369                     QRegister rm,
15370                     const QOperand& operand) {
15371  VIXL_ASSERT(AllowAssembler());
15372  CheckIT(cond);
15373  if (operand.IsImmediate()) {
15374    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15375      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15376      Dt_F_size_1 encoded_dt(dt);
15377      if (IsUsingT32()) {
15378        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15379        if (encoded_dt.IsValid() && (imm == 0)) {
15380          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15381            EmitT32_32(0xffb10040U |
15382                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15383                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15384                       rd.Encode(22, 12) | rm.Encode(5, 0));
15385            AdvanceIT();
15386            return;
15387          }
15388        }
15389      } else {
15390        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15391        if (encoded_dt.IsValid() && (imm == 0)) {
15392          if (cond.Is(al)) {
15393            EmitA32(0xf3b10040U |
15394                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15395                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15396                    rd.Encode(22, 12) | rm.Encode(5, 0));
15397            return;
15398          }
15399        }
15400      }
15401    }
15402  }
15403  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15404}
15405
15406void Assembler::vcgt(
15407    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15408  VIXL_ASSERT(AllowAssembler());
15409  CheckIT(cond);
15410  Dt_U_size_1 encoded_dt(dt);
15411  if (IsUsingT32()) {
15412    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15413    if (encoded_dt.IsValid()) {
15414      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15415        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15416                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15417                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15418        AdvanceIT();
15419        return;
15420      }
15421    }
15422    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15423    if (dt.Is(F32)) {
15424      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15425        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15426                   rm.Encode(5, 0));
15427        AdvanceIT();
15428        return;
15429      }
15430    }
15431  } else {
15432    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15433    if (encoded_dt.IsValid()) {
15434      if (cond.Is(al)) {
15435        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15436                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15437                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15438        return;
15439      }
15440    }
15441    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15442    if (dt.Is(F32)) {
15443      if (cond.Is(al)) {
15444        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15445                rm.Encode(5, 0));
15446        return;
15447      }
15448    }
15449  }
15450  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15451}
15452
15453void Assembler::vcgt(
15454    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15455  VIXL_ASSERT(AllowAssembler());
15456  CheckIT(cond);
15457  Dt_U_size_1 encoded_dt(dt);
15458  if (IsUsingT32()) {
15459    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15460    if (encoded_dt.IsValid()) {
15461      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15462        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15463                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15464                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15465        AdvanceIT();
15466        return;
15467      }
15468    }
15469    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15470    if (dt.Is(F32)) {
15471      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15472        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15473                   rm.Encode(5, 0));
15474        AdvanceIT();
15475        return;
15476      }
15477    }
15478  } else {
15479    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15480    if (encoded_dt.IsValid()) {
15481      if (cond.Is(al)) {
15482        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15483                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15484                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15485        return;
15486      }
15487    }
15488    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15489    if (dt.Is(F32)) {
15490      if (cond.Is(al)) {
15491        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15492                rm.Encode(5, 0));
15493        return;
15494      }
15495    }
15496  }
15497  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15498}
15499
15500void Assembler::vcle(Condition cond,
15501                     DataType dt,
15502                     DRegister rd,
15503                     DRegister rm,
15504                     const DOperand& operand) {
15505  VIXL_ASSERT(AllowAssembler());
15506  CheckIT(cond);
15507  if (operand.IsImmediate()) {
15508    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15509      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15510      Dt_F_size_1 encoded_dt(dt);
15511      if (IsUsingT32()) {
15512        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15513        if (encoded_dt.IsValid() && (imm == 0)) {
15514          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15515            EmitT32_32(0xffb10180U |
15516                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15517                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15518                       rd.Encode(22, 12) | rm.Encode(5, 0));
15519            AdvanceIT();
15520            return;
15521          }
15522        }
15523      } else {
15524        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15525        if (encoded_dt.IsValid() && (imm == 0)) {
15526          if (cond.Is(al)) {
15527            EmitA32(0xf3b10180U |
15528                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15529                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15530                    rd.Encode(22, 12) | rm.Encode(5, 0));
15531            return;
15532          }
15533        }
15534      }
15535    }
15536  }
15537  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15538}
15539
15540void Assembler::vcle(Condition cond,
15541                     DataType dt,
15542                     QRegister rd,
15543                     QRegister rm,
15544                     const QOperand& operand) {
15545  VIXL_ASSERT(AllowAssembler());
15546  CheckIT(cond);
15547  if (operand.IsImmediate()) {
15548    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15549      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15550      Dt_F_size_1 encoded_dt(dt);
15551      if (IsUsingT32()) {
15552        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15553        if (encoded_dt.IsValid() && (imm == 0)) {
15554          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15555            EmitT32_32(0xffb101c0U |
15556                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15557                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15558                       rd.Encode(22, 12) | rm.Encode(5, 0));
15559            AdvanceIT();
15560            return;
15561          }
15562        }
15563      } else {
15564        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15565        if (encoded_dt.IsValid() && (imm == 0)) {
15566          if (cond.Is(al)) {
15567            EmitA32(0xf3b101c0U |
15568                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15569                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15570                    rd.Encode(22, 12) | rm.Encode(5, 0));
15571            return;
15572          }
15573        }
15574      }
15575    }
15576  }
15577  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15578}
15579
15580void Assembler::vcle(
15581    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15582  VIXL_ASSERT(AllowAssembler());
15583  CheckIT(cond);
15584  Dt_U_size_1 encoded_dt(dt);
15585  if (IsUsingT32()) {
15586    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15587    if (encoded_dt.IsValid()) {
15588      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15589        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15590                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15591                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15592        AdvanceIT();
15593        return;
15594      }
15595    }
15596    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15597    if (dt.Is(F32)) {
15598      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15599        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15600                   rm.Encode(7, 16));
15601        AdvanceIT();
15602        return;
15603      }
15604    }
15605  } else {
15606    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15607    if (encoded_dt.IsValid()) {
15608      if (cond.Is(al)) {
15609        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15610                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15611                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15612        return;
15613      }
15614    }
15615    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15616    if (dt.Is(F32)) {
15617      if (cond.Is(al)) {
15618        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15619                rm.Encode(7, 16));
15620        return;
15621      }
15622    }
15623  }
15624  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15625}
15626
15627void Assembler::vcle(
15628    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15629  VIXL_ASSERT(AllowAssembler());
15630  CheckIT(cond);
15631  Dt_U_size_1 encoded_dt(dt);
15632  if (IsUsingT32()) {
15633    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15634    if (encoded_dt.IsValid()) {
15635      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15636        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15637                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15638                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15639        AdvanceIT();
15640        return;
15641      }
15642    }
15643    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15644    if (dt.Is(F32)) {
15645      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15646        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15647                   rm.Encode(7, 16));
15648        AdvanceIT();
15649        return;
15650      }
15651    }
15652  } else {
15653    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15654    if (encoded_dt.IsValid()) {
15655      if (cond.Is(al)) {
15656        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15657                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15658                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15659        return;
15660      }
15661    }
15662    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15663    if (dt.Is(F32)) {
15664      if (cond.Is(al)) {
15665        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15666                rm.Encode(7, 16));
15667        return;
15668      }
15669    }
15670  }
15671  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15672}
15673
15674void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
15675  VIXL_ASSERT(AllowAssembler());
15676  CheckIT(cond);
15677  Dt_size_5 encoded_dt(dt);
15678  if (IsUsingT32()) {
15679    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15680    if (encoded_dt.IsValid()) {
15681      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15682        EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
15683                   rd.Encode(22, 12) | rm.Encode(5, 0));
15684        AdvanceIT();
15685        return;
15686      }
15687    }
15688  } else {
15689    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15690    if (encoded_dt.IsValid()) {
15691      if (cond.Is(al)) {
15692        EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
15693                rd.Encode(22, 12) | rm.Encode(5, 0));
15694        return;
15695      }
15696    }
15697  }
15698  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15699}
15700
15701void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
15702  VIXL_ASSERT(AllowAssembler());
15703  CheckIT(cond);
15704  Dt_size_5 encoded_dt(dt);
15705  if (IsUsingT32()) {
15706    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15707    if (encoded_dt.IsValid()) {
15708      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15709        EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
15710                   rd.Encode(22, 12) | rm.Encode(5, 0));
15711        AdvanceIT();
15712        return;
15713      }
15714    }
15715  } else {
15716    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15717    if (encoded_dt.IsValid()) {
15718      if (cond.Is(al)) {
15719        EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
15720                rd.Encode(22, 12) | rm.Encode(5, 0));
15721        return;
15722      }
15723    }
15724  }
15725  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15726}
15727
15728void Assembler::vclt(Condition cond,
15729                     DataType dt,
15730                     DRegister rd,
15731                     DRegister rm,
15732                     const DOperand& operand) {
15733  VIXL_ASSERT(AllowAssembler());
15734  CheckIT(cond);
15735  if (operand.IsImmediate()) {
15736    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15737      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15738      Dt_F_size_1 encoded_dt(dt);
15739      if (IsUsingT32()) {
15740        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15741        if (encoded_dt.IsValid() && (imm == 0)) {
15742          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15743            EmitT32_32(0xffb10200U |
15744                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15745                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15746                       rd.Encode(22, 12) | rm.Encode(5, 0));
15747            AdvanceIT();
15748            return;
15749          }
15750        }
15751      } else {
15752        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15753        if (encoded_dt.IsValid() && (imm == 0)) {
15754          if (cond.Is(al)) {
15755            EmitA32(0xf3b10200U |
15756                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15757                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15758                    rd.Encode(22, 12) | rm.Encode(5, 0));
15759            return;
15760          }
15761        }
15762      }
15763    }
15764  }
15765  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15766}
15767
15768void Assembler::vclt(Condition cond,
15769                     DataType dt,
15770                     QRegister rd,
15771                     QRegister rm,
15772                     const QOperand& operand) {
15773  VIXL_ASSERT(AllowAssembler());
15774  CheckIT(cond);
15775  if (operand.IsImmediate()) {
15776    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15777      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15778      Dt_F_size_1 encoded_dt(dt);
15779      if (IsUsingT32()) {
15780        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15781        if (encoded_dt.IsValid() && (imm == 0)) {
15782          if (cond.Is(al) || AllowStronglyDiscouraged()) {
15783            EmitT32_32(0xffb10240U |
15784                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15785                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15786                       rd.Encode(22, 12) | rm.Encode(5, 0));
15787            AdvanceIT();
15788            return;
15789          }
15790        }
15791      } else {
15792        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15793        if (encoded_dt.IsValid() && (imm == 0)) {
15794          if (cond.Is(al)) {
15795            EmitA32(0xf3b10240U |
15796                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15797                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15798                    rd.Encode(22, 12) | rm.Encode(5, 0));
15799            return;
15800          }
15801        }
15802      }
15803    }
15804  }
15805  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15806}
15807
15808void Assembler::vclt(
15809    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
15810  VIXL_ASSERT(AllowAssembler());
15811  CheckIT(cond);
15812  Dt_U_size_1 encoded_dt(dt);
15813  if (IsUsingT32()) {
15814    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15815    if (encoded_dt.IsValid()) {
15816      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15817        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15818                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15819                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15820        AdvanceIT();
15821        return;
15822      }
15823    }
15824    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15825    if (dt.Is(F32)) {
15826      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15827        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15828                   rm.Encode(7, 16));
15829        AdvanceIT();
15830        return;
15831      }
15832    }
15833  } else {
15834    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15835    if (encoded_dt.IsValid()) {
15836      if (cond.Is(al)) {
15837        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15838                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15839                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15840        return;
15841      }
15842    }
15843    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15844    if (dt.Is(F32)) {
15845      if (cond.Is(al)) {
15846        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15847                rm.Encode(7, 16));
15848        return;
15849      }
15850    }
15851  }
15852  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15853}
15854
15855void Assembler::vclt(
15856    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
15857  VIXL_ASSERT(AllowAssembler());
15858  CheckIT(cond);
15859  Dt_U_size_1 encoded_dt(dt);
15860  if (IsUsingT32()) {
15861    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15862    if (encoded_dt.IsValid()) {
15863      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15864        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15865                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
15866                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15867        AdvanceIT();
15868        return;
15869      }
15870    }
15871    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15872    if (dt.Is(F32)) {
15873      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15874        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15875                   rm.Encode(7, 16));
15876        AdvanceIT();
15877        return;
15878      }
15879    }
15880  } else {
15881    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15882    if (encoded_dt.IsValid()) {
15883      if (cond.Is(al)) {
15884        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15885                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15886                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
15887        return;
15888      }
15889    }
15890    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15891    if (dt.Is(F32)) {
15892      if (cond.Is(al)) {
15893        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15894                rm.Encode(7, 16));
15895        return;
15896      }
15897    }
15898  }
15899  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15900}
15901
15902void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
15903  VIXL_ASSERT(AllowAssembler());
15904  CheckIT(cond);
15905  Dt_size_4 encoded_dt(dt);
15906  if (IsUsingT32()) {
15907    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15908    if (encoded_dt.IsValid()) {
15909      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15910        EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
15911                   rd.Encode(22, 12) | rm.Encode(5, 0));
15912        AdvanceIT();
15913        return;
15914      }
15915    }
15916  } else {
15917    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15918    if (encoded_dt.IsValid()) {
15919      if (cond.Is(al)) {
15920        EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
15921                rd.Encode(22, 12) | rm.Encode(5, 0));
15922        return;
15923      }
15924    }
15925  }
15926  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15927}
15928
15929void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
15930  VIXL_ASSERT(AllowAssembler());
15931  CheckIT(cond);
15932  Dt_size_4 encoded_dt(dt);
15933  if (IsUsingT32()) {
15934    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15935    if (encoded_dt.IsValid()) {
15936      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15937        EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
15938                   rd.Encode(22, 12) | rm.Encode(5, 0));
15939        AdvanceIT();
15940        return;
15941      }
15942    }
15943  } else {
15944    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15945    if (encoded_dt.IsValid()) {
15946      if (cond.Is(al)) {
15947        EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
15948                rd.Encode(22, 12) | rm.Encode(5, 0));
15949        return;
15950      }
15951    }
15952  }
15953  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15954}
15955
15956void Assembler::vcmp(Condition cond,
15957                     DataType dt,
15958                     SRegister rd,
15959                     const SOperand& operand) {
15960  VIXL_ASSERT(AllowAssembler());
15961  CheckIT(cond);
15962  if (operand.IsRegister()) {
15963    SRegister rm = operand.GetRegister();
15964    if (IsUsingT32()) {
15965      // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
15966      if (dt.Is(F32)) {
15967        EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15968        AdvanceIT();
15969        return;
15970      }
15971    } else {
15972      // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
15973      if (dt.Is(F32) && cond.IsNotNever()) {
15974        EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15975                rm.Encode(5, 0));
15976        return;
15977      }
15978    }
15979  }
15980  if (operand.IsImmediate()) {
15981    if (IsUsingT32()) {
15982      // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
15983      if (dt.Is(F32) && (operand.IsFloatZero())) {
15984        EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
15985        AdvanceIT();
15986        return;
15987      }
15988    } else {
15989      // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
15990      if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
15991        EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
15992        return;
15993      }
15994    }
15995  }
15996  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
15997}
15998
15999void Assembler::vcmp(Condition cond,
16000                     DataType dt,
16001                     DRegister rd,
16002                     const DOperand& operand) {
16003  VIXL_ASSERT(AllowAssembler());
16004  CheckIT(cond);
16005  if (operand.IsRegister()) {
16006    DRegister rm = operand.GetRegister();
16007    if (IsUsingT32()) {
16008      // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16009      if (dt.Is(F64)) {
16010        EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16011        AdvanceIT();
16012        return;
16013      }
16014    } else {
16015      // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16016      if (dt.Is(F64) && cond.IsNotNever()) {
16017        EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16018                rm.Encode(5, 0));
16019        return;
16020      }
16021    }
16022  }
16023  if (operand.IsImmediate()) {
16024    if (IsUsingT32()) {
16025      // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16026      if (dt.Is(F64) && (operand.IsFloatZero())) {
16027        EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
16028        AdvanceIT();
16029        return;
16030      }
16031    } else {
16032      // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16033      if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16034        EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16035        return;
16036      }
16037    }
16038  }
16039  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
16040}
16041
16042void Assembler::vcmpe(Condition cond,
16043                      DataType dt,
16044                      SRegister rd,
16045                      const SOperand& operand) {
16046  VIXL_ASSERT(AllowAssembler());
16047  CheckIT(cond);
16048  if (operand.IsRegister()) {
16049    SRegister rm = operand.GetRegister();
16050    if (IsUsingT32()) {
16051      // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16052      if (dt.Is(F32)) {
16053        EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16054        AdvanceIT();
16055        return;
16056      }
16057    } else {
16058      // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16059      if (dt.Is(F32) && cond.IsNotNever()) {
16060        EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16061                rm.Encode(5, 0));
16062        return;
16063      }
16064    }
16065  }
16066  if (operand.IsImmediate()) {
16067    if (IsUsingT32()) {
16068      // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16069      if (dt.Is(F32) && (operand.IsFloatZero())) {
16070        EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
16071        AdvanceIT();
16072        return;
16073      }
16074    } else {
16075      // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16076      if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16077        EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16078        return;
16079      }
16080    }
16081  }
16082  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
16083}
16084
16085void Assembler::vcmpe(Condition cond,
16086                      DataType dt,
16087                      DRegister rd,
16088                      const DOperand& operand) {
16089  VIXL_ASSERT(AllowAssembler());
16090  CheckIT(cond);
16091  if (operand.IsRegister()) {
16092    DRegister rm = operand.GetRegister();
16093    if (IsUsingT32()) {
16094      // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16095      if (dt.Is(F64)) {
16096        EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16097        AdvanceIT();
16098        return;
16099      }
16100    } else {
16101      // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16102      if (dt.Is(F64) && cond.IsNotNever()) {
16103        EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16104                rm.Encode(5, 0));
16105        return;
16106      }
16107    }
16108  }
16109  if (operand.IsImmediate()) {
16110    if (IsUsingT32()) {
16111      // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16112      if (dt.Is(F64) && (operand.IsFloatZero())) {
16113        EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
16114        AdvanceIT();
16115        return;
16116      }
16117    } else {
16118      // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16119      if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16120        EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16121        return;
16122      }
16123    }
16124  }
16125  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
16126}
16127
16128void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
16129  VIXL_ASSERT(AllowAssembler());
16130  CheckIT(cond);
16131  if (IsUsingT32()) {
16132    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
16133    if (dt.Is(Untyped8)) {
16134      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16135        EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16136        AdvanceIT();
16137        return;
16138      }
16139    }
16140  } else {
16141    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
16142    if (dt.Is(Untyped8)) {
16143      if (cond.Is(al)) {
16144        EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16145        return;
16146      }
16147    }
16148  }
16149  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16150}
16151
16152void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
16153  VIXL_ASSERT(AllowAssembler());
16154  CheckIT(cond);
16155  if (IsUsingT32()) {
16156    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
16157    if (dt.Is(Untyped8)) {
16158      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16159        EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16160        AdvanceIT();
16161        return;
16162      }
16163    }
16164  } else {
16165    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
16166    if (dt.Is(Untyped8)) {
16167      if (cond.Is(al)) {
16168        EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16169        return;
16170      }
16171    }
16172  }
16173  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16174}
16175
16176void Assembler::vcvt(
16177    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
16178  VIXL_ASSERT(AllowAssembler());
16179  CheckIT(cond);
16180  Dt_op_2 encoded_dt(dt2);
16181  if (IsUsingT32()) {
16182    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
16183    if (dt1.Is(F64) && dt2.Is(F32)) {
16184      EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16185      AdvanceIT();
16186      return;
16187    }
16188    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
16189    if (dt1.Is(F64) && encoded_dt.IsValid()) {
16190      EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
16191                 rd.Encode(22, 12) | rm.Encode(5, 0));
16192      AdvanceIT();
16193      return;
16194    }
16195  } else {
16196    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
16197    if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
16198      EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16199              rm.Encode(5, 0));
16200      return;
16201    }
16202    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
16203    if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
16204      EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
16205              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16206              rm.Encode(5, 0));
16207      return;
16208    }
16209  }
16210  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16211}
16212
16213void Assembler::vcvt(
16214    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16215  VIXL_ASSERT(AllowAssembler());
16216  CheckIT(cond);
16217  if (IsUsingT32()) {
16218    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
16219    if (dt1.Is(F32) && dt2.Is(F64)) {
16220      EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16221      AdvanceIT();
16222      return;
16223    }
16224    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16225    if (dt1.Is(U32) && dt2.Is(F64)) {
16226      EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16227      AdvanceIT();
16228      return;
16229    }
16230    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16231    if (dt1.Is(S32) && dt2.Is(F64)) {
16232      EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16233      AdvanceIT();
16234      return;
16235    }
16236  } else {
16237    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
16238    if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
16239      EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16240              rm.Encode(5, 0));
16241      return;
16242    }
16243    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16244    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16245      EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16246              rm.Encode(5, 0));
16247      return;
16248    }
16249    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16250    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16251      EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16252              rm.Encode(5, 0));
16253      return;
16254    }
16255  }
16256  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16257}
16258
16259void Assembler::vcvt(Condition cond,
16260                     DataType dt1,
16261                     DataType dt2,
16262                     DRegister rd,
16263                     DRegister rm,
16264                     int32_t fbits) {
16265  VIXL_ASSERT(AllowAssembler());
16266  CheckIT(cond);
16267  Dt_op_U_1 encoded_dt(dt1, dt2);
16268  Dt_U_sx_1 encoded_dt_2(dt2);
16269  Dt_U_sx_1 encoded_dt_3(dt1);
16270  if (IsUsingT32()) {
16271    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
16272    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16273      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16274        uint32_t fbits_ = 64 - fbits;
16275        EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16276                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16277                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16278        AdvanceIT();
16279        return;
16280      }
16281    }
16282    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
16283    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16284        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16285         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16286      unsigned offset = 32;
16287      if (dt2.Is(S16) || dt2.Is(U16)) {
16288        offset = 16;
16289      }
16290      uint32_t fbits_ = offset - fbits;
16291      EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16292                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16293                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16294                 ((fbits_ & 0x1e) >> 1));
16295      AdvanceIT();
16296      return;
16297    }
16298    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
16299    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16300        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16301         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16302      unsigned offset = 32;
16303      if (dt1.Is(S16) || dt1.Is(U16)) {
16304        offset = 16;
16305      }
16306      uint32_t fbits_ = offset - fbits;
16307      EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16308                 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16309                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16310                 ((fbits_ & 0x1e) >> 1));
16311      AdvanceIT();
16312      return;
16313    }
16314  } else {
16315    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
16316    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16317      if (cond.Is(al)) {
16318        uint32_t fbits_ = 64 - fbits;
16319        EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16320                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16321                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16322        return;
16323      }
16324    }
16325    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
16326    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16327        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16328         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16329        cond.IsNotNever()) {
16330      unsigned offset = 32;
16331      if (dt2.Is(S16) || dt2.Is(U16)) {
16332        offset = 16;
16333      }
16334      uint32_t fbits_ = offset - fbits;
16335      EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
16336              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16337              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16338              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16339              ((fbits_ & 0x1e) >> 1));
16340      return;
16341    }
16342    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
16343    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16344        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16345         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16346        cond.IsNotNever()) {
16347      unsigned offset = 32;
16348      if (dt1.Is(S16) || dt1.Is(U16)) {
16349        offset = 16;
16350      }
16351      uint32_t fbits_ = offset - fbits;
16352      EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
16353              ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16354              ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16355              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16356              ((fbits_ & 0x1e) >> 1));
16357      return;
16358    }
16359  }
16360  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16361}
16362
16363void Assembler::vcvt(Condition cond,
16364                     DataType dt1,
16365                     DataType dt2,
16366                     QRegister rd,
16367                     QRegister rm,
16368                     int32_t fbits) {
16369  VIXL_ASSERT(AllowAssembler());
16370  CheckIT(cond);
16371  Dt_op_U_1 encoded_dt(dt1, dt2);
16372  if (IsUsingT32()) {
16373    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
16374    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16375      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16376        uint32_t fbits_ = 64 - fbits;
16377        EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16378                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16379                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16380        AdvanceIT();
16381        return;
16382      }
16383    }
16384  } else {
16385    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
16386    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16387      if (cond.Is(al)) {
16388        uint32_t fbits_ = 64 - fbits;
16389        EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16390                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16391                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16392        return;
16393      }
16394    }
16395  }
16396  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16397}
16398
16399void Assembler::vcvt(Condition cond,
16400                     DataType dt1,
16401                     DataType dt2,
16402                     SRegister rd,
16403                     SRegister rm,
16404                     int32_t fbits) {
16405  VIXL_ASSERT(AllowAssembler());
16406  CheckIT(cond);
16407  Dt_U_sx_1 encoded_dt(dt2);
16408  Dt_U_sx_1 encoded_dt_2(dt1);
16409  if (IsUsingT32()) {
16410    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
16411    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16412        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16413         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16414      unsigned offset = 32;
16415      if (dt2.Is(S16) || dt2.Is(U16)) {
16416        offset = 16;
16417      }
16418      uint32_t fbits_ = offset - fbits;
16419      EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16420                 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16421                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16422                 ((fbits_ & 0x1e) >> 1));
16423      AdvanceIT();
16424      return;
16425    }
16426    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
16427    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16428        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16429         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16430      unsigned offset = 32;
16431      if (dt1.Is(S16) || dt1.Is(U16)) {
16432        offset = 16;
16433      }
16434      uint32_t fbits_ = offset - fbits;
16435      EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16436                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16437                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16438                 ((fbits_ & 0x1e) >> 1));
16439      AdvanceIT();
16440      return;
16441    }
16442  } else {
16443    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
16444    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16445        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16446         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16447        cond.IsNotNever()) {
16448      unsigned offset = 32;
16449      if (dt2.Is(S16) || dt2.Is(U16)) {
16450        offset = 16;
16451      }
16452      uint32_t fbits_ = offset - fbits;
16453      EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
16454              ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16455              ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16456              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16457              ((fbits_ & 0x1e) >> 1));
16458      return;
16459    }
16460    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
16461    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16462        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16463         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16464        cond.IsNotNever()) {
16465      unsigned offset = 32;
16466      if (dt1.Is(S16) || dt1.Is(U16)) {
16467        offset = 16;
16468      }
16469      uint32_t fbits_ = offset - fbits;
16470      EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
16471              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16472              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16473              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16474              ((fbits_ & 0x1e) >> 1));
16475      return;
16476    }
16477  }
16478  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16479}
16480
16481void Assembler::vcvt(
16482    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16483  VIXL_ASSERT(AllowAssembler());
16484  CheckIT(cond);
16485  Dt_op_1 encoded_dt(dt1, dt2);
16486  if (IsUsingT32()) {
16487    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
16488    if (encoded_dt.IsValid()) {
16489      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16490        EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
16491                   rd.Encode(22, 12) | rm.Encode(5, 0));
16492        AdvanceIT();
16493        return;
16494      }
16495    }
16496  } else {
16497    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
16498    if (encoded_dt.IsValid()) {
16499      if (cond.Is(al)) {
16500        EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
16501                rd.Encode(22, 12) | rm.Encode(5, 0));
16502        return;
16503      }
16504    }
16505  }
16506  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16507}
16508
16509void Assembler::vcvt(
16510    Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16511  VIXL_ASSERT(AllowAssembler());
16512  CheckIT(cond);
16513  Dt_op_1 encoded_dt(dt1, dt2);
16514  if (IsUsingT32()) {
16515    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
16516    if (encoded_dt.IsValid()) {
16517      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16518        EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
16519                   rd.Encode(22, 12) | rm.Encode(5, 0));
16520        AdvanceIT();
16521        return;
16522      }
16523    }
16524  } else {
16525    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
16526    if (encoded_dt.IsValid()) {
16527      if (cond.Is(al)) {
16528        EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
16529                rd.Encode(22, 12) | rm.Encode(5, 0));
16530        return;
16531      }
16532    }
16533  }
16534  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16535}
16536
16537void Assembler::vcvt(
16538    Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
16539  VIXL_ASSERT(AllowAssembler());
16540  CheckIT(cond);
16541  if (IsUsingT32()) {
16542    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
16543    if (dt1.Is(F16) && dt2.Is(F32)) {
16544      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16545        EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16546        AdvanceIT();
16547        return;
16548      }
16549    }
16550  } else {
16551    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
16552    if (dt1.Is(F16) && dt2.Is(F32)) {
16553      if (cond.Is(al)) {
16554        EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16555        return;
16556      }
16557    }
16558  }
16559  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16560}
16561
16562void Assembler::vcvt(
16563    Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
16564  VIXL_ASSERT(AllowAssembler());
16565  CheckIT(cond);
16566  if (IsUsingT32()) {
16567    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
16568    if (dt1.Is(F32) && dt2.Is(F16)) {
16569      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16570        EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16571        AdvanceIT();
16572        return;
16573      }
16574    }
16575  } else {
16576    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
16577    if (dt1.Is(F32) && dt2.Is(F16)) {
16578      if (cond.Is(al)) {
16579        EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16580        return;
16581      }
16582    }
16583  }
16584  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16585}
16586
16587void Assembler::vcvt(
16588    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16589  VIXL_ASSERT(AllowAssembler());
16590  CheckIT(cond);
16591  Dt_op_2 encoded_dt(dt2);
16592  if (IsUsingT32()) {
16593    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
16594    if (dt1.Is(U32) && dt2.Is(F32)) {
16595      EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16596      AdvanceIT();
16597      return;
16598    }
16599    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
16600    if (dt1.Is(S32) && dt2.Is(F32)) {
16601      EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16602      AdvanceIT();
16603      return;
16604    }
16605    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
16606    if (dt1.Is(F32) && encoded_dt.IsValid()) {
16607      EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
16608                 rd.Encode(22, 12) | rm.Encode(5, 0));
16609      AdvanceIT();
16610      return;
16611    }
16612  } else {
16613    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
16614    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
16615      EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16616              rm.Encode(5, 0));
16617      return;
16618    }
16619    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
16620    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
16621      EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16622              rm.Encode(5, 0));
16623      return;
16624    }
16625    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
16626    if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
16627      EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
16628              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16629              rm.Encode(5, 0));
16630      return;
16631    }
16632  }
16633  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16634}
16635
16636void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16637  VIXL_ASSERT(AllowAssembler());
16638  CheckIT(al);
16639  Dt_op_3 encoded_dt(dt1);
16640  if (IsUsingT32()) {
16641    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16642    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16643      EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
16644                 rd.Encode(22, 12) | rm.Encode(5, 0));
16645      AdvanceIT();
16646      return;
16647    }
16648  } else {
16649    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16650    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16651      EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
16652              rd.Encode(22, 12) | rm.Encode(5, 0));
16653      return;
16654    }
16655  }
16656  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16657}
16658
16659void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16660  VIXL_ASSERT(AllowAssembler());
16661  CheckIT(al);
16662  Dt_op_3 encoded_dt(dt1);
16663  if (IsUsingT32()) {
16664    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16665    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16666      EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
16667                 rd.Encode(22, 12) | rm.Encode(5, 0));
16668      AdvanceIT();
16669      return;
16670    }
16671  } else {
16672    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16673    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16674      EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
16675              rd.Encode(22, 12) | rm.Encode(5, 0));
16676      return;
16677    }
16678  }
16679  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16680}
16681
16682void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16683  VIXL_ASSERT(AllowAssembler());
16684  CheckIT(al);
16685  Dt_op_2 encoded_dt(dt1);
16686  if (IsUsingT32()) {
16687    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16688    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16689      EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16690                 rd.Encode(22, 12) | rm.Encode(5, 0));
16691      AdvanceIT();
16692      return;
16693    }
16694  } else {
16695    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16696    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16697      EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16698              rd.Encode(22, 12) | rm.Encode(5, 0));
16699      return;
16700    }
16701  }
16702  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16703}
16704
16705void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16706  VIXL_ASSERT(AllowAssembler());
16707  CheckIT(al);
16708  Dt_op_2 encoded_dt(dt1);
16709  if (IsUsingT32()) {
16710    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16711    if (encoded_dt.IsValid() && dt2.Is(F64)) {
16712      EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16713                 rd.Encode(22, 12) | rm.Encode(5, 0));
16714      AdvanceIT();
16715      return;
16716    }
16717  } else {
16718    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16719    if (encoded_dt.IsValid() && dt2.Is(F64)) {
16720      EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16721              rd.Encode(22, 12) | rm.Encode(5, 0));
16722      return;
16723    }
16724  }
16725  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16726}
16727
16728void Assembler::vcvtb(
16729    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16730  VIXL_ASSERT(AllowAssembler());
16731  CheckIT(cond);
16732  if (IsUsingT32()) {
16733    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16734    if (dt1.Is(F32) && dt2.Is(F16)) {
16735      EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16736      AdvanceIT();
16737      return;
16738    }
16739    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16740    if (dt1.Is(F16) && dt2.Is(F32)) {
16741      EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16742      AdvanceIT();
16743      return;
16744    }
16745  } else {
16746    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16747    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16748      EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16749              rm.Encode(5, 0));
16750      return;
16751    }
16752    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16753    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16754      EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16755              rm.Encode(5, 0));
16756      return;
16757    }
16758  }
16759  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16760}
16761
16762void Assembler::vcvtb(
16763    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
16764  VIXL_ASSERT(AllowAssembler());
16765  CheckIT(cond);
16766  if (IsUsingT32()) {
16767    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16768    if (dt1.Is(F64) && dt2.Is(F16)) {
16769      EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16770      AdvanceIT();
16771      return;
16772    }
16773  } else {
16774    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16775    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16776      EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16777              rm.Encode(5, 0));
16778      return;
16779    }
16780  }
16781  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16782}
16783
16784void Assembler::vcvtb(
16785    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16786  VIXL_ASSERT(AllowAssembler());
16787  CheckIT(cond);
16788  if (IsUsingT32()) {
16789    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16790    if (dt1.Is(F16) && dt2.Is(F64)) {
16791      EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16792      AdvanceIT();
16793      return;
16794    }
16795  } else {
16796    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16797    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16798      EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16799              rm.Encode(5, 0));
16800      return;
16801    }
16802  }
16803  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16804}
16805
16806void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16807  VIXL_ASSERT(AllowAssembler());
16808  CheckIT(al);
16809  Dt_op_3 encoded_dt(dt1);
16810  if (IsUsingT32()) {
16811    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16812    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16813      EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
16814                 rd.Encode(22, 12) | rm.Encode(5, 0));
16815      AdvanceIT();
16816      return;
16817    }
16818  } else {
16819    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16820    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16821      EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
16822              rd.Encode(22, 12) | rm.Encode(5, 0));
16823      return;
16824    }
16825  }
16826  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16827}
16828
16829void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16830  VIXL_ASSERT(AllowAssembler());
16831  CheckIT(al);
16832  Dt_op_3 encoded_dt(dt1);
16833  if (IsUsingT32()) {
16834    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16835    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16836      EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
16837                 rd.Encode(22, 12) | rm.Encode(5, 0));
16838      AdvanceIT();
16839      return;
16840    }
16841  } else {
16842    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16843    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16844      EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
16845              rd.Encode(22, 12) | rm.Encode(5, 0));
16846      return;
16847    }
16848  }
16849  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16850}
16851
16852void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16853  VIXL_ASSERT(AllowAssembler());
16854  CheckIT(al);
16855  Dt_op_2 encoded_dt(dt1);
16856  if (IsUsingT32()) {
16857    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16858    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16859      EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16860                 rd.Encode(22, 12) | rm.Encode(5, 0));
16861      AdvanceIT();
16862      return;
16863    }
16864  } else {
16865    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16866    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16867      EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16868              rd.Encode(22, 12) | rm.Encode(5, 0));
16869      return;
16870    }
16871  }
16872  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16873}
16874
16875void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16876  VIXL_ASSERT(AllowAssembler());
16877  CheckIT(al);
16878  Dt_op_2 encoded_dt(dt1);
16879  if (IsUsingT32()) {
16880    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16881    if (encoded_dt.IsValid() && dt2.Is(F64)) {
16882      EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16883                 rd.Encode(22, 12) | rm.Encode(5, 0));
16884      AdvanceIT();
16885      return;
16886    }
16887  } else {
16888    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16889    if (encoded_dt.IsValid() && dt2.Is(F64)) {
16890      EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16891              rd.Encode(22, 12) | rm.Encode(5, 0));
16892      return;
16893    }
16894  }
16895  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16896}
16897
16898void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16899  VIXL_ASSERT(AllowAssembler());
16900  CheckIT(al);
16901  Dt_op_3 encoded_dt(dt1);
16902  if (IsUsingT32()) {
16903    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16904    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16905      EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
16906                 rd.Encode(22, 12) | rm.Encode(5, 0));
16907      AdvanceIT();
16908      return;
16909    }
16910  } else {
16911    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16912    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16913      EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
16914              rd.Encode(22, 12) | rm.Encode(5, 0));
16915      return;
16916    }
16917  }
16918  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16919}
16920
16921void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
16922  VIXL_ASSERT(AllowAssembler());
16923  CheckIT(al);
16924  Dt_op_3 encoded_dt(dt1);
16925  if (IsUsingT32()) {
16926    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16927    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16928      EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
16929                 rd.Encode(22, 12) | rm.Encode(5, 0));
16930      AdvanceIT();
16931      return;
16932    }
16933  } else {
16934    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16935    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16936      EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
16937              rd.Encode(22, 12) | rm.Encode(5, 0));
16938      return;
16939    }
16940  }
16941  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16942}
16943
16944void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16945  VIXL_ASSERT(AllowAssembler());
16946  CheckIT(al);
16947  Dt_op_2 encoded_dt(dt1);
16948  if (IsUsingT32()) {
16949    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16950    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16951      EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16952                 rd.Encode(22, 12) | rm.Encode(5, 0));
16953      AdvanceIT();
16954      return;
16955    }
16956  } else {
16957    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16958    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16959      EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16960              rd.Encode(22, 12) | rm.Encode(5, 0));
16961      return;
16962    }
16963  }
16964  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16965}
16966
16967void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16968  VIXL_ASSERT(AllowAssembler());
16969  CheckIT(al);
16970  Dt_op_2 encoded_dt(dt1);
16971  if (IsUsingT32()) {
16972    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16973    if (encoded_dt.IsValid() && dt2.Is(F64)) {
16974      EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
16975                 rd.Encode(22, 12) | rm.Encode(5, 0));
16976      AdvanceIT();
16977      return;
16978    }
16979  } else {
16980    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16981    if (encoded_dt.IsValid() && dt2.Is(F64)) {
16982      EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
16983              rd.Encode(22, 12) | rm.Encode(5, 0));
16984      return;
16985    }
16986  }
16987  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16988}
16989
16990void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
16991  VIXL_ASSERT(AllowAssembler());
16992  CheckIT(al);
16993  Dt_op_3 encoded_dt(dt1);
16994  if (IsUsingT32()) {
16995    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16996    if (encoded_dt.IsValid() && dt2.Is(F32)) {
16997      EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
16998                 rd.Encode(22, 12) | rm.Encode(5, 0));
16999      AdvanceIT();
17000      return;
17001    }
17002  } else {
17003    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
17004    if (encoded_dt.IsValid() && dt2.Is(F32)) {
17005      EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
17006              rd.Encode(22, 12) | rm.Encode(5, 0));
17007      return;
17008    }
17009  }
17010  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17011}
17012
17013void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
17014  VIXL_ASSERT(AllowAssembler());
17015  CheckIT(al);
17016  Dt_op_3 encoded_dt(dt1);
17017  if (IsUsingT32()) {
17018    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
17019    if (encoded_dt.IsValid() && dt2.Is(F32)) {
17020      EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
17021                 rd.Encode(22, 12) | rm.Encode(5, 0));
17022      AdvanceIT();
17023      return;
17024    }
17025  } else {
17026    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
17027    if (encoded_dt.IsValid() && dt2.Is(F32)) {
17028      EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
17029              rd.Encode(22, 12) | rm.Encode(5, 0));
17030      return;
17031    }
17032  }
17033  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17034}
17035
17036void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
17037  VIXL_ASSERT(AllowAssembler());
17038  CheckIT(al);
17039  Dt_op_2 encoded_dt(dt1);
17040  if (IsUsingT32()) {
17041    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
17042    if (encoded_dt.IsValid() && dt2.Is(F32)) {
17043      EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17044                 rd.Encode(22, 12) | rm.Encode(5, 0));
17045      AdvanceIT();
17046      return;
17047    }
17048  } else {
17049    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17050    if (encoded_dt.IsValid() && dt2.Is(F32)) {
17051      EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17052              rd.Encode(22, 12) | rm.Encode(5, 0));
17053      return;
17054    }
17055  }
17056  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17057}
17058
17059void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17060  VIXL_ASSERT(AllowAssembler());
17061  CheckIT(al);
17062  Dt_op_2 encoded_dt(dt1);
17063  if (IsUsingT32()) {
17064    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17065    if (encoded_dt.IsValid() && dt2.Is(F64)) {
17066      EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17067                 rd.Encode(22, 12) | rm.Encode(5, 0));
17068      AdvanceIT();
17069      return;
17070    }
17071  } else {
17072    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17073    if (encoded_dt.IsValid() && dt2.Is(F64)) {
17074      EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17075              rd.Encode(22, 12) | rm.Encode(5, 0));
17076      return;
17077    }
17078  }
17079  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17080}
17081
17082void Assembler::vcvtr(
17083    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
17084  VIXL_ASSERT(AllowAssembler());
17085  CheckIT(cond);
17086  if (IsUsingT32()) {
17087    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
17088    if (dt1.Is(U32) && dt2.Is(F32)) {
17089      EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17090      AdvanceIT();
17091      return;
17092    }
17093    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
17094    if (dt1.Is(S32) && dt2.Is(F32)) {
17095      EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17096      AdvanceIT();
17097      return;
17098    }
17099  } else {
17100    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
17101    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
17102      EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17103              rm.Encode(5, 0));
17104      return;
17105    }
17106    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
17107    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
17108      EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17109              rm.Encode(5, 0));
17110      return;
17111    }
17112  }
17113  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17114}
17115
17116void Assembler::vcvtr(
17117    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17118  VIXL_ASSERT(AllowAssembler());
17119  CheckIT(cond);
17120  if (IsUsingT32()) {
17121    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
17122    if (dt1.Is(U32) && dt2.Is(F64)) {
17123      EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17124      AdvanceIT();
17125      return;
17126    }
17127    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
17128    if (dt1.Is(S32) && dt2.Is(F64)) {
17129      EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17130      AdvanceIT();
17131      return;
17132    }
17133  } else {
17134    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
17135    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
17136      EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17137              rm.Encode(5, 0));
17138      return;
17139    }
17140    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
17141    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
17142      EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17143              rm.Encode(5, 0));
17144      return;
17145    }
17146  }
17147  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17148}
17149
17150void Assembler::vcvtt(
17151    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
17152  VIXL_ASSERT(AllowAssembler());
17153  CheckIT(cond);
17154  if (IsUsingT32()) {
17155    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
17156    if (dt1.Is(F32) && dt2.Is(F16)) {
17157      EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17158      AdvanceIT();
17159      return;
17160    }
17161    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
17162    if (dt1.Is(F16) && dt2.Is(F32)) {
17163      EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17164      AdvanceIT();
17165      return;
17166    }
17167  } else {
17168    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
17169    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
17170      EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17171              rm.Encode(5, 0));
17172      return;
17173    }
17174    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
17175    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
17176      EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17177              rm.Encode(5, 0));
17178      return;
17179    }
17180  }
17181  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17182}
17183
17184void Assembler::vcvtt(
17185    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
17186  VIXL_ASSERT(AllowAssembler());
17187  CheckIT(cond);
17188  if (IsUsingT32()) {
17189    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
17190    if (dt1.Is(F64) && dt2.Is(F16)) {
17191      EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17192      AdvanceIT();
17193      return;
17194    }
17195  } else {
17196    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
17197    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
17198      EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17199              rm.Encode(5, 0));
17200      return;
17201    }
17202  }
17203  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17204}
17205
17206void Assembler::vcvtt(
17207    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
17208  VIXL_ASSERT(AllowAssembler());
17209  CheckIT(cond);
17210  if (IsUsingT32()) {
17211    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
17212    if (dt1.Is(F16) && dt2.Is(F64)) {
17213      EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17214      AdvanceIT();
17215      return;
17216    }
17217  } else {
17218    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
17219    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
17220      EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17221              rm.Encode(5, 0));
17222      return;
17223    }
17224  }
17225  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17226}
17227
17228void Assembler::vdiv(
17229    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17230  VIXL_ASSERT(AllowAssembler());
17231  CheckIT(cond);
17232  if (IsUsingT32()) {
17233    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
17234    if (dt.Is(F32)) {
17235      EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17236                 rm.Encode(5, 0));
17237      AdvanceIT();
17238      return;
17239    }
17240  } else {
17241    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
17242    if (dt.Is(F32) && cond.IsNotNever()) {
17243      EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17244              rn.Encode(7, 16) | rm.Encode(5, 0));
17245      return;
17246    }
17247  }
17248  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17249}
17250
17251void Assembler::vdiv(
17252    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17253  VIXL_ASSERT(AllowAssembler());
17254  CheckIT(cond);
17255  if (IsUsingT32()) {
17256    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
17257    if (dt.Is(F64)) {
17258      EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17259                 rm.Encode(5, 0));
17260      AdvanceIT();
17261      return;
17262    }
17263  } else {
17264    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
17265    if (dt.Is(F64) && cond.IsNotNever()) {
17266      EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17267              rn.Encode(7, 16) | rm.Encode(5, 0));
17268      return;
17269    }
17270  }
17271  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17272}
17273
17274void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
17275  VIXL_ASSERT(AllowAssembler());
17276  CheckIT(cond);
17277  Dt_B_E_1 encoded_dt(dt);
17278  if (IsUsingT32()) {
17279    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
17280    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
17281      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17282        EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17283                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17284                   rd.Encode(7, 16) | (rt.GetCode() << 12));
17285        AdvanceIT();
17286        return;
17287      }
17288    }
17289  } else {
17290    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
17291    if (encoded_dt.IsValid() && cond.IsNotNever() &&
17292        (!rt.IsPC() || AllowUnpredictable())) {
17293      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17294        EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
17295                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17296                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17297                rd.Encode(7, 16) | (rt.GetCode() << 12));
17298        return;
17299      }
17300    }
17301  }
17302  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17303}
17304
17305void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
17306  VIXL_ASSERT(AllowAssembler());
17307  CheckIT(cond);
17308  Dt_B_E_1 encoded_dt(dt);
17309  if (IsUsingT32()) {
17310    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
17311    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
17312      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17313        EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17314                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17315                   rd.Encode(7, 16) | (rt.GetCode() << 12));
17316        AdvanceIT();
17317        return;
17318      }
17319    }
17320  } else {
17321    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
17322    if (encoded_dt.IsValid() && cond.IsNotNever() &&
17323        (!rt.IsPC() || AllowUnpredictable())) {
17324      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17325        EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
17326                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17327                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17328                rd.Encode(7, 16) | (rt.GetCode() << 12));
17329        return;
17330      }
17331    }
17332  }
17333  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17334}
17335
17336void Assembler::vdup(Condition cond,
17337                     DataType dt,
17338                     DRegister rd,
17339                     DRegisterLane rm) {
17340  VIXL_ASSERT(AllowAssembler());
17341  CheckIT(cond);
17342  Dt_imm4_1 encoded_dt(dt, rm);
17343  if (IsUsingT32()) {
17344    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
17345    if (encoded_dt.IsValid()) {
17346      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17347        EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
17348                   rd.Encode(22, 12) | rm.Encode(5, 0));
17349        AdvanceIT();
17350        return;
17351      }
17352    }
17353  } else {
17354    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
17355    if (encoded_dt.IsValid()) {
17356      if (cond.Is(al)) {
17357        EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
17358                rd.Encode(22, 12) | rm.Encode(5, 0));
17359        return;
17360      }
17361    }
17362  }
17363  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17364}
17365
17366void Assembler::vdup(Condition cond,
17367                     DataType dt,
17368                     QRegister rd,
17369                     DRegisterLane rm) {
17370  VIXL_ASSERT(AllowAssembler());
17371  CheckIT(cond);
17372  Dt_imm4_1 encoded_dt(dt, rm);
17373  if (IsUsingT32()) {
17374    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
17375    if (encoded_dt.IsValid()) {
17376      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17377        EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
17378                   rd.Encode(22, 12) | rm.Encode(5, 0));
17379        AdvanceIT();
17380        return;
17381      }
17382    }
17383  } else {
17384    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
17385    if (encoded_dt.IsValid()) {
17386      if (cond.Is(al)) {
17387        EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
17388                rd.Encode(22, 12) | rm.Encode(5, 0));
17389        return;
17390      }
17391    }
17392  }
17393  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17394}
17395
17396void Assembler::veor(
17397    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17398  VIXL_ASSERT(AllowAssembler());
17399  CheckIT(cond);
17400  USE(dt);
17401  if (IsUsingT32()) {
17402    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
17403    if (cond.Is(al) || AllowStronglyDiscouraged()) {
17404      EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17405                 rm.Encode(5, 0));
17406      AdvanceIT();
17407      return;
17408    }
17409  } else {
17410    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
17411    if (cond.Is(al)) {
17412      EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17413              rm.Encode(5, 0));
17414      return;
17415    }
17416  }
17417  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17418}
17419
17420void Assembler::veor(
17421    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17422  VIXL_ASSERT(AllowAssembler());
17423  CheckIT(cond);
17424  USE(dt);
17425  if (IsUsingT32()) {
17426    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
17427    if (cond.Is(al) || AllowStronglyDiscouraged()) {
17428      EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17429                 rm.Encode(5, 0));
17430      AdvanceIT();
17431      return;
17432    }
17433  } else {
17434    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
17435    if (cond.Is(al)) {
17436      EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17437              rm.Encode(5, 0));
17438      return;
17439    }
17440  }
17441  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17442}
17443
17444void Assembler::vext(Condition cond,
17445                     DataType dt,
17446                     DRegister rd,
17447                     DRegister rn,
17448                     DRegister rm,
17449                     const DOperand& operand) {
17450  VIXL_ASSERT(AllowAssembler());
17451  CheckIT(cond);
17452  if (operand.IsImmediate()) {
17453    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17454      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
17455      if (IsUsingT32()) {
17456        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17457        if (dt.Is(Untyped8) && (imm <= 7)) {
17458          if (cond.Is(al) || AllowStronglyDiscouraged()) {
17459            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17460                       rm.Encode(5, 0) | (imm << 8));
17461            AdvanceIT();
17462            return;
17463          }
17464        }
17465        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17466        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17467            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17468          if (cond.Is(al) || AllowStronglyDiscouraged()) {
17469            uint32_t imm4 = imm / dt.GetSize();
17470            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17471                       rm.Encode(5, 0) | (imm4 << 8));
17472            AdvanceIT();
17473            return;
17474          }
17475        }
17476      } else {
17477        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17478        if (dt.Is(Untyped8) && (imm <= 7)) {
17479          if (cond.Is(al)) {
17480            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17481                    rm.Encode(5, 0) | (imm << 8));
17482            return;
17483          }
17484        }
17485        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17486        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17487            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17488          if (cond.Is(al)) {
17489            uint32_t imm4 = imm / dt.GetSize();
17490            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17491                    rm.Encode(5, 0) | (imm4 << 8));
17492            return;
17493          }
17494        }
17495      }
17496    }
17497  }
17498  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17499}
17500
17501void Assembler::vext(Condition cond,
17502                     DataType dt,
17503                     QRegister rd,
17504                     QRegister rn,
17505                     QRegister rm,
17506                     const QOperand& operand) {
17507  VIXL_ASSERT(AllowAssembler());
17508  CheckIT(cond);
17509  if (operand.IsImmediate()) {
17510    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17511      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
17512      if (IsUsingT32()) {
17513        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17514        if (dt.Is(Untyped8) && (imm <= 15)) {
17515          if (cond.Is(al) || AllowStronglyDiscouraged()) {
17516            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17517                       rm.Encode(5, 0) | (imm << 8));
17518            AdvanceIT();
17519            return;
17520          }
17521        }
17522        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17523        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17524            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17525          if (cond.Is(al) || AllowStronglyDiscouraged()) {
17526            uint32_t imm4 = imm / dt.GetSize();
17527            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17528                       rm.Encode(5, 0) | (imm4 << 8));
17529            AdvanceIT();
17530            return;
17531          }
17532        }
17533      } else {
17534        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17535        if (dt.Is(Untyped8) && (imm <= 15)) {
17536          if (cond.Is(al)) {
17537            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17538                    rm.Encode(5, 0) | (imm << 8));
17539            return;
17540          }
17541        }
17542        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17543        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17544            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17545          if (cond.Is(al)) {
17546            uint32_t imm4 = imm / dt.GetSize();
17547            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17548                    rm.Encode(5, 0) | (imm4 << 8));
17549            return;
17550          }
17551        }
17552      }
17553    }
17554  }
17555  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17556}
17557
17558void Assembler::vfma(
17559    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17560  VIXL_ASSERT(AllowAssembler());
17561  CheckIT(cond);
17562  if (IsUsingT32()) {
17563    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17564    if (dt.Is(F32)) {
17565      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17566        EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17567                   rm.Encode(5, 0));
17568        AdvanceIT();
17569        return;
17570      }
17571    }
17572    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17573    if (dt.Is(F64)) {
17574      EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17575                 rm.Encode(5, 0));
17576      AdvanceIT();
17577      return;
17578    }
17579  } else {
17580    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17581    if (dt.Is(F32)) {
17582      if (cond.Is(al)) {
17583        EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17584                rm.Encode(5, 0));
17585        return;
17586      }
17587    }
17588    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17589    if (dt.Is(F64) && cond.IsNotNever()) {
17590      EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17591              rn.Encode(7, 16) | rm.Encode(5, 0));
17592      return;
17593    }
17594  }
17595  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17596}
17597
17598void Assembler::vfma(
17599    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17600  VIXL_ASSERT(AllowAssembler());
17601  CheckIT(cond);
17602  if (IsUsingT32()) {
17603    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17604    if (dt.Is(F32)) {
17605      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17606        EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17607                   rm.Encode(5, 0));
17608        AdvanceIT();
17609        return;
17610      }
17611    }
17612  } else {
17613    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17614    if (dt.Is(F32)) {
17615      if (cond.Is(al)) {
17616        EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17617                rm.Encode(5, 0));
17618        return;
17619      }
17620    }
17621  }
17622  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17623}
17624
17625void Assembler::vfma(
17626    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17627  VIXL_ASSERT(AllowAssembler());
17628  CheckIT(cond);
17629  if (IsUsingT32()) {
17630    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17631    if (dt.Is(F32)) {
17632      EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17633                 rm.Encode(5, 0));
17634      AdvanceIT();
17635      return;
17636    }
17637  } else {
17638    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17639    if (dt.Is(F32) && cond.IsNotNever()) {
17640      EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17641              rn.Encode(7, 16) | rm.Encode(5, 0));
17642      return;
17643    }
17644  }
17645  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17646}
17647
17648void Assembler::vfms(
17649    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17650  VIXL_ASSERT(AllowAssembler());
17651  CheckIT(cond);
17652  if (IsUsingT32()) {
17653    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17654    if (dt.Is(F32)) {
17655      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17656        EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17657                   rm.Encode(5, 0));
17658        AdvanceIT();
17659        return;
17660      }
17661    }
17662    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17663    if (dt.Is(F64)) {
17664      EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17665                 rm.Encode(5, 0));
17666      AdvanceIT();
17667      return;
17668    }
17669  } else {
17670    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17671    if (dt.Is(F32)) {
17672      if (cond.Is(al)) {
17673        EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17674                rm.Encode(5, 0));
17675        return;
17676      }
17677    }
17678    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17679    if (dt.Is(F64) && cond.IsNotNever()) {
17680      EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17681              rn.Encode(7, 16) | rm.Encode(5, 0));
17682      return;
17683    }
17684  }
17685  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17686}
17687
17688void Assembler::vfms(
17689    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17690  VIXL_ASSERT(AllowAssembler());
17691  CheckIT(cond);
17692  if (IsUsingT32()) {
17693    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17694    if (dt.Is(F32)) {
17695      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17696        EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17697                   rm.Encode(5, 0));
17698        AdvanceIT();
17699        return;
17700      }
17701    }
17702  } else {
17703    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17704    if (dt.Is(F32)) {
17705      if (cond.Is(al)) {
17706        EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17707                rm.Encode(5, 0));
17708        return;
17709      }
17710    }
17711  }
17712  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17713}
17714
17715void Assembler::vfms(
17716    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17717  VIXL_ASSERT(AllowAssembler());
17718  CheckIT(cond);
17719  if (IsUsingT32()) {
17720    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17721    if (dt.Is(F32)) {
17722      EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17723                 rm.Encode(5, 0));
17724      AdvanceIT();
17725      return;
17726    }
17727  } else {
17728    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17729    if (dt.Is(F32) && cond.IsNotNever()) {
17730      EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17731              rn.Encode(7, 16) | rm.Encode(5, 0));
17732      return;
17733    }
17734  }
17735  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17736}
17737
17738void Assembler::vfnma(
17739    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17740  VIXL_ASSERT(AllowAssembler());
17741  CheckIT(cond);
17742  if (IsUsingT32()) {
17743    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17744    if (dt.Is(F32)) {
17745      EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17746                 rm.Encode(5, 0));
17747      AdvanceIT();
17748      return;
17749    }
17750  } else {
17751    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17752    if (dt.Is(F32) && cond.IsNotNever()) {
17753      EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17754              rn.Encode(7, 16) | rm.Encode(5, 0));
17755      return;
17756    }
17757  }
17758  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17759}
17760
17761void Assembler::vfnma(
17762    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17763  VIXL_ASSERT(AllowAssembler());
17764  CheckIT(cond);
17765  if (IsUsingT32()) {
17766    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17767    if (dt.Is(F64)) {
17768      EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17769                 rm.Encode(5, 0));
17770      AdvanceIT();
17771      return;
17772    }
17773  } else {
17774    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17775    if (dt.Is(F64) && cond.IsNotNever()) {
17776      EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17777              rn.Encode(7, 16) | rm.Encode(5, 0));
17778      return;
17779    }
17780  }
17781  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17782}
17783
17784void Assembler::vfnms(
17785    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
17786  VIXL_ASSERT(AllowAssembler());
17787  CheckIT(cond);
17788  if (IsUsingT32()) {
17789    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17790    if (dt.Is(F32)) {
17791      EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17792                 rm.Encode(5, 0));
17793      AdvanceIT();
17794      return;
17795    }
17796  } else {
17797    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17798    if (dt.Is(F32) && cond.IsNotNever()) {
17799      EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17800              rn.Encode(7, 16) | rm.Encode(5, 0));
17801      return;
17802    }
17803  }
17804  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17805}
17806
17807void Assembler::vfnms(
17808    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17809  VIXL_ASSERT(AllowAssembler());
17810  CheckIT(cond);
17811  if (IsUsingT32()) {
17812    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17813    if (dt.Is(F64)) {
17814      EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17815                 rm.Encode(5, 0));
17816      AdvanceIT();
17817      return;
17818    }
17819  } else {
17820    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17821    if (dt.Is(F64) && cond.IsNotNever()) {
17822      EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17823              rn.Encode(7, 16) | rm.Encode(5, 0));
17824      return;
17825    }
17826  }
17827  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17828}
17829
17830void Assembler::vhadd(
17831    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17832  VIXL_ASSERT(AllowAssembler());
17833  CheckIT(cond);
17834  Dt_U_size_1 encoded_dt(dt);
17835  if (IsUsingT32()) {
17836    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17837    if (encoded_dt.IsValid()) {
17838      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17839        EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17840                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17841                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17842        AdvanceIT();
17843        return;
17844      }
17845    }
17846  } else {
17847    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17848    if (encoded_dt.IsValid()) {
17849      if (cond.Is(al)) {
17850        EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17851                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17852                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17853        return;
17854      }
17855    }
17856  }
17857  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17858}
17859
17860void Assembler::vhadd(
17861    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17862  VIXL_ASSERT(AllowAssembler());
17863  CheckIT(cond);
17864  Dt_U_size_1 encoded_dt(dt);
17865  if (IsUsingT32()) {
17866    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17867    if (encoded_dt.IsValid()) {
17868      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17869        EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17870                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17871                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17872        AdvanceIT();
17873        return;
17874      }
17875    }
17876  } else {
17877    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17878    if (encoded_dt.IsValid()) {
17879      if (cond.Is(al)) {
17880        EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17881                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17882                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17883        return;
17884      }
17885    }
17886  }
17887  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17888}
17889
17890void Assembler::vhsub(
17891    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
17892  VIXL_ASSERT(AllowAssembler());
17893  CheckIT(cond);
17894  Dt_U_size_1 encoded_dt(dt);
17895  if (IsUsingT32()) {
17896    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17897    if (encoded_dt.IsValid()) {
17898      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17899        EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17900                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17901                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17902        AdvanceIT();
17903        return;
17904      }
17905    }
17906  } else {
17907    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17908    if (encoded_dt.IsValid()) {
17909      if (cond.Is(al)) {
17910        EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17911                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17912                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17913        return;
17914      }
17915    }
17916  }
17917  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17918}
17919
17920void Assembler::vhsub(
17921    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
17922  VIXL_ASSERT(AllowAssembler());
17923  CheckIT(cond);
17924  Dt_U_size_1 encoded_dt(dt);
17925  if (IsUsingT32()) {
17926    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17927    if (encoded_dt.IsValid()) {
17928      if (cond.Is(al) || AllowStronglyDiscouraged()) {
17929        EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17930                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17931                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17932        AdvanceIT();
17933        return;
17934      }
17935    }
17936  } else {
17937    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17938    if (encoded_dt.IsValid()) {
17939      if (cond.Is(al)) {
17940        EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17941                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17942                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17943        return;
17944      }
17945    }
17946  }
17947  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17948}
17949
17950void Assembler::vld1(Condition cond,
17951                     DataType dt,
17952                     const NeonRegisterList& nreglist,
17953                     const AlignedMemOperand& operand) {
17954  VIXL_ASSERT(AllowAssembler());
17955  CheckIT(cond);
17956  if (operand.IsImmediateZero()) {
17957    Register rn = operand.GetBaseRegister();
17958    Alignment align = operand.GetAlignment();
17959    Dt_size_6 encoded_dt(dt);
17960    Dt_size_7 encoded_dt_2(dt);
17961    Align_align_1 encoded_align_1(align, nreglist);
17962    Align_a_1 encoded_align_2(align, dt);
17963    Align_index_align_1 encoded_align_3(align, nreglist, dt);
17964    if (IsUsingT32()) {
17965      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17966      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17967          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17968          operand.IsOffset() && encoded_align_1.IsValid() &&
17969          (!rn.IsPC() || AllowUnpredictable())) {
17970        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17971          const DRegister& first = nreglist.GetFirstDRegister();
17972          uint32_t len_encoding;
17973          switch (nreglist.GetLength()) {
17974            default:
17975              VIXL_UNREACHABLE_OR_FALLTHROUGH();
17976            case 1:
17977              len_encoding = 0x7;
17978              break;
17979            case 2:
17980              len_encoding = 0xa;
17981              break;
17982            case 3:
17983              len_encoding = 0x6;
17984              break;
17985            case 4:
17986              len_encoding = 0x2;
17987              break;
17988          }
17989          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17990                     (encoded_align_1.GetEncodingValue() << 4) |
17991                     first.Encode(22, 12) | (len_encoding << 8) |
17992                     (rn.GetCode() << 16));
17993          AdvanceIT();
17994          return;
17995        }
17996      }
17997      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17998      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17999          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18000          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18001          (!rn.IsPC() || AllowUnpredictable())) {
18002        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18003          const DRegister& first = nreglist.GetFirstDRegister();
18004          uint32_t len_encoding;
18005          switch (nreglist.GetLength()) {
18006            default:
18007              VIXL_UNREACHABLE_OR_FALLTHROUGH();
18008            case 1:
18009              len_encoding = 0x7;
18010              break;
18011            case 2:
18012              len_encoding = 0xa;
18013              break;
18014            case 3:
18015              len_encoding = 0x6;
18016              break;
18017            case 4:
18018              len_encoding = 0x2;
18019              break;
18020          }
18021          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18022                     (encoded_align_1.GetEncodingValue() << 4) |
18023                     first.Encode(22, 12) | (len_encoding << 8) |
18024                     (rn.GetCode() << 16));
18025          AdvanceIT();
18026          return;
18027        }
18028      }
18029      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18030      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18031          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18032          operand.IsOffset() && encoded_align_2.IsValid() &&
18033          (!rn.IsPC() || AllowUnpredictable())) {
18034        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18035          const DRegister& first = nreglist.GetFirstDRegister();
18036          uint32_t len_encoding = nreglist.GetLength() - 1;
18037          EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18038                     (encoded_align_2.GetEncodingValue() << 4) |
18039                     first.Encode(22, 12) | (len_encoding << 5) |
18040                     (rn.GetCode() << 16));
18041          AdvanceIT();
18042          return;
18043        }
18044      }
18045      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18046      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18047          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18048          operand.IsPostIndex() && encoded_align_2.IsValid() &&
18049          (!rn.IsPC() || AllowUnpredictable())) {
18050        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18051          const DRegister& first = nreglist.GetFirstDRegister();
18052          uint32_t len_encoding = nreglist.GetLength() - 1;
18053          EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18054                     (encoded_align_2.GetEncodingValue() << 4) |
18055                     first.Encode(22, 12) | (len_encoding << 5) |
18056                     (rn.GetCode() << 16));
18057          AdvanceIT();
18058          return;
18059        }
18060      }
18061      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18062      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18063          (nreglist.GetLength() == 1) && operand.IsOffset() &&
18064          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18065        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18066          const DRegister& first = nreglist.GetFirstDRegister();
18067          EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18068                     (encoded_align_3.GetEncodingValue() << 4) |
18069                     first.Encode(22, 12) | (rn.GetCode() << 16));
18070          AdvanceIT();
18071          return;
18072        }
18073      }
18074      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18075      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18076          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
18077          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18078        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18079          const DRegister& first = nreglist.GetFirstDRegister();
18080          EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18081                     (encoded_align_3.GetEncodingValue() << 4) |
18082                     first.Encode(22, 12) | (rn.GetCode() << 16));
18083          AdvanceIT();
18084          return;
18085        }
18086      }
18087    } else {
18088      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18089      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18090          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18091          operand.IsOffset() && encoded_align_1.IsValid() &&
18092          (!rn.IsPC() || AllowUnpredictable())) {
18093        if (cond.Is(al)) {
18094          const DRegister& first = nreglist.GetFirstDRegister();
18095          uint32_t len_encoding;
18096          switch (nreglist.GetLength()) {
18097            default:
18098              VIXL_UNREACHABLE_OR_FALLTHROUGH();
18099            case 1:
18100              len_encoding = 0x7;
18101              break;
18102            case 2:
18103              len_encoding = 0xa;
18104              break;
18105            case 3:
18106              len_encoding = 0x6;
18107              break;
18108            case 4:
18109              len_encoding = 0x2;
18110              break;
18111          }
18112          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18113                  (encoded_align_1.GetEncodingValue() << 4) |
18114                  first.Encode(22, 12) | (len_encoding << 8) |
18115                  (rn.GetCode() << 16));
18116          return;
18117        }
18118      }
18119      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18120      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18121          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18122          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18123          (!rn.IsPC() || AllowUnpredictable())) {
18124        if (cond.Is(al)) {
18125          const DRegister& first = nreglist.GetFirstDRegister();
18126          uint32_t len_encoding;
18127          switch (nreglist.GetLength()) {
18128            default:
18129              VIXL_UNREACHABLE_OR_FALLTHROUGH();
18130            case 1:
18131              len_encoding = 0x7;
18132              break;
18133            case 2:
18134              len_encoding = 0xa;
18135              break;
18136            case 3:
18137              len_encoding = 0x6;
18138              break;
18139            case 4:
18140              len_encoding = 0x2;
18141              break;
18142          }
18143          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18144                  (encoded_align_1.GetEncodingValue() << 4) |
18145                  first.Encode(22, 12) | (len_encoding << 8) |
18146                  (rn.GetCode() << 16));
18147          return;
18148        }
18149      }
18150      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18151      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18152          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18153          operand.IsOffset() && encoded_align_2.IsValid() &&
18154          (!rn.IsPC() || AllowUnpredictable())) {
18155        if (cond.Is(al)) {
18156          const DRegister& first = nreglist.GetFirstDRegister();
18157          uint32_t len_encoding = nreglist.GetLength() - 1;
18158          EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18159                  (encoded_align_2.GetEncodingValue() << 4) |
18160                  first.Encode(22, 12) | (len_encoding << 5) |
18161                  (rn.GetCode() << 16));
18162          return;
18163        }
18164      }
18165      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18166      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18167          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18168          operand.IsPostIndex() && encoded_align_2.IsValid() &&
18169          (!rn.IsPC() || AllowUnpredictable())) {
18170        if (cond.Is(al)) {
18171          const DRegister& first = nreglist.GetFirstDRegister();
18172          uint32_t len_encoding = nreglist.GetLength() - 1;
18173          EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18174                  (encoded_align_2.GetEncodingValue() << 4) |
18175                  first.Encode(22, 12) | (len_encoding << 5) |
18176                  (rn.GetCode() << 16));
18177          return;
18178        }
18179      }
18180      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18181      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18182          (nreglist.GetLength() == 1) && operand.IsOffset() &&
18183          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18184        if (cond.Is(al)) {
18185          const DRegister& first = nreglist.GetFirstDRegister();
18186          EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18187                  (encoded_align_3.GetEncodingValue() << 4) |
18188                  first.Encode(22, 12) | (rn.GetCode() << 16));
18189          return;
18190        }
18191      }
18192      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18193      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18194          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
18195          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
18196        if (cond.Is(al)) {
18197          const DRegister& first = nreglist.GetFirstDRegister();
18198          EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18199                  (encoded_align_3.GetEncodingValue() << 4) |
18200                  first.Encode(22, 12) | (rn.GetCode() << 16));
18201          return;
18202        }
18203      }
18204    }
18205  }
18206  if (operand.IsPlainRegister()) {
18207    Register rn = operand.GetBaseRegister();
18208    Alignment align = operand.GetAlignment();
18209    Register rm = operand.GetOffsetRegister();
18210    Dt_size_6 encoded_dt(dt);
18211    Dt_size_7 encoded_dt_2(dt);
18212    Align_align_1 encoded_align_1(align, nreglist);
18213    Align_a_1 encoded_align_2(align, dt);
18214    Align_index_align_1 encoded_align_3(align, nreglist, dt);
18215    if (IsUsingT32()) {
18216      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18217      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18218          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18219          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18220        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18221          const DRegister& first = nreglist.GetFirstDRegister();
18222          uint32_t len_encoding;
18223          switch (nreglist.GetLength()) {
18224            default:
18225              VIXL_UNREACHABLE_OR_FALLTHROUGH();
18226            case 1:
18227              len_encoding = 0x7;
18228              break;
18229            case 2:
18230              len_encoding = 0xa;
18231              break;
18232            case 3:
18233              len_encoding = 0x6;
18234              break;
18235            case 4:
18236              len_encoding = 0x2;
18237              break;
18238          }
18239          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18240                     (encoded_align_1.GetEncodingValue() << 4) |
18241                     first.Encode(22, 12) | (len_encoding << 8) |
18242                     (rn.GetCode() << 16) | rm.GetCode());
18243          AdvanceIT();
18244          return;
18245        }
18246      }
18247      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18248      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18249          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18250          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18251        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18252          const DRegister& first = nreglist.GetFirstDRegister();
18253          uint32_t len_encoding = nreglist.GetLength() - 1;
18254          EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18255                     (encoded_align_2.GetEncodingValue() << 4) |
18256                     first.Encode(22, 12) | (len_encoding << 5) |
18257                     (rn.GetCode() << 16) | rm.GetCode());
18258          AdvanceIT();
18259          return;
18260        }
18261      }
18262      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18263      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18264          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18265          (!rn.IsPC() || AllowUnpredictable())) {
18266        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18267          const DRegister& first = nreglist.GetFirstDRegister();
18268          EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18269                     (encoded_align_3.GetEncodingValue() << 4) |
18270                     first.Encode(22, 12) | (rn.GetCode() << 16) |
18271                     rm.GetCode());
18272          AdvanceIT();
18273          return;
18274        }
18275      }
18276    } else {
18277      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18278      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18279          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
18280          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18281        if (cond.Is(al)) {
18282          const DRegister& first = nreglist.GetFirstDRegister();
18283          uint32_t len_encoding;
18284          switch (nreglist.GetLength()) {
18285            default:
18286              VIXL_UNREACHABLE_OR_FALLTHROUGH();
18287            case 1:
18288              len_encoding = 0x7;
18289              break;
18290            case 2:
18291              len_encoding = 0xa;
18292              break;
18293            case 3:
18294              len_encoding = 0x6;
18295              break;
18296            case 4:
18297              len_encoding = 0x2;
18298              break;
18299          }
18300          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18301                  (encoded_align_1.GetEncodingValue() << 4) |
18302                  first.Encode(22, 12) | (len_encoding << 8) |
18303                  (rn.GetCode() << 16) | rm.GetCode());
18304          return;
18305        }
18306      }
18307      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18308      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18309          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
18310          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18311        if (cond.Is(al)) {
18312          const DRegister& first = nreglist.GetFirstDRegister();
18313          uint32_t len_encoding = nreglist.GetLength() - 1;
18314          EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18315                  (encoded_align_2.GetEncodingValue() << 4) |
18316                  first.Encode(22, 12) | (len_encoding << 5) |
18317                  (rn.GetCode() << 16) | rm.GetCode());
18318          return;
18319        }
18320      }
18321      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18322      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
18323          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18324          (!rn.IsPC() || AllowUnpredictable())) {
18325        if (cond.Is(al)) {
18326          const DRegister& first = nreglist.GetFirstDRegister();
18327          EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18328                  (encoded_align_3.GetEncodingValue() << 4) |
18329                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18330          return;
18331        }
18332      }
18333    }
18334  }
18335  Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
18336}
18337
18338void Assembler::vld2(Condition cond,
18339                     DataType dt,
18340                     const NeonRegisterList& nreglist,
18341                     const AlignedMemOperand& operand) {
18342  VIXL_ASSERT(AllowAssembler());
18343  CheckIT(cond);
18344  if (operand.IsImmediateZero()) {
18345    Register rn = operand.GetBaseRegister();
18346    Alignment align = operand.GetAlignment();
18347    Dt_size_7 encoded_dt(dt);
18348    Align_align_2 encoded_align_1(align, nreglist);
18349    Align_a_2 encoded_align_2(align, dt);
18350    Align_index_align_2 encoded_align_3(align, nreglist, dt);
18351    if (IsUsingT32()) {
18352      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18353      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18354          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18355           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18356           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18357          operand.IsOffset() && encoded_align_1.IsValid() &&
18358          (!rn.IsPC() || AllowUnpredictable())) {
18359        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18360          const DRegister& first = nreglist.GetFirstDRegister();
18361          uint32_t len_encoding;
18362          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18363            len_encoding = 0x8;
18364          }
18365          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18366            len_encoding = 0x9;
18367          }
18368          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18369            len_encoding = 0x3;
18370          }
18371          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18372                     (encoded_align_1.GetEncodingValue() << 4) |
18373                     first.Encode(22, 12) | (len_encoding << 8) |
18374                     (rn.GetCode() << 16));
18375          AdvanceIT();
18376          return;
18377        }
18378      }
18379      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18380      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18381          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18382           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18383           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18384          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18385          (!rn.IsPC() || AllowUnpredictable())) {
18386        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18387          const DRegister& first = nreglist.GetFirstDRegister();
18388          uint32_t len_encoding;
18389          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18390            len_encoding = 0x8;
18391          }
18392          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18393            len_encoding = 0x9;
18394          }
18395          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18396            len_encoding = 0x3;
18397          }
18398          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18399                     (encoded_align_1.GetEncodingValue() << 4) |
18400                     first.Encode(22, 12) | (len_encoding << 8) |
18401                     (rn.GetCode() << 16));
18402          AdvanceIT();
18403          return;
18404        }
18405      }
18406      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18407      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18408          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18409           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18410          operand.IsOffset() && encoded_align_2.IsValid() &&
18411          (!rn.IsPC() || AllowUnpredictable())) {
18412        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18413          const DRegister& first = nreglist.GetFirstDRegister();
18414          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18415          EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18416                     (encoded_align_2.GetEncodingValue() << 4) |
18417                     first.Encode(22, 12) | (len_encoding << 5) |
18418                     (rn.GetCode() << 16));
18419          AdvanceIT();
18420          return;
18421        }
18422      }
18423      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18424      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18425          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18426           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18427          operand.IsPostIndex() && encoded_align_2.IsValid() &&
18428          (!rn.IsPC() || AllowUnpredictable())) {
18429        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18430          const DRegister& first = nreglist.GetFirstDRegister();
18431          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18432          EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18433                     (encoded_align_2.GetEncodingValue() << 4) |
18434                     first.Encode(22, 12) | (len_encoding << 5) |
18435                     (rn.GetCode() << 16));
18436          AdvanceIT();
18437          return;
18438        }
18439      }
18440      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18441      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18442          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18443           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18444          operand.IsOffset() && encoded_align_3.IsValid() &&
18445          (!rn.IsPC() || AllowUnpredictable())) {
18446        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18447          const DRegister& first = nreglist.GetFirstDRegister();
18448          EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18449                     (encoded_align_3.GetEncodingValue() << 4) |
18450                     first.Encode(22, 12) | (rn.GetCode() << 16));
18451          AdvanceIT();
18452          return;
18453        }
18454      }
18455      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18456      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18457          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18458           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18459          operand.IsPostIndex() && encoded_align_3.IsValid() &&
18460          (!rn.IsPC() || AllowUnpredictable())) {
18461        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18462          const DRegister& first = nreglist.GetFirstDRegister();
18463          EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18464                     (encoded_align_3.GetEncodingValue() << 4) |
18465                     first.Encode(22, 12) | (rn.GetCode() << 16));
18466          AdvanceIT();
18467          return;
18468        }
18469      }
18470    } else {
18471      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18472      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18473          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18474           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18475           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18476          operand.IsOffset() && encoded_align_1.IsValid() &&
18477          (!rn.IsPC() || AllowUnpredictable())) {
18478        if (cond.Is(al)) {
18479          const DRegister& first = nreglist.GetFirstDRegister();
18480          uint32_t len_encoding;
18481          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18482            len_encoding = 0x8;
18483          }
18484          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18485            len_encoding = 0x9;
18486          }
18487          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18488            len_encoding = 0x3;
18489          }
18490          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18491                  (encoded_align_1.GetEncodingValue() << 4) |
18492                  first.Encode(22, 12) | (len_encoding << 8) |
18493                  (rn.GetCode() << 16));
18494          return;
18495        }
18496      }
18497      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18498      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18499          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18500           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18501           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18502          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18503          (!rn.IsPC() || AllowUnpredictable())) {
18504        if (cond.Is(al)) {
18505          const DRegister& first = nreglist.GetFirstDRegister();
18506          uint32_t len_encoding;
18507          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18508            len_encoding = 0x8;
18509          }
18510          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18511            len_encoding = 0x9;
18512          }
18513          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18514            len_encoding = 0x3;
18515          }
18516          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18517                  (encoded_align_1.GetEncodingValue() << 4) |
18518                  first.Encode(22, 12) | (len_encoding << 8) |
18519                  (rn.GetCode() << 16));
18520          return;
18521        }
18522      }
18523      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18524      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18525          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18526           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18527          operand.IsOffset() && encoded_align_2.IsValid() &&
18528          (!rn.IsPC() || AllowUnpredictable())) {
18529        if (cond.Is(al)) {
18530          const DRegister& first = nreglist.GetFirstDRegister();
18531          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18532          EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18533                  (encoded_align_2.GetEncodingValue() << 4) |
18534                  first.Encode(22, 12) | (len_encoding << 5) |
18535                  (rn.GetCode() << 16));
18536          return;
18537        }
18538      }
18539      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18540      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18541          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18542           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18543          operand.IsPostIndex() && encoded_align_2.IsValid() &&
18544          (!rn.IsPC() || AllowUnpredictable())) {
18545        if (cond.Is(al)) {
18546          const DRegister& first = nreglist.GetFirstDRegister();
18547          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18548          EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18549                  (encoded_align_2.GetEncodingValue() << 4) |
18550                  first.Encode(22, 12) | (len_encoding << 5) |
18551                  (rn.GetCode() << 16));
18552          return;
18553        }
18554      }
18555      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18556      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18557          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18558           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18559          operand.IsOffset() && encoded_align_3.IsValid() &&
18560          (!rn.IsPC() || AllowUnpredictable())) {
18561        if (cond.Is(al)) {
18562          const DRegister& first = nreglist.GetFirstDRegister();
18563          EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18564                  (encoded_align_3.GetEncodingValue() << 4) |
18565                  first.Encode(22, 12) | (rn.GetCode() << 16));
18566          return;
18567        }
18568      }
18569      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18570      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18571          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18572           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18573          operand.IsPostIndex() && encoded_align_3.IsValid() &&
18574          (!rn.IsPC() || AllowUnpredictable())) {
18575        if (cond.Is(al)) {
18576          const DRegister& first = nreglist.GetFirstDRegister();
18577          EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18578                  (encoded_align_3.GetEncodingValue() << 4) |
18579                  first.Encode(22, 12) | (rn.GetCode() << 16));
18580          return;
18581        }
18582      }
18583    }
18584  }
18585  if (operand.IsPlainRegister()) {
18586    Register rn = operand.GetBaseRegister();
18587    Alignment align = operand.GetAlignment();
18588    Register rm = operand.GetOffsetRegister();
18589    Dt_size_7 encoded_dt(dt);
18590    Align_align_2 encoded_align_1(align, nreglist);
18591    Align_a_2 encoded_align_2(align, dt);
18592    Align_index_align_2 encoded_align_3(align, nreglist, dt);
18593    if (IsUsingT32()) {
18594      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18595      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18596          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18597           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18598           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18599          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18600        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18601          const DRegister& first = nreglist.GetFirstDRegister();
18602          uint32_t len_encoding;
18603          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18604            len_encoding = 0x8;
18605          }
18606          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18607            len_encoding = 0x9;
18608          }
18609          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18610            len_encoding = 0x3;
18611          }
18612          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18613                     (encoded_align_1.GetEncodingValue() << 4) |
18614                     first.Encode(22, 12) | (len_encoding << 8) |
18615                     (rn.GetCode() << 16) | rm.GetCode());
18616          AdvanceIT();
18617          return;
18618        }
18619      }
18620      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18621      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18622          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18623           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18624          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18625        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18626          const DRegister& first = nreglist.GetFirstDRegister();
18627          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18628          EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18629                     (encoded_align_2.GetEncodingValue() << 4) |
18630                     first.Encode(22, 12) | (len_encoding << 5) |
18631                     (rn.GetCode() << 16) | rm.GetCode());
18632          AdvanceIT();
18633          return;
18634        }
18635      }
18636      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18637      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18638          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18639           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18640          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18641        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18642          const DRegister& first = nreglist.GetFirstDRegister();
18643          EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
18644                     (encoded_align_3.GetEncodingValue() << 4) |
18645                     first.Encode(22, 12) | (rn.GetCode() << 16) |
18646                     rm.GetCode());
18647          AdvanceIT();
18648          return;
18649        }
18650      }
18651    } else {
18652      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18653      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18654          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18655           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18656           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
18657          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18658        if (cond.Is(al)) {
18659          const DRegister& first = nreglist.GetFirstDRegister();
18660          uint32_t len_encoding;
18661          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18662            len_encoding = 0x8;
18663          }
18664          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18665            len_encoding = 0x9;
18666          }
18667          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18668            len_encoding = 0x3;
18669          }
18670          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18671                  (encoded_align_1.GetEncodingValue() << 4) |
18672                  first.Encode(22, 12) | (len_encoding << 8) |
18673                  (rn.GetCode() << 16) | rm.GetCode());
18674          return;
18675        }
18676      }
18677      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18678      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18679          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18680           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18681          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18682        if (cond.Is(al)) {
18683          const DRegister& first = nreglist.GetFirstDRegister();
18684          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18685          EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18686                  (encoded_align_2.GetEncodingValue() << 4) |
18687                  first.Encode(22, 12) | (len_encoding << 5) |
18688                  (rn.GetCode() << 16) | rm.GetCode());
18689          return;
18690        }
18691      }
18692      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18693      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18694          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18695           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
18696          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18697        if (cond.Is(al)) {
18698          const DRegister& first = nreglist.GetFirstDRegister();
18699          EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
18700                  (encoded_align_3.GetEncodingValue() << 4) |
18701                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18702          return;
18703        }
18704      }
18705    }
18706  }
18707  Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
18708}
18709
18710void Assembler::vld3(Condition cond,
18711                     DataType dt,
18712                     const NeonRegisterList& nreglist,
18713                     const AlignedMemOperand& operand) {
18714  VIXL_ASSERT(AllowAssembler());
18715  CheckIT(cond);
18716  if (operand.IsImmediateZero()) {
18717    Register rn = operand.GetBaseRegister();
18718    Alignment align = operand.GetAlignment();
18719    Dt_size_7 encoded_dt(dt);
18720    Align_align_3 encoded_align_1(align);
18721    if (IsUsingT32()) {
18722      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18723      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18724          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18725           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18726          operand.IsOffset() && encoded_align_1.IsValid() &&
18727          (!rn.IsPC() || AllowUnpredictable())) {
18728        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18729          const DRegister& first = nreglist.GetFirstDRegister();
18730          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18731          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18732                     (encoded_align_1.GetEncodingValue() << 4) |
18733                     first.Encode(22, 12) | (len_encoding << 8) |
18734                     (rn.GetCode() << 16));
18735          AdvanceIT();
18736          return;
18737        }
18738      }
18739      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18740      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18741          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18742           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18743          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18744          (!rn.IsPC() || AllowUnpredictable())) {
18745        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18746          const DRegister& first = nreglist.GetFirstDRegister();
18747          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18748          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18749                     (encoded_align_1.GetEncodingValue() << 4) |
18750                     first.Encode(22, 12) | (len_encoding << 8) |
18751                     (rn.GetCode() << 16));
18752          AdvanceIT();
18753          return;
18754        }
18755      }
18756    } else {
18757      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18758      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18759          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18760           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18761          operand.IsOffset() && encoded_align_1.IsValid() &&
18762          (!rn.IsPC() || AllowUnpredictable())) {
18763        if (cond.Is(al)) {
18764          const DRegister& first = nreglist.GetFirstDRegister();
18765          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18766          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18767                  (encoded_align_1.GetEncodingValue() << 4) |
18768                  first.Encode(22, 12) | (len_encoding << 8) |
18769                  (rn.GetCode() << 16));
18770          return;
18771        }
18772      }
18773      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18774      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18775          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18776           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18777          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18778          (!rn.IsPC() || AllowUnpredictable())) {
18779        if (cond.Is(al)) {
18780          const DRegister& first = nreglist.GetFirstDRegister();
18781          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18782          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18783                  (encoded_align_1.GetEncodingValue() << 4) |
18784                  first.Encode(22, 12) | (len_encoding << 8) |
18785                  (rn.GetCode() << 16));
18786          return;
18787        }
18788      }
18789    }
18790  }
18791  if (operand.IsPlainRegister()) {
18792    Register rn = operand.GetBaseRegister();
18793    Alignment align = operand.GetAlignment();
18794    Register rm = operand.GetOffsetRegister();
18795    Dt_size_7 encoded_dt(dt);
18796    Align_align_3 encoded_align_1(align);
18797    if (IsUsingT32()) {
18798      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18799      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18800          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18801           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18802          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18803        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18804          const DRegister& first = nreglist.GetFirstDRegister();
18805          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18806          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18807                     (encoded_align_1.GetEncodingValue() << 4) |
18808                     first.Encode(22, 12) | (len_encoding << 8) |
18809                     (rn.GetCode() << 16) | rm.GetCode());
18810          AdvanceIT();
18811          return;
18812        }
18813      }
18814    } else {
18815      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18816      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18817          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18818           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18819          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
18820        if (cond.Is(al)) {
18821          const DRegister& first = nreglist.GetFirstDRegister();
18822          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18823          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18824                  (encoded_align_1.GetEncodingValue() << 4) |
18825                  first.Encode(22, 12) | (len_encoding << 8) |
18826                  (rn.GetCode() << 16) | rm.GetCode());
18827          return;
18828        }
18829      }
18830    }
18831  }
18832  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
18833}
18834
18835void Assembler::vld3(Condition cond,
18836                     DataType dt,
18837                     const NeonRegisterList& nreglist,
18838                     const MemOperand& operand) {
18839  VIXL_ASSERT(AllowAssembler());
18840  CheckIT(cond);
18841  if (operand.IsImmediateZero()) {
18842    Register rn = operand.GetBaseRegister();
18843    Dt_size_7 encoded_dt(dt);
18844    Index_1 encoded_align_1(nreglist, dt);
18845    if (IsUsingT32()) {
18846      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18847      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18848          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18849           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18850          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18851        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18852          const DRegister& first = nreglist.GetFirstDRegister();
18853          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18854          EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18855                     first.Encode(22, 12) | (len_encoding << 5) |
18856                     (rn.GetCode() << 16));
18857          AdvanceIT();
18858          return;
18859        }
18860      }
18861      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18862      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18863          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18864           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18865          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18866        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18867          const DRegister& first = nreglist.GetFirstDRegister();
18868          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18869          EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18870                     first.Encode(22, 12) | (len_encoding << 5) |
18871                     (rn.GetCode() << 16));
18872          AdvanceIT();
18873          return;
18874        }
18875      }
18876      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18877      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18878          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18879           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18880          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18881        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18882          const DRegister& first = nreglist.GetFirstDRegister();
18883          EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18884                     (encoded_align_1.GetEncodingValue() << 4) |
18885                     first.Encode(22, 12) | (rn.GetCode() << 16));
18886          AdvanceIT();
18887          return;
18888        }
18889      }
18890      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18891      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18892          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18893           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18894          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18895        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18896          const DRegister& first = nreglist.GetFirstDRegister();
18897          EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18898                     (encoded_align_1.GetEncodingValue() << 4) |
18899                     first.Encode(22, 12) | (rn.GetCode() << 16));
18900          AdvanceIT();
18901          return;
18902        }
18903      }
18904    } else {
18905      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18906      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18907          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18908           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18909          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18910        if (cond.Is(al)) {
18911          const DRegister& first = nreglist.GetFirstDRegister();
18912          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18913          EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18914                  first.Encode(22, 12) | (len_encoding << 5) |
18915                  (rn.GetCode() << 16));
18916          return;
18917        }
18918      }
18919      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18920      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18921          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18922           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18923          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18924        if (cond.Is(al)) {
18925          const DRegister& first = nreglist.GetFirstDRegister();
18926          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18927          EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18928                  first.Encode(22, 12) | (len_encoding << 5) |
18929                  (rn.GetCode() << 16));
18930          return;
18931        }
18932      }
18933      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18934      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18935          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18936           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18937          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
18938        if (cond.Is(al)) {
18939          const DRegister& first = nreglist.GetFirstDRegister();
18940          EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18941                  (encoded_align_1.GetEncodingValue() << 4) |
18942                  first.Encode(22, 12) | (rn.GetCode() << 16));
18943          return;
18944        }
18945      }
18946      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18947      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18948          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18949           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18950          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
18951        if (cond.Is(al)) {
18952          const DRegister& first = nreglist.GetFirstDRegister();
18953          EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18954                  (encoded_align_1.GetEncodingValue() << 4) |
18955                  first.Encode(22, 12) | (rn.GetCode() << 16));
18956          return;
18957        }
18958      }
18959    }
18960  }
18961  if (operand.IsPlainRegister()) {
18962    Register rn = operand.GetBaseRegister();
18963    Sign sign = operand.GetSign();
18964    Register rm = operand.GetOffsetRegister();
18965    Dt_size_7 encoded_dt(dt);
18966    Index_1 encoded_align_1(nreglist, dt);
18967    if (IsUsingT32()) {
18968      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
18969      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18970          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18971           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18972          sign.IsPlus() && operand.IsPostIndex() &&
18973          (!rn.IsPC() || AllowUnpredictable())) {
18974        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18975          const DRegister& first = nreglist.GetFirstDRegister();
18976          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18977          EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
18978                     first.Encode(22, 12) | (len_encoding << 5) |
18979                     (rn.GetCode() << 16) | rm.GetCode());
18980          AdvanceIT();
18981          return;
18982        }
18983      }
18984      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
18985      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18986          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18987           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
18988          sign.IsPlus() && operand.IsPostIndex() &&
18989          (!rn.IsPC() || AllowUnpredictable())) {
18990        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18991          const DRegister& first = nreglist.GetFirstDRegister();
18992          EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
18993                     (encoded_align_1.GetEncodingValue() << 4) |
18994                     first.Encode(22, 12) | (rn.GetCode() << 16) |
18995                     rm.GetCode());
18996          AdvanceIT();
18997          return;
18998        }
18999      }
19000    } else {
19001      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19002      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
19003          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19004           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19005          sign.IsPlus() && operand.IsPostIndex() &&
19006          (!rn.IsPC() || AllowUnpredictable())) {
19007        if (cond.Is(al)) {
19008          const DRegister& first = nreglist.GetFirstDRegister();
19009          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19010          EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19011                  first.Encode(22, 12) | (len_encoding << 5) |
19012                  (rn.GetCode() << 16) | rm.GetCode());
19013          return;
19014        }
19015      }
19016      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19017      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19018          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19019           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
19020          sign.IsPlus() && operand.IsPostIndex() &&
19021          (!rn.IsPC() || AllowUnpredictable())) {
19022        if (cond.Is(al)) {
19023          const DRegister& first = nreglist.GetFirstDRegister();
19024          EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
19025                  (encoded_align_1.GetEncodingValue() << 4) |
19026                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19027          return;
19028        }
19029      }
19030    }
19031  }
19032  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
19033}
19034
19035void Assembler::vld4(Condition cond,
19036                     DataType dt,
19037                     const NeonRegisterList& nreglist,
19038                     const AlignedMemOperand& operand) {
19039  VIXL_ASSERT(AllowAssembler());
19040  CheckIT(cond);
19041  if (operand.IsImmediateZero()) {
19042    Register rn = operand.GetBaseRegister();
19043    Alignment align = operand.GetAlignment();
19044    Dt_size_7 encoded_dt(dt);
19045    Dt_size_8 encoded_dt_2(dt, align);
19046    Align_align_4 encoded_align_1(align);
19047    Align_a_3 encoded_align_2(align, dt);
19048    Align_index_align_3 encoded_align_3(align, nreglist, dt);
19049    if (IsUsingT32()) {
19050      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19051      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19052          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19053           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19054          operand.IsOffset() && encoded_align_1.IsValid() &&
19055          (!rn.IsPC() || AllowUnpredictable())) {
19056        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19057          const DRegister& first = nreglist.GetFirstDRegister();
19058          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19059          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
19060                     (encoded_align_1.GetEncodingValue() << 4) |
19061                     first.Encode(22, 12) | (len_encoding << 8) |
19062                     (rn.GetCode() << 16));
19063          AdvanceIT();
19064          return;
19065        }
19066      }
19067      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19068      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19069          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19070           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19071          operand.IsPostIndex() && encoded_align_1.IsValid() &&
19072          (!rn.IsPC() || AllowUnpredictable())) {
19073        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19074          const DRegister& first = nreglist.GetFirstDRegister();
19075          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19076          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
19077                     (encoded_align_1.GetEncodingValue() << 4) |
19078                     first.Encode(22, 12) | (len_encoding << 8) |
19079                     (rn.GetCode() << 16));
19080          AdvanceIT();
19081          return;
19082        }
19083      }
19084      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19085      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19086          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19087           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19088          operand.IsOffset() && encoded_align_2.IsValid() &&
19089          (!rn.IsPC() || AllowUnpredictable())) {
19090        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19091          const DRegister& first = nreglist.GetFirstDRegister();
19092          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19093          EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19094                     (encoded_align_2.GetEncodingValue() << 4) |
19095                     first.Encode(22, 12) | (len_encoding << 5) |
19096                     (rn.GetCode() << 16));
19097          AdvanceIT();
19098          return;
19099        }
19100      }
19101      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19102      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19103          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19104           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19105          operand.IsPostIndex() && encoded_align_2.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(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19111                     (encoded_align_2.GetEncodingValue() << 4) |
19112                     first.Encode(22, 12) | (len_encoding << 5) |
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.IsTransferOneLane() &&
19120          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19121           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19122          operand.IsOffset() && encoded_align_3.IsValid() &&
19123          (!rn.IsPC() || AllowUnpredictable())) {
19124        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19125          const DRegister& first = nreglist.GetFirstDRegister();
19126          EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19127                     (encoded_align_3.GetEncodingValue() << 4) |
19128                     first.Encode(22, 12) | (rn.GetCode() << 16));
19129          AdvanceIT();
19130          return;
19131        }
19132      }
19133      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19134      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19135          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19136           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19137          operand.IsPostIndex() && encoded_align_3.IsValid() &&
19138          (!rn.IsPC() || AllowUnpredictable())) {
19139        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19140          const DRegister& first = nreglist.GetFirstDRegister();
19141          EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19142                     (encoded_align_3.GetEncodingValue() << 4) |
19143                     first.Encode(22, 12) | (rn.GetCode() << 16));
19144          AdvanceIT();
19145          return;
19146        }
19147      }
19148    } else {
19149      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19150      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19151          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19152           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19153          operand.IsOffset() && encoded_align_1.IsValid() &&
19154          (!rn.IsPC() || AllowUnpredictable())) {
19155        if (cond.Is(al)) {
19156          const DRegister& first = nreglist.GetFirstDRegister();
19157          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19158          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
19159                  (encoded_align_1.GetEncodingValue() << 4) |
19160                  first.Encode(22, 12) | (len_encoding << 8) |
19161                  (rn.GetCode() << 16));
19162          return;
19163        }
19164      }
19165      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19166      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19167          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19168           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19169          operand.IsPostIndex() && encoded_align_1.IsValid() &&
19170          (!rn.IsPC() || AllowUnpredictable())) {
19171        if (cond.Is(al)) {
19172          const DRegister& first = nreglist.GetFirstDRegister();
19173          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19174          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
19175                  (encoded_align_1.GetEncodingValue() << 4) |
19176                  first.Encode(22, 12) | (len_encoding << 8) |
19177                  (rn.GetCode() << 16));
19178          return;
19179        }
19180      }
19181      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19182      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19183          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19184           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19185          operand.IsOffset() && encoded_align_2.IsValid() &&
19186          (!rn.IsPC() || AllowUnpredictable())) {
19187        if (cond.Is(al)) {
19188          const DRegister& first = nreglist.GetFirstDRegister();
19189          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19190          EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19191                  (encoded_align_2.GetEncodingValue() << 4) |
19192                  first.Encode(22, 12) | (len_encoding << 5) |
19193                  (rn.GetCode() << 16));
19194          return;
19195        }
19196      }
19197      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19198      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19199          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19200           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19201          operand.IsPostIndex() && encoded_align_2.IsValid() &&
19202          (!rn.IsPC() || AllowUnpredictable())) {
19203        if (cond.Is(al)) {
19204          const DRegister& first = nreglist.GetFirstDRegister();
19205          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19206          EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19207                  (encoded_align_2.GetEncodingValue() << 4) |
19208                  first.Encode(22, 12) | (len_encoding << 5) |
19209                  (rn.GetCode() << 16));
19210          return;
19211        }
19212      }
19213      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19214      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19215          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19216           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19217          operand.IsOffset() && encoded_align_3.IsValid() &&
19218          (!rn.IsPC() || AllowUnpredictable())) {
19219        if (cond.Is(al)) {
19220          const DRegister& first = nreglist.GetFirstDRegister();
19221          EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19222                  (encoded_align_3.GetEncodingValue() << 4) |
19223                  first.Encode(22, 12) | (rn.GetCode() << 16));
19224          return;
19225        }
19226      }
19227      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19228      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19229          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19230           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19231          operand.IsPostIndex() && encoded_align_3.IsValid() &&
19232          (!rn.IsPC() || AllowUnpredictable())) {
19233        if (cond.Is(al)) {
19234          const DRegister& first = nreglist.GetFirstDRegister();
19235          EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19236                  (encoded_align_3.GetEncodingValue() << 4) |
19237                  first.Encode(22, 12) | (rn.GetCode() << 16));
19238          return;
19239        }
19240      }
19241    }
19242  }
19243  if (operand.IsPlainRegister()) {
19244    Register rn = operand.GetBaseRegister();
19245    Alignment align = operand.GetAlignment();
19246    Register rm = operand.GetOffsetRegister();
19247    Dt_size_7 encoded_dt(dt);
19248    Dt_size_8 encoded_dt_2(dt, align);
19249    Align_align_4 encoded_align_1(align);
19250    Align_a_3 encoded_align_2(align, dt);
19251    Align_index_align_3 encoded_align_3(align, nreglist, dt);
19252    if (IsUsingT32()) {
19253      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19254      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19255          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19256           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19257          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19258        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19259          const DRegister& first = nreglist.GetFirstDRegister();
19260          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19261          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
19262                     (encoded_align_1.GetEncodingValue() << 4) |
19263                     first.Encode(22, 12) | (len_encoding << 8) |
19264                     (rn.GetCode() << 16) | rm.GetCode());
19265          AdvanceIT();
19266          return;
19267        }
19268      }
19269      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19270      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19271          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19272           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19273          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19274        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19275          const DRegister& first = nreglist.GetFirstDRegister();
19276          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19277          EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19278                     (encoded_align_2.GetEncodingValue() << 4) |
19279                     first.Encode(22, 12) | (len_encoding << 5) |
19280                     (rn.GetCode() << 16) | rm.GetCode());
19281          AdvanceIT();
19282          return;
19283        }
19284      }
19285      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19286      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19287          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19288           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19289          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19290        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19291          const DRegister& first = nreglist.GetFirstDRegister();
19292          EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
19293                     (encoded_align_3.GetEncodingValue() << 4) |
19294                     first.Encode(22, 12) | (rn.GetCode() << 16) |
19295                     rm.GetCode());
19296          AdvanceIT();
19297          return;
19298        }
19299      }
19300    } else {
19301      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19302      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19303          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19304           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19305          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19306        if (cond.Is(al)) {
19307          const DRegister& first = nreglist.GetFirstDRegister();
19308          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19309          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
19310                  (encoded_align_1.GetEncodingValue() << 4) |
19311                  first.Encode(22, 12) | (len_encoding << 8) |
19312                  (rn.GetCode() << 16) | rm.GetCode());
19313          return;
19314        }
19315      }
19316      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19317      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19318          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19319           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19320          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19321        if (cond.Is(al)) {
19322          const DRegister& first = nreglist.GetFirstDRegister();
19323          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19324          EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19325                  (encoded_align_2.GetEncodingValue() << 4) |
19326                  first.Encode(22, 12) | (len_encoding << 5) |
19327                  (rn.GetCode() << 16) | rm.GetCode());
19328          return;
19329        }
19330      }
19331      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19332      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19333          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19334           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
19335          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
19336        if (cond.Is(al)) {
19337          const DRegister& first = nreglist.GetFirstDRegister();
19338          EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
19339                  (encoded_align_3.GetEncodingValue() << 4) |
19340                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19341          return;
19342        }
19343      }
19344    }
19345  }
19346  Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
19347}
19348
19349void Assembler::vldm(Condition cond,
19350                     DataType dt,
19351                     Register rn,
19352                     WriteBack write_back,
19353                     DRegisterList dreglist) {
19354  VIXL_ASSERT(AllowAssembler());
19355  CheckIT(cond);
19356  USE(dt);
19357  if (IsUsingT32()) {
19358    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
19359    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19360         AllowUnpredictable())) {
19361      const DRegister& dreg = dreglist.GetFirstDRegister();
19362      unsigned len = dreglist.GetLength() * 2;
19363      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19364                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19365                 (len & 0xff));
19366      AdvanceIT();
19367      return;
19368    }
19369  } else {
19370    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
19371    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19372                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19373                              AllowUnpredictable())) {
19374      const DRegister& dreg = dreglist.GetFirstDRegister();
19375      unsigned len = dreglist.GetLength() * 2;
19376      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19377              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19378              (len & 0xff));
19379      return;
19380    }
19381  }
19382  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
19383}
19384
19385void Assembler::vldm(Condition cond,
19386                     DataType dt,
19387                     Register rn,
19388                     WriteBack write_back,
19389                     SRegisterList sreglist) {
19390  VIXL_ASSERT(AllowAssembler());
19391  CheckIT(cond);
19392  USE(dt);
19393  if (IsUsingT32()) {
19394    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
19395    if ((!rn.IsPC() || AllowUnpredictable())) {
19396      const SRegister& sreg = sreglist.GetFirstSRegister();
19397      unsigned len = sreglist.GetLength();
19398      EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19399                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19400                 (len & 0xff));
19401      AdvanceIT();
19402      return;
19403    }
19404  } else {
19405    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
19406    if (cond.IsNotNever() &&
19407        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
19408      const SRegister& sreg = sreglist.GetFirstSRegister();
19409      unsigned len = sreglist.GetLength();
19410      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19411              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19412              (len & 0xff));
19413      return;
19414    }
19415  }
19416  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
19417}
19418
19419void Assembler::vldmdb(Condition cond,
19420                       DataType dt,
19421                       Register rn,
19422                       WriteBack write_back,
19423                       DRegisterList dreglist) {
19424  VIXL_ASSERT(AllowAssembler());
19425  CheckIT(cond);
19426  USE(dt);
19427  if (IsUsingT32()) {
19428    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
19429    if (write_back.DoesWriteBack() &&
19430        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19431         AllowUnpredictable())) {
19432      const DRegister& dreg = dreglist.GetFirstDRegister();
19433      unsigned len = dreglist.GetLength() * 2;
19434      EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
19435                 (len & 0xff));
19436      AdvanceIT();
19437      return;
19438    }
19439  } else {
19440    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
19441    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
19442        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19443         AllowUnpredictable())) {
19444      const DRegister& dreg = dreglist.GetFirstDRegister();
19445      unsigned len = dreglist.GetLength() * 2;
19446      EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19447              dreg.Encode(22, 12) | (len & 0xff));
19448      return;
19449    }
19450  }
19451  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
19452}
19453
19454void Assembler::vldmdb(Condition cond,
19455                       DataType dt,
19456                       Register rn,
19457                       WriteBack write_back,
19458                       SRegisterList sreglist) {
19459  VIXL_ASSERT(AllowAssembler());
19460  CheckIT(cond);
19461  USE(dt);
19462  if (IsUsingT32()) {
19463    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
19464    if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
19465      const SRegister& sreg = sreglist.GetFirstSRegister();
19466      unsigned len = sreglist.GetLength();
19467      EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
19468                 (len & 0xff));
19469      AdvanceIT();
19470      return;
19471    }
19472  } else {
19473    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
19474    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
19475        (!rn.IsPC() || AllowUnpredictable())) {
19476      const SRegister& sreg = sreglist.GetFirstSRegister();
19477      unsigned len = sreglist.GetLength();
19478      EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19479              sreg.Encode(22, 12) | (len & 0xff));
19480      return;
19481    }
19482  }
19483  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
19484}
19485
19486void Assembler::vldmia(Condition cond,
19487                       DataType dt,
19488                       Register rn,
19489                       WriteBack write_back,
19490                       DRegisterList dreglist) {
19491  VIXL_ASSERT(AllowAssembler());
19492  CheckIT(cond);
19493  USE(dt);
19494  if (IsUsingT32()) {
19495    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
19496    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19497         AllowUnpredictable())) {
19498      const DRegister& dreg = dreglist.GetFirstDRegister();
19499      unsigned len = dreglist.GetLength() * 2;
19500      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19501                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19502                 (len & 0xff));
19503      AdvanceIT();
19504      return;
19505    }
19506  } else {
19507    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
19508    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19509                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19510                              AllowUnpredictable())) {
19511      const DRegister& dreg = dreglist.GetFirstDRegister();
19512      unsigned len = dreglist.GetLength() * 2;
19513      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19514              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19515              (len & 0xff));
19516      return;
19517    }
19518  }
19519  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
19520}
19521
19522void Assembler::vldmia(Condition cond,
19523                       DataType dt,
19524                       Register rn,
19525                       WriteBack write_back,
19526                       SRegisterList sreglist) {
19527  VIXL_ASSERT(AllowAssembler());
19528  CheckIT(cond);
19529  USE(dt);
19530  if (IsUsingT32()) {
19531    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
19532    if ((!rn.IsPC() || AllowUnpredictable())) {
19533      const SRegister& sreg = sreglist.GetFirstSRegister();
19534      unsigned len = sreglist.GetLength();
19535      EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19536                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19537                 (len & 0xff));
19538      AdvanceIT();
19539      return;
19540    }
19541  } else {
19542    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
19543    if (cond.IsNotNever() &&
19544        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
19545      const SRegister& sreg = sreglist.GetFirstSRegister();
19546      unsigned len = sreglist.GetLength();
19547      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19548              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19549              (len & 0xff));
19550      return;
19551    }
19552  }
19553  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
19554}
19555
19556void Assembler::vldr(Condition cond,
19557                     DataType dt,
19558                     DRegister rd,
19559                     Location* location) {
19560  VIXL_ASSERT(AllowAssembler());
19561  CheckIT(cond);
19562  Location::Offset offset =
19563      location->IsBound()
19564          ? location->GetLocation() -
19565                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19566          : 0;
19567  if (IsUsingT32()) {
19568    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19569    if (dt.IsNoneOr(Untyped64) &&
19570        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19571          ((offset & 0x3) == 0)) ||
19572         !location->IsBound())) {
19573      static class EmitOp : public Location::EmitOperator {
19574       public:
19575        EmitOp() : Location::EmitOperator(T32) {}
19576        virtual uint32_t Encode(uint32_t instr,
19577                                Location::Offset pc,
19578                                const Location* location) const VIXL_OVERRIDE {
19579          pc += kT32PcDelta;
19580          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
19581          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19582                      ((offset & 0x3) == 0));
19583          int32_t target = offset >> 2;
19584          uint32_t U = (target >= 0);
19585          target = abs(target) | (U << 8);
19586          return instr | (target & 0xff) | ((target & 0x100) << 15);
19587        }
19588      } immop;
19589      EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12),
19590                      location,
19591                      immop,
19592                      &kT32DataInfo));
19593      AdvanceIT();
19594      return;
19595    }
19596  } else {
19597    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19598    if (dt.IsNoneOr(Untyped64) &&
19599        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19600          ((offset & 0x3) == 0)) ||
19601         !location->IsBound()) &&
19602        cond.IsNotNever()) {
19603      static class EmitOp : public Location::EmitOperator {
19604       public:
19605        EmitOp() : Location::EmitOperator(A32) {}
19606        virtual uint32_t Encode(uint32_t instr,
19607                                Location::Offset pc,
19608                                const Location* location) const VIXL_OVERRIDE {
19609          pc += kA32PcDelta;
19610          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
19611          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19612                      ((offset & 0x3) == 0));
19613          int32_t target = offset >> 2;
19614          uint32_t U = (target >= 0);
19615          target = abs(target) | (U << 8);
19616          return instr | (target & 0xff) | ((target & 0x100) << 15);
19617        }
19618      } immop;
19619      EmitA32(
19620          Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
19621               location,
19622               immop,
19623               &kA32DataInfo));
19624      return;
19625    }
19626  }
19627  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
19628}
19629
19630bool Assembler::vldr_info(Condition cond,
19631                          DataType dt,
19632                          DRegister rd,
19633                          Location* location,
19634                          const struct ReferenceInfo** info) {
19635  VIXL_ASSERT(!location->IsBound());
19636  USE(location);
19637  USE(rd);
19638  if (IsUsingT32()) {
19639    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19640    if (dt.IsNoneOr(Untyped64)) {
19641      *info = &kT32DataInfo;
19642      return true;
19643    }
19644  } else {
19645    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19646    if (dt.IsNoneOr(Untyped64) && cond.IsNotNever()) {
19647      *info = &kA32DataInfo;
19648      return true;
19649    }
19650  }
19651  return false;
19652}
19653
19654void Assembler::vldr(Condition cond,
19655                     DataType dt,
19656                     DRegister rd,
19657                     const MemOperand& operand) {
19658  VIXL_ASSERT(AllowAssembler());
19659  CheckIT(cond);
19660  if (operand.IsImmediate()) {
19661    Register rn = operand.GetBaseRegister();
19662    int32_t offset = operand.GetOffsetImmediate();
19663    if (IsUsingT32()) {
19664      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
19665      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19666          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
19667        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19668        uint32_t offset_ = abs(offset) >> 2;
19669        EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19670        AdvanceIT();
19671        return;
19672      }
19673      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
19674      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19675          ((offset % 4) == 0) && operand.IsOffset() &&
19676          ((rn.GetCode() & 0xf) != 0xf)) {
19677        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19678        uint32_t offset_ = abs(offset) >> 2;
19679        EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19680                   offset_ | (sign << 23));
19681        AdvanceIT();
19682        return;
19683      }
19684    } else {
19685      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
19686      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19687          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19688          cond.IsNotNever()) {
19689        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19690        uint32_t offset_ = abs(offset) >> 2;
19691        EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19692                offset_ | (sign << 23));
19693        return;
19694      }
19695      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
19696      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
19697          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19698          ((rn.GetCode() & 0xf) != 0xf)) {
19699        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19700        uint32_t offset_ = abs(offset) >> 2;
19701        EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19702                (rn.GetCode() << 16) | offset_ | (sign << 23));
19703        return;
19704      }
19705    }
19706  }
19707  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19708}
19709
19710void Assembler::vldr(Condition cond,
19711                     DataType dt,
19712                     SRegister rd,
19713                     Location* location) {
19714  VIXL_ASSERT(AllowAssembler());
19715  CheckIT(cond);
19716  Location::Offset offset =
19717      location->IsBound()
19718          ? location->GetLocation() -
19719                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19720          : 0;
19721  if (IsUsingT32()) {
19722    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19723    if (dt.IsNoneOr(Untyped32) &&
19724        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19725          ((offset & 0x3) == 0)) ||
19726         !location->IsBound())) {
19727      static class EmitOp : public Location::EmitOperator {
19728       public:
19729        EmitOp() : Location::EmitOperator(T32) {}
19730        virtual uint32_t Encode(uint32_t instr,
19731                                Location::Offset pc,
19732                                const Location* location) const VIXL_OVERRIDE {
19733          pc += kT32PcDelta;
19734          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
19735          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19736                      ((offset & 0x3) == 0));
19737          int32_t target = offset >> 2;
19738          uint32_t U = (target >= 0);
19739          target = abs(target) | (U << 8);
19740          return instr | (target & 0xff) | ((target & 0x100) << 15);
19741        }
19742      } immop;
19743      EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12),
19744                      location,
19745                      immop,
19746                      &kT32DataInfo));
19747      AdvanceIT();
19748      return;
19749    }
19750  } else {
19751    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19752    if (dt.IsNoneOr(Untyped32) &&
19753        ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
19754          ((offset & 0x3) == 0)) ||
19755         !location->IsBound()) &&
19756        cond.IsNotNever()) {
19757      static class EmitOp : public Location::EmitOperator {
19758       public:
19759        EmitOp() : Location::EmitOperator(A32) {}
19760        virtual uint32_t Encode(uint32_t instr,
19761                                Location::Offset pc,
19762                                const Location* location) const VIXL_OVERRIDE {
19763          pc += kA32PcDelta;
19764          Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
19765          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19766                      ((offset & 0x3) == 0));
19767          int32_t target = offset >> 2;
19768          uint32_t U = (target >= 0);
19769          target = abs(target) | (U << 8);
19770          return instr | (target & 0xff) | ((target & 0x100) << 15);
19771        }
19772      } immop;
19773      EmitA32(
19774          Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
19775               location,
19776               immop,
19777               &kA32DataInfo));
19778      return;
19779    }
19780  }
19781  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
19782}
19783
19784bool Assembler::vldr_info(Condition cond,
19785                          DataType dt,
19786                          SRegister rd,
19787                          Location* location,
19788                          const struct ReferenceInfo** info) {
19789  VIXL_ASSERT(!location->IsBound());
19790  USE(location);
19791  USE(rd);
19792  if (IsUsingT32()) {
19793    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19794    if (dt.IsNoneOr(Untyped32)) {
19795      *info = &kT32DataInfo;
19796      return true;
19797    }
19798  } else {
19799    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19800    if (dt.IsNoneOr(Untyped32) && cond.IsNotNever()) {
19801      *info = &kA32DataInfo;
19802      return true;
19803    }
19804  }
19805  return false;
19806}
19807
19808void Assembler::vldr(Condition cond,
19809                     DataType dt,
19810                     SRegister rd,
19811                     const MemOperand& operand) {
19812  VIXL_ASSERT(AllowAssembler());
19813  CheckIT(cond);
19814  if (operand.IsImmediate()) {
19815    Register rn = operand.GetBaseRegister();
19816    int32_t offset = operand.GetOffsetImmediate();
19817    if (IsUsingT32()) {
19818      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
19819      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19820          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
19821        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19822        uint32_t offset_ = abs(offset) >> 2;
19823        EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19824        AdvanceIT();
19825        return;
19826      }
19827      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
19828      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19829          ((offset % 4) == 0) && operand.IsOffset() &&
19830          ((rn.GetCode() & 0xf) != 0xf)) {
19831        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19832        uint32_t offset_ = abs(offset) >> 2;
19833        EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19834                   offset_ | (sign << 23));
19835        AdvanceIT();
19836        return;
19837      }
19838    } else {
19839      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
19840      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19841          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19842          cond.IsNotNever()) {
19843        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19844        uint32_t offset_ = abs(offset) >> 2;
19845        EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19846                offset_ | (sign << 23));
19847        return;
19848      }
19849      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
19850      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
19851          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19852          ((rn.GetCode() & 0xf) != 0xf)) {
19853        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19854        uint32_t offset_ = abs(offset) >> 2;
19855        EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19856                (rn.GetCode() << 16) | offset_ | (sign << 23));
19857        return;
19858      }
19859    }
19860  }
19861  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19862}
19863
19864void Assembler::vmax(
19865    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19866  VIXL_ASSERT(AllowAssembler());
19867  CheckIT(cond);
19868  Dt_U_size_1 encoded_dt(dt);
19869  if (IsUsingT32()) {
19870    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
19871    if (dt.Is(F32)) {
19872      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19873        EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19874                   rm.Encode(5, 0));
19875        AdvanceIT();
19876        return;
19877      }
19878    }
19879    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
19880    if (encoded_dt.IsValid()) {
19881      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19882        EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19883                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19884                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19885        AdvanceIT();
19886        return;
19887      }
19888    }
19889  } else {
19890    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
19891    if (dt.Is(F32)) {
19892      if (cond.Is(al)) {
19893        EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19894                rm.Encode(5, 0));
19895        return;
19896      }
19897    }
19898    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
19899    if (encoded_dt.IsValid()) {
19900      if (cond.Is(al)) {
19901        EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19902                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19903                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19904        return;
19905      }
19906    }
19907  }
19908  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19909}
19910
19911void Assembler::vmax(
19912    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19913  VIXL_ASSERT(AllowAssembler());
19914  CheckIT(cond);
19915  Dt_U_size_1 encoded_dt(dt);
19916  if (IsUsingT32()) {
19917    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
19918    if (dt.Is(F32)) {
19919      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19920        EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19921                   rm.Encode(5, 0));
19922        AdvanceIT();
19923        return;
19924      }
19925    }
19926    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
19927    if (encoded_dt.IsValid()) {
19928      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19929        EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19930                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19931                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19932        AdvanceIT();
19933        return;
19934      }
19935    }
19936  } else {
19937    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
19938    if (dt.Is(F32)) {
19939      if (cond.Is(al)) {
19940        EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19941                rm.Encode(5, 0));
19942        return;
19943      }
19944    }
19945    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
19946    if (encoded_dt.IsValid()) {
19947      if (cond.Is(al)) {
19948        EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19949                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19950                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19951        return;
19952      }
19953    }
19954  }
19955  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19956}
19957
19958void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19959  VIXL_ASSERT(AllowAssembler());
19960  CheckIT(al);
19961  if (IsUsingT32()) {
19962    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19963    if (OutsideITBlock() && dt.Is(F32)) {
19964      EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19965                 rm.Encode(5, 0));
19966      AdvanceIT();
19967      return;
19968    }
19969    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19970    if (OutsideITBlock() && dt.Is(F64)) {
19971      EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19972                 rm.Encode(5, 0));
19973      AdvanceIT();
19974      return;
19975    }
19976  } else {
19977    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19978    if (dt.Is(F32)) {
19979      EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19980              rm.Encode(5, 0));
19981      return;
19982    }
19983    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19984    if (dt.Is(F64)) {
19985      EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19986              rm.Encode(5, 0));
19987      return;
19988    }
19989  }
19990  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
19991}
19992
19993void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19994  VIXL_ASSERT(AllowAssembler());
19995  CheckIT(al);
19996  if (IsUsingT32()) {
19997    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19998    if (OutsideITBlock() && dt.Is(F32)) {
19999      EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20000                 rm.Encode(5, 0));
20001      AdvanceIT();
20002      return;
20003    }
20004  } else {
20005    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20006    if (dt.Is(F32)) {
20007      EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20008              rm.Encode(5, 0));
20009      return;
20010    }
20011  }
20012  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20013}
20014
20015void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20016  VIXL_ASSERT(AllowAssembler());
20017  CheckIT(al);
20018  if (IsUsingT32()) {
20019    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20020    if (OutsideITBlock() && dt.Is(F32)) {
20021      EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20022                 rm.Encode(5, 0));
20023      AdvanceIT();
20024      return;
20025    }
20026  } else {
20027    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20028    if (dt.Is(F32)) {
20029      EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20030              rm.Encode(5, 0));
20031      return;
20032    }
20033  }
20034  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20035}
20036
20037void Assembler::vmin(
20038    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20039  VIXL_ASSERT(AllowAssembler());
20040  CheckIT(cond);
20041  Dt_U_size_1 encoded_dt(dt);
20042  if (IsUsingT32()) {
20043    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20044    if (dt.Is(F32)) {
20045      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20046        EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20047                   rm.Encode(5, 0));
20048        AdvanceIT();
20049        return;
20050      }
20051    }
20052    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20053    if (encoded_dt.IsValid()) {
20054      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20055        EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20056                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20057                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20058        AdvanceIT();
20059        return;
20060      }
20061    }
20062  } else {
20063    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20064    if (dt.Is(F32)) {
20065      if (cond.Is(al)) {
20066        EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20067                rm.Encode(5, 0));
20068        return;
20069      }
20070    }
20071    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20072    if (encoded_dt.IsValid()) {
20073      if (cond.Is(al)) {
20074        EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20075                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20076                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20077        return;
20078      }
20079    }
20080  }
20081  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20082}
20083
20084void Assembler::vmin(
20085    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20086  VIXL_ASSERT(AllowAssembler());
20087  CheckIT(cond);
20088  Dt_U_size_1 encoded_dt(dt);
20089  if (IsUsingT32()) {
20090    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20091    if (dt.Is(F32)) {
20092      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20093        EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20094                   rm.Encode(5, 0));
20095        AdvanceIT();
20096        return;
20097      }
20098    }
20099    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20100    if (encoded_dt.IsValid()) {
20101      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20102        EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20103                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20104                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20105        AdvanceIT();
20106        return;
20107      }
20108    }
20109  } else {
20110    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20111    if (dt.Is(F32)) {
20112      if (cond.Is(al)) {
20113        EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20114                rm.Encode(5, 0));
20115        return;
20116      }
20117    }
20118    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20119    if (encoded_dt.IsValid()) {
20120      if (cond.Is(al)) {
20121        EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20122                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20123                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20124        return;
20125      }
20126    }
20127  }
20128  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20129}
20130
20131void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20132  VIXL_ASSERT(AllowAssembler());
20133  CheckIT(al);
20134  if (IsUsingT32()) {
20135    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20136    if (OutsideITBlock() && dt.Is(F32)) {
20137      EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20138                 rm.Encode(5, 0));
20139      AdvanceIT();
20140      return;
20141    }
20142    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20143    if (OutsideITBlock() && dt.Is(F64)) {
20144      EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20145                 rm.Encode(5, 0));
20146      AdvanceIT();
20147      return;
20148    }
20149  } else {
20150    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20151    if (dt.Is(F32)) {
20152      EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20153              rm.Encode(5, 0));
20154      return;
20155    }
20156    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20157    if (dt.Is(F64)) {
20158      EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20159              rm.Encode(5, 0));
20160      return;
20161    }
20162  }
20163  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20164}
20165
20166void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20167  VIXL_ASSERT(AllowAssembler());
20168  CheckIT(al);
20169  if (IsUsingT32()) {
20170    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20171    if (OutsideITBlock() && dt.Is(F32)) {
20172      EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20173                 rm.Encode(5, 0));
20174      AdvanceIT();
20175      return;
20176    }
20177  } else {
20178    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20179    if (dt.Is(F32)) {
20180      EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20181              rm.Encode(5, 0));
20182      return;
20183    }
20184  }
20185  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20186}
20187
20188void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20189  VIXL_ASSERT(AllowAssembler());
20190  CheckIT(al);
20191  if (IsUsingT32()) {
20192    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20193    if (OutsideITBlock() && dt.Is(F32)) {
20194      EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20195                 rm.Encode(5, 0));
20196      AdvanceIT();
20197      return;
20198    }
20199  } else {
20200    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20201    if (dt.Is(F32)) {
20202      EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20203              rm.Encode(5, 0));
20204      return;
20205    }
20206  }
20207  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20208}
20209
20210void Assembler::vmla(
20211    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
20212  VIXL_ASSERT(AllowAssembler());
20213  CheckIT(cond);
20214  Dt_size_9 encoded_dt(dt);
20215  if (IsUsingT32()) {
20216    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20217    if (encoded_dt.IsValid() &&
20218        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20219         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20220          (rm.GetLane() <= 1)))) {
20221      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20222        EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20223                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20224                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20225        AdvanceIT();
20226        return;
20227      }
20228    }
20229  } else {
20230    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20231    if (encoded_dt.IsValid() &&
20232        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20233         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20234          (rm.GetLane() <= 1)))) {
20235      if (cond.Is(al)) {
20236        EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20237                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20238                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20239        return;
20240      }
20241    }
20242  }
20243  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20244}
20245
20246void Assembler::vmla(
20247    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
20248  VIXL_ASSERT(AllowAssembler());
20249  CheckIT(cond);
20250  Dt_size_9 encoded_dt(dt);
20251  if (IsUsingT32()) {
20252    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20253    if (encoded_dt.IsValid() &&
20254        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20255         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20256          (rm.GetLane() <= 1)))) {
20257      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20258        EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20259                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20260                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20261        AdvanceIT();
20262        return;
20263      }
20264    }
20265  } else {
20266    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20267    if (encoded_dt.IsValid() &&
20268        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20269         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20270          (rm.GetLane() <= 1)))) {
20271      if (cond.Is(al)) {
20272        EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20273                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20274                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20275        return;
20276      }
20277    }
20278  }
20279  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20280}
20281
20282void Assembler::vmla(
20283    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20284  VIXL_ASSERT(AllowAssembler());
20285  CheckIT(cond);
20286  Dt_size_10 encoded_dt(dt);
20287  if (IsUsingT32()) {
20288    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20289    if (dt.Is(F32)) {
20290      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20291        EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20292                   rm.Encode(5, 0));
20293        AdvanceIT();
20294        return;
20295      }
20296    }
20297    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20298    if (dt.Is(F64)) {
20299      EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20300                 rm.Encode(5, 0));
20301      AdvanceIT();
20302      return;
20303    }
20304    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20305    if (encoded_dt.IsValid()) {
20306      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20307        EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
20308                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20309        AdvanceIT();
20310        return;
20311      }
20312    }
20313  } else {
20314    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20315    if (dt.Is(F32)) {
20316      if (cond.Is(al)) {
20317        EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20318                rm.Encode(5, 0));
20319        return;
20320      }
20321    }
20322    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20323    if (dt.Is(F64) && cond.IsNotNever()) {
20324      EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20325              rn.Encode(7, 16) | rm.Encode(5, 0));
20326      return;
20327    }
20328    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20329    if (encoded_dt.IsValid()) {
20330      if (cond.Is(al)) {
20331        EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
20332                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20333        return;
20334      }
20335    }
20336  }
20337  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20338}
20339
20340void Assembler::vmla(
20341    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20342  VIXL_ASSERT(AllowAssembler());
20343  CheckIT(cond);
20344  Dt_size_10 encoded_dt(dt);
20345  if (IsUsingT32()) {
20346    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20347    if (dt.Is(F32)) {
20348      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20349        EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20350                   rm.Encode(5, 0));
20351        AdvanceIT();
20352        return;
20353      }
20354    }
20355    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20356    if (encoded_dt.IsValid()) {
20357      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20358        EmitT32_32(0xef000940U | (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 <Qd>, <Qn>, <Qm> ; A1
20366    if (dt.Is(F32)) {
20367      if (cond.Is(al)) {
20368        EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20369                rm.Encode(5, 0));
20370        return;
20371      }
20372    }
20373    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20374    if (encoded_dt.IsValid()) {
20375      if (cond.Is(al)) {
20376        EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
20377                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20378        return;
20379      }
20380    }
20381  }
20382  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20383}
20384
20385void Assembler::vmla(
20386    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20387  VIXL_ASSERT(AllowAssembler());
20388  CheckIT(cond);
20389  if (IsUsingT32()) {
20390    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20391    if (dt.Is(F32)) {
20392      EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20393                 rm.Encode(5, 0));
20394      AdvanceIT();
20395      return;
20396    }
20397  } else {
20398    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20399    if (dt.Is(F32) && cond.IsNotNever()) {
20400      EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20401              rn.Encode(7, 16) | rm.Encode(5, 0));
20402      return;
20403    }
20404  }
20405  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20406}
20407
20408void Assembler::vmlal(
20409    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
20410  VIXL_ASSERT(AllowAssembler());
20411  CheckIT(cond);
20412  Dt_size_11 encoded_dt(dt);
20413  if (IsUsingT32()) {
20414    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20415    if (encoded_dt.IsValid() &&
20416        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20417         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20418          (rm.GetLane() <= 1)))) {
20419      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20420        EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
20421                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20422                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20423        AdvanceIT();
20424        return;
20425      }
20426    }
20427  } else {
20428    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20429    if (encoded_dt.IsValid() &&
20430        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20431         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20432          (rm.GetLane() <= 1)))) {
20433      if (cond.Is(al)) {
20434        EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
20435                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20436                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20437        return;
20438      }
20439    }
20440  }
20441  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20442}
20443
20444void Assembler::vmlal(
20445    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
20446  VIXL_ASSERT(AllowAssembler());
20447  CheckIT(cond);
20448  Dt_size_12 encoded_dt(dt);
20449  if (IsUsingT32()) {
20450    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20451    if (encoded_dt.IsValid()) {
20452      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20453        EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
20454                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20455                   rn.Encode(7, 16) | rm.Encode(5, 0));
20456        AdvanceIT();
20457        return;
20458      }
20459    }
20460  } else {
20461    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20462    if (encoded_dt.IsValid()) {
20463      if (cond.Is(al)) {
20464        EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
20465                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20466                rn.Encode(7, 16) | rm.Encode(5, 0));
20467        return;
20468      }
20469    }
20470  }
20471  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20472}
20473
20474void Assembler::vmls(
20475    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
20476  VIXL_ASSERT(AllowAssembler());
20477  CheckIT(cond);
20478  Dt_size_9 encoded_dt(dt);
20479  if (IsUsingT32()) {
20480    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20481    if (encoded_dt.IsValid() &&
20482        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20483         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20484          (rm.GetLane() <= 1)))) {
20485      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20486        EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20487                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20488                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20489        AdvanceIT();
20490        return;
20491      }
20492    }
20493  } else {
20494    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20495    if (encoded_dt.IsValid() &&
20496        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20497         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20498          (rm.GetLane() <= 1)))) {
20499      if (cond.Is(al)) {
20500        EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20501                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20502                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20503        return;
20504      }
20505    }
20506  }
20507  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20508}
20509
20510void Assembler::vmls(
20511    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
20512  VIXL_ASSERT(AllowAssembler());
20513  CheckIT(cond);
20514  Dt_size_9 encoded_dt(dt);
20515  if (IsUsingT32()) {
20516    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20517    if (encoded_dt.IsValid() &&
20518        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20519         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20520          (rm.GetLane() <= 1)))) {
20521      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20522        EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20523                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20524                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20525        AdvanceIT();
20526        return;
20527      }
20528    }
20529  } else {
20530    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20531    if (encoded_dt.IsValid() &&
20532        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20533         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20534          (rm.GetLane() <= 1)))) {
20535      if (cond.Is(al)) {
20536        EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20537                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20538                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20539        return;
20540      }
20541    }
20542  }
20543  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20544}
20545
20546void Assembler::vmls(
20547    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20548  VIXL_ASSERT(AllowAssembler());
20549  CheckIT(cond);
20550  Dt_size_10 encoded_dt(dt);
20551  if (IsUsingT32()) {
20552    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20553    if (dt.Is(F32)) {
20554      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20555        EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20556                   rm.Encode(5, 0));
20557        AdvanceIT();
20558        return;
20559      }
20560    }
20561    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20562    if (dt.Is(F64)) {
20563      EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20564                 rm.Encode(5, 0));
20565      AdvanceIT();
20566      return;
20567    }
20568    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20569    if (encoded_dt.IsValid()) {
20570      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20571        EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
20572                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20573        AdvanceIT();
20574        return;
20575      }
20576    }
20577  } else {
20578    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20579    if (dt.Is(F32)) {
20580      if (cond.Is(al)) {
20581        EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20582                rm.Encode(5, 0));
20583        return;
20584      }
20585    }
20586    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20587    if (dt.Is(F64) && cond.IsNotNever()) {
20588      EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20589              rn.Encode(7, 16) | rm.Encode(5, 0));
20590      return;
20591    }
20592    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20593    if (encoded_dt.IsValid()) {
20594      if (cond.Is(al)) {
20595        EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
20596                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20597        return;
20598      }
20599    }
20600  }
20601  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20602}
20603
20604void Assembler::vmls(
20605    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20606  VIXL_ASSERT(AllowAssembler());
20607  CheckIT(cond);
20608  Dt_size_10 encoded_dt(dt);
20609  if (IsUsingT32()) {
20610    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20611    if (dt.Is(F32)) {
20612      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20613        EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20614                   rm.Encode(5, 0));
20615        AdvanceIT();
20616        return;
20617      }
20618    }
20619    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20620    if (encoded_dt.IsValid()) {
20621      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20622        EmitT32_32(0xff000940U | (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 <Qd>, <Qn>, <Qm> ; A1
20630    if (dt.Is(F32)) {
20631      if (cond.Is(al)) {
20632        EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20633                rm.Encode(5, 0));
20634        return;
20635      }
20636    }
20637    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20638    if (encoded_dt.IsValid()) {
20639      if (cond.Is(al)) {
20640        EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
20641                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20642        return;
20643      }
20644    }
20645  }
20646  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20647}
20648
20649void Assembler::vmls(
20650    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20651  VIXL_ASSERT(AllowAssembler());
20652  CheckIT(cond);
20653  if (IsUsingT32()) {
20654    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20655    if (dt.Is(F32)) {
20656      EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20657                 rm.Encode(5, 0));
20658      AdvanceIT();
20659      return;
20660    }
20661  } else {
20662    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20663    if (dt.Is(F32) && cond.IsNotNever()) {
20664      EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20665              rn.Encode(7, 16) | rm.Encode(5, 0));
20666      return;
20667    }
20668  }
20669  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20670}
20671
20672void Assembler::vmlsl(
20673    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
20674  VIXL_ASSERT(AllowAssembler());
20675  CheckIT(cond);
20676  Dt_size_11 encoded_dt(dt);
20677  if (IsUsingT32()) {
20678    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20679    if (encoded_dt.IsValid() &&
20680        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20681         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20682          (rm.GetLane() <= 1)))) {
20683      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20684        EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
20685                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20686                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20687        AdvanceIT();
20688        return;
20689      }
20690    }
20691  } else {
20692    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20693    if (encoded_dt.IsValid() &&
20694        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20695         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20696          (rm.GetLane() <= 1)))) {
20697      if (cond.Is(al)) {
20698        EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
20699                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20700                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20701        return;
20702      }
20703    }
20704  }
20705  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20706}
20707
20708void Assembler::vmlsl(
20709    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
20710  VIXL_ASSERT(AllowAssembler());
20711  CheckIT(cond);
20712  Dt_size_12 encoded_dt(dt);
20713  if (IsUsingT32()) {
20714    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20715    if (encoded_dt.IsValid()) {
20716      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20717        EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
20718                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20719                   rn.Encode(7, 16) | rm.Encode(5, 0));
20720        AdvanceIT();
20721        return;
20722      }
20723    }
20724  } else {
20725    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20726    if (encoded_dt.IsValid()) {
20727      if (cond.Is(al)) {
20728        EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
20729                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20730                rn.Encode(7, 16) | rm.Encode(5, 0));
20731        return;
20732      }
20733    }
20734  }
20735  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20736}
20737
20738void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
20739  VIXL_ASSERT(AllowAssembler());
20740  CheckIT(cond);
20741  if (IsUsingT32()) {
20742    // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
20743    if ((!rt.IsPC() || AllowUnpredictable())) {
20744      EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
20745      AdvanceIT();
20746      return;
20747    }
20748  } else {
20749    // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
20750    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
20751      EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20752              rn.Encode(7, 16));
20753      return;
20754    }
20755  }
20756  Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
20757}
20758
20759void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
20760  VIXL_ASSERT(AllowAssembler());
20761  CheckIT(cond);
20762  if (IsUsingT32()) {
20763    // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
20764    if ((!rt.IsPC() || AllowUnpredictable())) {
20765      EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
20766      AdvanceIT();
20767      return;
20768    }
20769  } else {
20770    // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
20771    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
20772      EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
20773              (rt.GetCode() << 12));
20774      return;
20775    }
20776  }
20777  Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
20778}
20779
20780void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
20781  VIXL_ASSERT(AllowAssembler());
20782  CheckIT(cond);
20783  if (IsUsingT32()) {
20784    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
20785    if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20786      EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20787                 rm.Encode(5, 0));
20788      AdvanceIT();
20789      return;
20790    }
20791  } else {
20792    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
20793    if (cond.IsNotNever() &&
20794        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20795      EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20796              (rt2.GetCode() << 16) | rm.Encode(5, 0));
20797      return;
20798    }
20799  }
20800  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
20801}
20802
20803void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
20804  VIXL_ASSERT(AllowAssembler());
20805  CheckIT(cond);
20806  if (IsUsingT32()) {
20807    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
20808    if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20809      EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20810                 (rt2.GetCode() << 16));
20811      AdvanceIT();
20812      return;
20813    }
20814  } else {
20815    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
20816    if (cond.IsNotNever() &&
20817        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20818      EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20819              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20820      return;
20821    }
20822  }
20823  Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
20824}
20825
20826void Assembler::vmov(
20827    Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
20828  VIXL_ASSERT(AllowAssembler());
20829  CheckIT(cond);
20830  if (IsUsingT32()) {
20831    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
20832    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20833        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20834      EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20835                 rm.Encode(5, 0));
20836      AdvanceIT();
20837      return;
20838    }
20839  } else {
20840    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
20841    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20842        cond.IsNotNever() &&
20843        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20844      EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20845              (rt2.GetCode() << 16) | rm.Encode(5, 0));
20846      return;
20847    }
20848  }
20849  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
20850}
20851
20852void Assembler::vmov(
20853    Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
20854  VIXL_ASSERT(AllowAssembler());
20855  CheckIT(cond);
20856  if (IsUsingT32()) {
20857    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
20858    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20859        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20860      EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20861                 (rt2.GetCode() << 16));
20862      AdvanceIT();
20863      return;
20864    }
20865  } else {
20866    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
20867    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20868        cond.IsNotNever() &&
20869        ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20870      EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20871              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20872      return;
20873    }
20874  }
20875  Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
20876}
20877
20878void Assembler::vmov(Condition cond,
20879                     DataType dt,
20880                     DRegisterLane rd,
20881                     Register rt) {
20882  VIXL_ASSERT(AllowAssembler());
20883  CheckIT(cond);
20884  Dt_opc1_opc2_1 encoded_dt(dt, rd);
20885  if (IsUsingT32()) {
20886    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
20887    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
20888      EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20889                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
20890                 rd.Encode(7, 16) | (rt.GetCode() << 12));
20891      AdvanceIT();
20892      return;
20893    }
20894  } else {
20895    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
20896    if (encoded_dt.IsValid() && cond.IsNotNever() &&
20897        (!rt.IsPC() || AllowUnpredictable())) {
20898      EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
20899              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20900              ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
20901              (rt.GetCode() << 12));
20902      return;
20903    }
20904  }
20905  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
20906}
20907
20908void Assembler::vmov(Condition cond,
20909                     DataType dt,
20910                     DRegister rd,
20911                     const DOperand& operand) {
20912  VIXL_ASSERT(AllowAssembler());
20913  CheckIT(cond);
20914  if (operand.IsImmediate()) {
20915    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
20916    if (IsUsingT32()) {
20917      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20918      if (encoded_dt.IsValid()) {
20919        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20920          EmitT32_32(
20921              0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20922              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20923              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20924              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20925              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20926          AdvanceIT();
20927          return;
20928        }
20929      }
20930    } else {
20931      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20932      if (encoded_dt.IsValid()) {
20933        if (cond.Is(al)) {
20934          EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20935                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20936                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20937                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20938                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20939          return;
20940        }
20941      }
20942    }
20943  }
20944  if (operand.IsImmediate()) {
20945    ImmediateVFP vfp(operand.GetNeonImmediate());
20946    if (IsUsingT32()) {
20947      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
20948      if (dt.Is(F64) && vfp.IsValid()) {
20949        EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
20950                   (vfp.GetEncodingValue() & 0xf) |
20951                   ((vfp.GetEncodingValue() & 0xf0) << 12));
20952        AdvanceIT();
20953        return;
20954      }
20955    } else {
20956      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
20957      if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
20958        EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20959                (vfp.GetEncodingValue() & 0xf) |
20960                ((vfp.GetEncodingValue() & 0xf0) << 12));
20961        return;
20962      }
20963    }
20964  }
20965  if (operand.IsRegister()) {
20966    DRegister rm = operand.GetRegister();
20967    if (IsUsingT32()) {
20968      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
20969      if (dt.Is(F64)) {
20970        EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20971        AdvanceIT();
20972        return;
20973      }
20974      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
20975      if (!dt.Is(F64)) {
20976        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20977          EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
20978                     rm.Encode(5, 0));
20979          AdvanceIT();
20980          return;
20981        }
20982      }
20983    } else {
20984      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
20985      if (dt.Is(F64) && cond.IsNotNever()) {
20986        EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20987                rm.Encode(5, 0));
20988        return;
20989      }
20990      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
20991      if (!dt.Is(F64)) {
20992        if (cond.Is(al)) {
20993          EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
20994                  rm.Encode(5, 0));
20995          return;
20996        }
20997      }
20998    }
20999  }
21000  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21001}
21002
21003void Assembler::vmov(Condition cond,
21004                     DataType dt,
21005                     QRegister rd,
21006                     const QOperand& operand) {
21007  VIXL_ASSERT(AllowAssembler());
21008  CheckIT(cond);
21009  if (operand.IsImmediate()) {
21010    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
21011    if (IsUsingT32()) {
21012      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21013      if (encoded_dt.IsValid()) {
21014        if (cond.Is(al) || AllowStronglyDiscouraged()) {
21015          EmitT32_32(
21016              0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21017              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21018              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21019              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21020              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21021          AdvanceIT();
21022          return;
21023        }
21024      }
21025    } else {
21026      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21027      if (encoded_dt.IsValid()) {
21028        if (cond.Is(al)) {
21029          EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21030                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21031                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21032                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21033                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21034          return;
21035        }
21036      }
21037    }
21038  }
21039  if (operand.IsRegister()) {
21040    QRegister rm = operand.GetRegister();
21041    if (IsUsingT32()) {
21042      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21043      if (!dt.Is(F64)) {
21044        if (cond.Is(al) || AllowStronglyDiscouraged()) {
21045          EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21046                     rm.Encode(5, 0));
21047          AdvanceIT();
21048          return;
21049        }
21050      }
21051    } else {
21052      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21053      if (!dt.Is(F64)) {
21054        if (cond.Is(al)) {
21055          EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21056                  rm.Encode(5, 0));
21057          return;
21058        }
21059      }
21060    }
21061  }
21062  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21063}
21064
21065void Assembler::vmov(Condition cond,
21066                     DataType dt,
21067                     SRegister rd,
21068                     const SOperand& operand) {
21069  VIXL_ASSERT(AllowAssembler());
21070  CheckIT(cond);
21071  if (operand.IsImmediate()) {
21072    ImmediateVFP vfp(operand.GetNeonImmediate());
21073    if (IsUsingT32()) {
21074      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
21075      if (dt.Is(F32) && vfp.IsValid()) {
21076        EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
21077                   (vfp.GetEncodingValue() & 0xf) |
21078                   ((vfp.GetEncodingValue() & 0xf0) << 12));
21079        AdvanceIT();
21080        return;
21081      }
21082    } else {
21083      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
21084      if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
21085        EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21086                (vfp.GetEncodingValue() & 0xf) |
21087                ((vfp.GetEncodingValue() & 0xf0) << 12));
21088        return;
21089      }
21090    }
21091  }
21092  if (operand.IsRegister()) {
21093    SRegister rm = operand.GetRegister();
21094    if (IsUsingT32()) {
21095      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21096      if (dt.Is(F32)) {
21097        EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21098        AdvanceIT();
21099        return;
21100      }
21101    } else {
21102      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21103      if (dt.Is(F32) && cond.IsNotNever()) {
21104        EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21105                rm.Encode(5, 0));
21106        return;
21107      }
21108    }
21109  }
21110  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21111}
21112
21113void Assembler::vmov(Condition cond,
21114                     DataType dt,
21115                     Register rt,
21116                     DRegisterLane rn) {
21117  VIXL_ASSERT(AllowAssembler());
21118  CheckIT(cond);
21119  Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
21120  if (IsUsingT32()) {
21121    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
21122    if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
21123      EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21124                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21125                 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21126                 (rt.GetCode() << 12) | rn.Encode(7, 16));
21127      AdvanceIT();
21128      return;
21129    }
21130  } else {
21131    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
21132    if (encoded_dt.IsValid() && cond.IsNotNever() &&
21133        (!rt.IsPC() || AllowUnpredictable())) {
21134      EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
21135              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21136              ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21137              ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21138              (rt.GetCode() << 12) | rn.Encode(7, 16));
21139      return;
21140    }
21141  }
21142  Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
21143}
21144
21145void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
21146  VIXL_ASSERT(AllowAssembler());
21147  CheckIT(cond);
21148  Dt_U_imm3H_1 encoded_dt(dt);
21149  if (IsUsingT32()) {
21150    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
21151    if (encoded_dt.IsValid()) {
21152      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21153        EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21154                   ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
21155                   rd.Encode(22, 12) | rm.Encode(5, 0));
21156        AdvanceIT();
21157        return;
21158      }
21159    }
21160  } else {
21161    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
21162    if (encoded_dt.IsValid()) {
21163      if (cond.Is(al)) {
21164        EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21165                ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
21166                rd.Encode(22, 12) | rm.Encode(5, 0));
21167        return;
21168      }
21169    }
21170  }
21171  Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
21172}
21173
21174void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
21175  VIXL_ASSERT(AllowAssembler());
21176  CheckIT(cond);
21177  Dt_size_3 encoded_dt(dt);
21178  if (IsUsingT32()) {
21179    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21180    if (encoded_dt.IsValid()) {
21181      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21182        EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
21183                   rd.Encode(22, 12) | rm.Encode(5, 0));
21184        AdvanceIT();
21185        return;
21186      }
21187    }
21188  } else {
21189    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21190    if (encoded_dt.IsValid()) {
21191      if (cond.Is(al)) {
21192        EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
21193                rd.Encode(22, 12) | rm.Encode(5, 0));
21194        return;
21195      }
21196    }
21197  }
21198  Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
21199}
21200
21201void Assembler::vmrs(Condition cond,
21202                     RegisterOrAPSR_nzcv rt,
21203                     SpecialFPRegister spec_reg) {
21204  VIXL_ASSERT(AllowAssembler());
21205  CheckIT(cond);
21206  if (IsUsingT32()) {
21207    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
21208    EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
21209    AdvanceIT();
21210    return;
21211  } else {
21212    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
21213    if (cond.IsNotNever()) {
21214      EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
21215              (spec_reg.GetReg() << 16));
21216      return;
21217    }
21218  }
21219  Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
21220}
21221
21222void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
21223  VIXL_ASSERT(AllowAssembler());
21224  CheckIT(cond);
21225  if (IsUsingT32()) {
21226    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
21227    if ((!rt.IsPC() || AllowUnpredictable())) {
21228      EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) |
21229                 (rt.GetCode() << 12));
21230      AdvanceIT();
21231      return;
21232    }
21233  } else {
21234    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
21235    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
21236      EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
21237              (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
21238      return;
21239    }
21240  }
21241  Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
21242}
21243
21244void Assembler::vmul(Condition cond,
21245                     DataType dt,
21246                     DRegister rd,
21247                     DRegister rn,
21248                     DRegister dm,
21249                     unsigned index) {
21250  VIXL_ASSERT(AllowAssembler());
21251  CheckIT(cond);
21252  Dt_F_size_3 encoded_dt(dt);
21253  if (IsUsingT32()) {
21254    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
21255    if (encoded_dt.IsValid() &&
21256        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21257         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21258      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21259        uint32_t shift = 4;
21260        if (dt.Is(I16)) {
21261          shift = 3;
21262        }
21263        uint32_t mvm = dm.GetCode() | index << shift;
21264        EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21265                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21266                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21267                   ((mvm & 0x10) << 1));
21268        AdvanceIT();
21269        return;
21270      }
21271    }
21272  } else {
21273    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
21274    if (encoded_dt.IsValid() &&
21275        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21276         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21277      if (cond.Is(al)) {
21278        uint32_t shift = 4;
21279        if (dt.Is(I16)) {
21280          shift = 3;
21281        }
21282        uint32_t mvm = dm.GetCode() | index << shift;
21283        EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21284                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21285                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21286                ((mvm & 0x10) << 1));
21287        return;
21288      }
21289    }
21290  }
21291  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21292}
21293
21294void Assembler::vmul(Condition cond,
21295                     DataType dt,
21296                     QRegister rd,
21297                     QRegister rn,
21298                     DRegister dm,
21299                     unsigned index) {
21300  VIXL_ASSERT(AllowAssembler());
21301  CheckIT(cond);
21302  Dt_F_size_3 encoded_dt(dt);
21303  if (IsUsingT32()) {
21304    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
21305    if (encoded_dt.IsValid() &&
21306        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21307         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21308      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21309        uint32_t shift = 4;
21310        if (dt.Is(I16)) {
21311          shift = 3;
21312        }
21313        uint32_t mvm = dm.GetCode() | index << shift;
21314        EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21315                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21316                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21317                   ((mvm & 0x10) << 1));
21318        AdvanceIT();
21319        return;
21320      }
21321    }
21322  } else {
21323    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
21324    if (encoded_dt.IsValid() &&
21325        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21326         (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
21327      if (cond.Is(al)) {
21328        uint32_t shift = 4;
21329        if (dt.Is(I16)) {
21330          shift = 3;
21331        }
21332        uint32_t mvm = dm.GetCode() | index << shift;
21333        EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21334                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21335                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21336                ((mvm & 0x10) << 1));
21337        return;
21338      }
21339    }
21340  }
21341  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21342}
21343
21344void Assembler::vmul(
21345    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21346  VIXL_ASSERT(AllowAssembler());
21347  CheckIT(cond);
21348  Dt_op_size_1 encoded_dt(dt);
21349  if (IsUsingT32()) {
21350    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21351    if (dt.Is(F32)) {
21352      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21353        EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21354                   rm.Encode(5, 0));
21355        AdvanceIT();
21356        return;
21357      }
21358    }
21359    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
21360    if (dt.Is(F64)) {
21361      EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21362                 rm.Encode(5, 0));
21363      AdvanceIT();
21364      return;
21365    }
21366    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21367    if (encoded_dt.IsValid()) {
21368      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21369        EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21370                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21371                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21372        AdvanceIT();
21373        return;
21374      }
21375    }
21376  } else {
21377    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21378    if (dt.Is(F32)) {
21379      if (cond.Is(al)) {
21380        EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21381                rm.Encode(5, 0));
21382        return;
21383      }
21384    }
21385    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
21386    if (dt.Is(F64) && cond.IsNotNever()) {
21387      EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21388              rn.Encode(7, 16) | rm.Encode(5, 0));
21389      return;
21390    }
21391    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21392    if (encoded_dt.IsValid()) {
21393      if (cond.Is(al)) {
21394        EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21395                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21396                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21397        return;
21398      }
21399    }
21400  }
21401  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21402}
21403
21404void Assembler::vmul(
21405    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21406  VIXL_ASSERT(AllowAssembler());
21407  CheckIT(cond);
21408  Dt_op_size_1 encoded_dt(dt);
21409  if (IsUsingT32()) {
21410    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
21411    if (dt.Is(F32)) {
21412      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21413        EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21414                   rm.Encode(5, 0));
21415        AdvanceIT();
21416        return;
21417      }
21418    }
21419    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21420    if (encoded_dt.IsValid()) {
21421      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21422        EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21423                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21424                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21425        AdvanceIT();
21426        return;
21427      }
21428    }
21429  } else {
21430    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
21431    if (dt.Is(F32)) {
21432      if (cond.Is(al)) {
21433        EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21434                rm.Encode(5, 0));
21435        return;
21436      }
21437    }
21438    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21439    if (encoded_dt.IsValid()) {
21440      if (cond.Is(al)) {
21441        EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21442                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21443                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21444        return;
21445      }
21446    }
21447  }
21448  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21449}
21450
21451void Assembler::vmul(
21452    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21453  VIXL_ASSERT(AllowAssembler());
21454  CheckIT(cond);
21455  if (IsUsingT32()) {
21456    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
21457    if (dt.Is(F32)) {
21458      EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21459                 rm.Encode(5, 0));
21460      AdvanceIT();
21461      return;
21462    }
21463  } else {
21464    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
21465    if (dt.Is(F32) && cond.IsNotNever()) {
21466      EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21467              rn.Encode(7, 16) | rm.Encode(5, 0));
21468      return;
21469    }
21470  }
21471  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21472}
21473
21474void Assembler::vmull(Condition cond,
21475                      DataType dt,
21476                      QRegister rd,
21477                      DRegister rn,
21478                      DRegister dm,
21479                      unsigned index) {
21480  VIXL_ASSERT(AllowAssembler());
21481  CheckIT(cond);
21482  Dt_U_size_2 encoded_dt(dt);
21483  if (IsUsingT32()) {
21484    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
21485    if (encoded_dt.IsValid() &&
21486        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
21487         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21488          (dm.GetCode() <= 15)))) {
21489      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21490        uint32_t shift = 4;
21491        if (dt.Is(S16) || dt.Is(U16)) {
21492          shift = 3;
21493        }
21494        uint32_t mvm = dm.GetCode() | index << shift;
21495        EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21496                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21497                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21498                   ((mvm & 0x10) << 1));
21499        AdvanceIT();
21500        return;
21501      }
21502    }
21503  } else {
21504    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
21505    if (encoded_dt.IsValid() &&
21506        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
21507         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21508          (dm.GetCode() <= 15)))) {
21509      if (cond.Is(al)) {
21510        uint32_t shift = 4;
21511        if (dt.Is(S16) || dt.Is(U16)) {
21512          shift = 3;
21513        }
21514        uint32_t mvm = dm.GetCode() | index << shift;
21515        EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21516                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21517                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21518                ((mvm & 0x10) << 1));
21519        return;
21520      }
21521    }
21522  }
21523  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
21524}
21525
21526void Assembler::vmull(
21527    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21528  VIXL_ASSERT(AllowAssembler());
21529  CheckIT(cond);
21530  Dt_op_U_size_1 encoded_dt(dt);
21531  if (IsUsingT32()) {
21532    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21533    if (encoded_dt.IsValid()) {
21534      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21535        EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21536                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21537                   ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21538                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21539        AdvanceIT();
21540        return;
21541      }
21542    }
21543  } else {
21544    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21545    if (encoded_dt.IsValid()) {
21546      if (cond.Is(al)) {
21547        EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21548                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21549                ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21550                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21551        return;
21552      }
21553    }
21554  }
21555  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
21556}
21557
21558void Assembler::vmvn(Condition cond,
21559                     DataType dt,
21560                     DRegister rd,
21561                     const DOperand& operand) {
21562  VIXL_ASSERT(AllowAssembler());
21563  CheckIT(cond);
21564  if (operand.IsImmediate()) {
21565    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
21566    if (IsUsingT32()) {
21567      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
21568      if (encoded_dt.IsValid()) {
21569        if (cond.Is(al) || AllowStronglyDiscouraged()) {
21570          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
21571                     rd.Encode(22, 12) |
21572                     (encoded_dt.GetEncodedImmediate() & 0xf) |
21573                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21574                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21575          AdvanceIT();
21576          return;
21577        }
21578      }
21579    } else {
21580      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
21581      if (encoded_dt.IsValid()) {
21582        if (cond.Is(al)) {
21583          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
21584                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21585                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21586                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21587          return;
21588        }
21589      }
21590    }
21591  }
21592  if (operand.IsRegister()) {
21593    DRegister rm = operand.GetRegister();
21594    USE(dt);
21595    if (IsUsingT32()) {
21596      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21597      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21598        EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21599        AdvanceIT();
21600        return;
21601      }
21602    } else {
21603      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21604      if (cond.Is(al)) {
21605        EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21606        return;
21607      }
21608    }
21609  }
21610  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21611}
21612
21613void Assembler::vmvn(Condition cond,
21614                     DataType dt,
21615                     QRegister rd,
21616                     const QOperand& operand) {
21617  VIXL_ASSERT(AllowAssembler());
21618  CheckIT(cond);
21619  if (operand.IsImmediate()) {
21620    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
21621    if (IsUsingT32()) {
21622      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21623      if (encoded_dt.IsValid()) {
21624        if (cond.Is(al) || AllowStronglyDiscouraged()) {
21625          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
21626                     rd.Encode(22, 12) |
21627                     (encoded_dt.GetEncodedImmediate() & 0xf) |
21628                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21629                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21630          AdvanceIT();
21631          return;
21632        }
21633      }
21634    } else {
21635      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21636      if (encoded_dt.IsValid()) {
21637        if (cond.Is(al)) {
21638          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
21639                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21640                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21641                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21642          return;
21643        }
21644      }
21645    }
21646  }
21647  if (operand.IsRegister()) {
21648    QRegister rm = operand.GetRegister();
21649    USE(dt);
21650    if (IsUsingT32()) {
21651      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21652      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21653        EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21654        AdvanceIT();
21655        return;
21656      }
21657    } else {
21658      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21659      if (cond.Is(al)) {
21660        EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21661        return;
21662      }
21663    }
21664  }
21665  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21666}
21667
21668void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
21669  VIXL_ASSERT(AllowAssembler());
21670  CheckIT(cond);
21671  Dt_F_size_1 encoded_dt(dt);
21672  if (IsUsingT32()) {
21673    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21674    if (encoded_dt.IsValid()) {
21675      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21676        EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21677                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21678                   rd.Encode(22, 12) | rm.Encode(5, 0));
21679        AdvanceIT();
21680        return;
21681      }
21682    }
21683    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21684    if (dt.Is(F64)) {
21685      EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21686      AdvanceIT();
21687      return;
21688    }
21689  } else {
21690    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21691    if (encoded_dt.IsValid()) {
21692      if (cond.Is(al)) {
21693        EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21694                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21695                rd.Encode(22, 12) | rm.Encode(5, 0));
21696        return;
21697      }
21698    }
21699    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21700    if (dt.Is(F64) && cond.IsNotNever()) {
21701      EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21702              rm.Encode(5, 0));
21703      return;
21704    }
21705  }
21706  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21707}
21708
21709void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
21710  VIXL_ASSERT(AllowAssembler());
21711  CheckIT(cond);
21712  Dt_F_size_1 encoded_dt(dt);
21713  if (IsUsingT32()) {
21714    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21715    if (encoded_dt.IsValid()) {
21716      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21717        EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21718                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21719                   rd.Encode(22, 12) | rm.Encode(5, 0));
21720        AdvanceIT();
21721        return;
21722      }
21723    }
21724  } else {
21725    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21726    if (encoded_dt.IsValid()) {
21727      if (cond.Is(al)) {
21728        EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21729                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21730                rd.Encode(22, 12) | rm.Encode(5, 0));
21731        return;
21732      }
21733    }
21734  }
21735  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21736}
21737
21738void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
21739  VIXL_ASSERT(AllowAssembler());
21740  CheckIT(cond);
21741  if (IsUsingT32()) {
21742    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21743    if (dt.Is(F32)) {
21744      EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21745      AdvanceIT();
21746      return;
21747    }
21748  } else {
21749    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21750    if (dt.Is(F32) && cond.IsNotNever()) {
21751      EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21752              rm.Encode(5, 0));
21753      return;
21754    }
21755  }
21756  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21757}
21758
21759void Assembler::vnmla(
21760    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21761  VIXL_ASSERT(AllowAssembler());
21762  CheckIT(cond);
21763  if (IsUsingT32()) {
21764    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21765    if (dt.Is(F32)) {
21766      EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21767                 rm.Encode(5, 0));
21768      AdvanceIT();
21769      return;
21770    }
21771  } else {
21772    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21773    if (dt.Is(F32) && cond.IsNotNever()) {
21774      EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21775              rn.Encode(7, 16) | rm.Encode(5, 0));
21776      return;
21777    }
21778  }
21779  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21780}
21781
21782void Assembler::vnmla(
21783    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21784  VIXL_ASSERT(AllowAssembler());
21785  CheckIT(cond);
21786  if (IsUsingT32()) {
21787    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21788    if (dt.Is(F64)) {
21789      EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21790                 rm.Encode(5, 0));
21791      AdvanceIT();
21792      return;
21793    }
21794  } else {
21795    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21796    if (dt.Is(F64) && cond.IsNotNever()) {
21797      EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21798              rn.Encode(7, 16) | rm.Encode(5, 0));
21799      return;
21800    }
21801  }
21802  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21803}
21804
21805void Assembler::vnmls(
21806    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21807  VIXL_ASSERT(AllowAssembler());
21808  CheckIT(cond);
21809  if (IsUsingT32()) {
21810    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21811    if (dt.Is(F32)) {
21812      EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21813                 rm.Encode(5, 0));
21814      AdvanceIT();
21815      return;
21816    }
21817  } else {
21818    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21819    if (dt.Is(F32) && cond.IsNotNever()) {
21820      EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21821              rn.Encode(7, 16) | rm.Encode(5, 0));
21822      return;
21823    }
21824  }
21825  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21826}
21827
21828void Assembler::vnmls(
21829    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21830  VIXL_ASSERT(AllowAssembler());
21831  CheckIT(cond);
21832  if (IsUsingT32()) {
21833    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21834    if (dt.Is(F64)) {
21835      EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21836                 rm.Encode(5, 0));
21837      AdvanceIT();
21838      return;
21839    }
21840  } else {
21841    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21842    if (dt.Is(F64) && cond.IsNotNever()) {
21843      EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21844              rn.Encode(7, 16) | rm.Encode(5, 0));
21845      return;
21846    }
21847  }
21848  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21849}
21850
21851void Assembler::vnmul(
21852    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
21853  VIXL_ASSERT(AllowAssembler());
21854  CheckIT(cond);
21855  if (IsUsingT32()) {
21856    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
21857    if (dt.Is(F32)) {
21858      EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21859                 rm.Encode(5, 0));
21860      AdvanceIT();
21861      return;
21862    }
21863  } else {
21864    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
21865    if (dt.Is(F32) && cond.IsNotNever()) {
21866      EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21867              rn.Encode(7, 16) | rm.Encode(5, 0));
21868      return;
21869    }
21870  }
21871  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21872}
21873
21874void Assembler::vnmul(
21875    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21876  VIXL_ASSERT(AllowAssembler());
21877  CheckIT(cond);
21878  if (IsUsingT32()) {
21879    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
21880    if (dt.Is(F64)) {
21881      EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21882                 rm.Encode(5, 0));
21883      AdvanceIT();
21884      return;
21885    }
21886  } else {
21887    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
21888    if (dt.Is(F64) && cond.IsNotNever()) {
21889      EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21890              rn.Encode(7, 16) | rm.Encode(5, 0));
21891      return;
21892    }
21893  }
21894  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21895}
21896
21897void Assembler::vorn(Condition cond,
21898                     DataType dt,
21899                     DRegister rd,
21900                     DRegister rn,
21901                     const DOperand& operand) {
21902  VIXL_ASSERT(AllowAssembler());
21903  CheckIT(cond);
21904  if (operand.IsImmediate()) {
21905    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
21906    if (IsUsingT32()) {
21907      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
21908      if (encoded_dt.IsValid() && rd.Is(rn)) {
21909        if (cond.Is(al) || AllowStronglyDiscouraged()) {
21910          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
21911                     rd.Encode(22, 12) |
21912                     (encoded_dt.GetEncodedImmediate() & 0xf) |
21913                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21914                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21915          AdvanceIT();
21916          return;
21917        }
21918      }
21919    } else {
21920      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
21921      if (encoded_dt.IsValid() && rd.Is(rn)) {
21922        if (cond.Is(al)) {
21923          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
21924                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21925                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21926                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21927          return;
21928        }
21929      }
21930    }
21931  }
21932  if (operand.IsRegister()) {
21933    DRegister rm = operand.GetRegister();
21934    USE(dt);
21935    if (IsUsingT32()) {
21936      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
21937      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21938        EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21939                   rm.Encode(5, 0));
21940        AdvanceIT();
21941        return;
21942      }
21943    } else {
21944      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
21945      if (cond.Is(al)) {
21946        EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21947                rm.Encode(5, 0));
21948        return;
21949      }
21950    }
21951  }
21952  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
21953}
21954
21955void Assembler::vorn(Condition cond,
21956                     DataType dt,
21957                     QRegister rd,
21958                     QRegister rn,
21959                     const QOperand& operand) {
21960  VIXL_ASSERT(AllowAssembler());
21961  CheckIT(cond);
21962  if (operand.IsImmediate()) {
21963    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
21964    if (IsUsingT32()) {
21965      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
21966      if (encoded_dt.IsValid() && rd.Is(rn)) {
21967        if (cond.Is(al) || AllowStronglyDiscouraged()) {
21968          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
21969                     rd.Encode(22, 12) |
21970                     (encoded_dt.GetEncodedImmediate() & 0xf) |
21971                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21972                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21973          AdvanceIT();
21974          return;
21975        }
21976      }
21977    } else {
21978      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
21979      if (encoded_dt.IsValid() && rd.Is(rn)) {
21980        if (cond.Is(al)) {
21981          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
21982                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21983                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21984                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21985          return;
21986        }
21987      }
21988    }
21989  }
21990  if (operand.IsRegister()) {
21991    QRegister rm = operand.GetRegister();
21992    USE(dt);
21993    if (IsUsingT32()) {
21994      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
21995      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21996        EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21997                   rm.Encode(5, 0));
21998        AdvanceIT();
21999        return;
22000      }
22001    } else {
22002      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22003      if (cond.Is(al)) {
22004        EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22005                rm.Encode(5, 0));
22006        return;
22007      }
22008    }
22009  }
22010  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
22011}
22012
22013void Assembler::vorr(Condition cond,
22014                     DataType dt,
22015                     DRegister rd,
22016                     DRegister rn,
22017                     const DOperand& operand) {
22018  VIXL_ASSERT(AllowAssembler());
22019  CheckIT(cond);
22020  if (operand.IsRegister()) {
22021    DRegister rm = operand.GetRegister();
22022    USE(dt);
22023    if (IsUsingT32()) {
22024      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
22025      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22026        EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22027                   rm.Encode(5, 0));
22028        AdvanceIT();
22029        return;
22030      }
22031    } else {
22032      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
22033      if (cond.Is(al)) {
22034        EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22035                rm.Encode(5, 0));
22036        return;
22037      }
22038    }
22039  }
22040  if (operand.IsImmediate()) {
22041    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
22042    if (IsUsingT32()) {
22043      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
22044      if (encoded_dt.IsValid() && rd.Is(rn)) {
22045        if (cond.Is(al) || AllowStronglyDiscouraged()) {
22046          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
22047                     rd.Encode(22, 12) |
22048                     (encoded_dt.GetEncodedImmediate() & 0xf) |
22049                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22050                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22051          AdvanceIT();
22052          return;
22053        }
22054      }
22055    } else {
22056      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
22057      if (encoded_dt.IsValid() && rd.Is(rn)) {
22058        if (cond.Is(al)) {
22059          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
22060                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22061                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22062                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22063          return;
22064        }
22065      }
22066    }
22067  }
22068  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22069}
22070
22071void Assembler::vorr(Condition cond,
22072                     DataType dt,
22073                     QRegister rd,
22074                     QRegister rn,
22075                     const QOperand& operand) {
22076  VIXL_ASSERT(AllowAssembler());
22077  CheckIT(cond);
22078  if (operand.IsRegister()) {
22079    QRegister rm = operand.GetRegister();
22080    USE(dt);
22081    if (IsUsingT32()) {
22082      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22083      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22084        EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22085                   rm.Encode(5, 0));
22086        AdvanceIT();
22087        return;
22088      }
22089    } else {
22090      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22091      if (cond.Is(al)) {
22092        EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22093                rm.Encode(5, 0));
22094        return;
22095      }
22096    }
22097  }
22098  if (operand.IsImmediate()) {
22099    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
22100    if (IsUsingT32()) {
22101      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22102      if (encoded_dt.IsValid() && rd.Is(rn)) {
22103        if (cond.Is(al) || AllowStronglyDiscouraged()) {
22104          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22105                     rd.Encode(22, 12) |
22106                     (encoded_dt.GetEncodedImmediate() & 0xf) |
22107                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22108                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22109          AdvanceIT();
22110          return;
22111        }
22112      }
22113    } else {
22114      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22115      if (encoded_dt.IsValid() && rd.Is(rn)) {
22116        if (cond.Is(al)) {
22117          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22118                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22119                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22120                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22121          return;
22122        }
22123      }
22124    }
22125  }
22126  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22127}
22128
22129void Assembler::vpadal(Condition cond,
22130                       DataType dt,
22131                       DRegister rd,
22132                       DRegister rm) {
22133  VIXL_ASSERT(AllowAssembler());
22134  CheckIT(cond);
22135  Dt_op_size_2 encoded_dt(dt);
22136  if (IsUsingT32()) {
22137    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22138    if (encoded_dt.IsValid()) {
22139      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22140        EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22141                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22142                   rd.Encode(22, 12) | rm.Encode(5, 0));
22143        AdvanceIT();
22144        return;
22145      }
22146    }
22147  } else {
22148    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22149    if (encoded_dt.IsValid()) {
22150      if (cond.Is(al)) {
22151        EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22152                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22153                rd.Encode(22, 12) | rm.Encode(5, 0));
22154        return;
22155      }
22156    }
22157  }
22158  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22159}
22160
22161void Assembler::vpadal(Condition cond,
22162                       DataType dt,
22163                       QRegister rd,
22164                       QRegister rm) {
22165  VIXL_ASSERT(AllowAssembler());
22166  CheckIT(cond);
22167  Dt_op_size_2 encoded_dt(dt);
22168  if (IsUsingT32()) {
22169    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22170    if (encoded_dt.IsValid()) {
22171      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22172        EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22173                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22174                   rd.Encode(22, 12) | rm.Encode(5, 0));
22175        AdvanceIT();
22176        return;
22177      }
22178    }
22179  } else {
22180    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22181    if (encoded_dt.IsValid()) {
22182      if (cond.Is(al)) {
22183        EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22184                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22185                rd.Encode(22, 12) | rm.Encode(5, 0));
22186        return;
22187      }
22188    }
22189  }
22190  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22191}
22192
22193void Assembler::vpadd(
22194    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22195  VIXL_ASSERT(AllowAssembler());
22196  CheckIT(cond);
22197  Dt_size_4 encoded_dt(dt);
22198  if (IsUsingT32()) {
22199    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22200    if (dt.Is(F32)) {
22201      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22202        EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22203                   rm.Encode(5, 0));
22204        AdvanceIT();
22205        return;
22206      }
22207    }
22208    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22209    if (encoded_dt.IsValid()) {
22210      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22211        EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
22212                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22213        AdvanceIT();
22214        return;
22215      }
22216    }
22217  } else {
22218    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22219    if (dt.Is(F32)) {
22220      if (cond.Is(al)) {
22221        EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22222                rm.Encode(5, 0));
22223        return;
22224      }
22225    }
22226    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22227    if (encoded_dt.IsValid()) {
22228      if (cond.Is(al)) {
22229        EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
22230                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22231        return;
22232      }
22233    }
22234  }
22235  Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
22236}
22237
22238void Assembler::vpaddl(Condition cond,
22239                       DataType dt,
22240                       DRegister rd,
22241                       DRegister rm) {
22242  VIXL_ASSERT(AllowAssembler());
22243  CheckIT(cond);
22244  Dt_op_size_2 encoded_dt(dt);
22245  if (IsUsingT32()) {
22246    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22247    if (encoded_dt.IsValid()) {
22248      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22249        EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22250                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22251                   rd.Encode(22, 12) | rm.Encode(5, 0));
22252        AdvanceIT();
22253        return;
22254      }
22255    }
22256  } else {
22257    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22258    if (encoded_dt.IsValid()) {
22259      if (cond.Is(al)) {
22260        EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22261                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22262                rd.Encode(22, 12) | rm.Encode(5, 0));
22263        return;
22264      }
22265    }
22266  }
22267  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22268}
22269
22270void Assembler::vpaddl(Condition cond,
22271                       DataType dt,
22272                       QRegister rd,
22273                       QRegister rm) {
22274  VIXL_ASSERT(AllowAssembler());
22275  CheckIT(cond);
22276  Dt_op_size_2 encoded_dt(dt);
22277  if (IsUsingT32()) {
22278    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22279    if (encoded_dt.IsValid()) {
22280      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22281        EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22282                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22283                   rd.Encode(22, 12) | rm.Encode(5, 0));
22284        AdvanceIT();
22285        return;
22286      }
22287    }
22288  } else {
22289    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22290    if (encoded_dt.IsValid()) {
22291      if (cond.Is(al)) {
22292        EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22293                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22294                rd.Encode(22, 12) | rm.Encode(5, 0));
22295        return;
22296      }
22297    }
22298  }
22299  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22300}
22301
22302void Assembler::vpmax(
22303    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22304  VIXL_ASSERT(AllowAssembler());
22305  CheckIT(cond);
22306  Dt_U_size_1 encoded_dt(dt);
22307  if (IsUsingT32()) {
22308    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22309    if (dt.Is(F32)) {
22310      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22311        EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22312                   rm.Encode(5, 0));
22313        AdvanceIT();
22314        return;
22315      }
22316    }
22317    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22318    if (encoded_dt.IsValid()) {
22319      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22320        EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22321                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22322                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22323        AdvanceIT();
22324        return;
22325      }
22326    }
22327  } else {
22328    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22329    if (dt.Is(F32)) {
22330      if (cond.Is(al)) {
22331        EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22332                rm.Encode(5, 0));
22333        return;
22334      }
22335    }
22336    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22337    if (encoded_dt.IsValid()) {
22338      if (cond.Is(al)) {
22339        EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22340                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22341                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22342        return;
22343      }
22344    }
22345  }
22346  Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
22347}
22348
22349void Assembler::vpmin(
22350    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22351  VIXL_ASSERT(AllowAssembler());
22352  CheckIT(cond);
22353  Dt_U_size_1 encoded_dt(dt);
22354  if (IsUsingT32()) {
22355    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22356    if (dt.Is(F32)) {
22357      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22358        EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22359                   rm.Encode(5, 0));
22360        AdvanceIT();
22361        return;
22362      }
22363    }
22364    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22365    if (encoded_dt.IsValid()) {
22366      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22367        EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22368                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22369                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22370        AdvanceIT();
22371        return;
22372      }
22373    }
22374  } else {
22375    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22376    if (dt.Is(F32)) {
22377      if (cond.Is(al)) {
22378        EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22379                rm.Encode(5, 0));
22380        return;
22381      }
22382    }
22383    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22384    if (encoded_dt.IsValid()) {
22385      if (cond.Is(al)) {
22386        EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22387                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22388                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22389        return;
22390      }
22391    }
22392  }
22393  Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
22394}
22395
22396void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
22397  VIXL_ASSERT(AllowAssembler());
22398  CheckIT(cond);
22399  USE(dt);
22400  if (IsUsingT32()) {
22401    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
22402    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
22403      const DRegister& dreg = dreglist.GetFirstDRegister();
22404      unsigned len = dreglist.GetLength() * 2;
22405      EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
22406      AdvanceIT();
22407      return;
22408    }
22409  } else {
22410    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
22411    if (cond.IsNotNever() &&
22412        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
22413      const DRegister& dreg = dreglist.GetFirstDRegister();
22414      unsigned len = dreglist.GetLength() * 2;
22415      EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22416              (len & 0xff));
22417      return;
22418    }
22419  }
22420  Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
22421}
22422
22423void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
22424  VIXL_ASSERT(AllowAssembler());
22425  CheckIT(cond);
22426  USE(dt);
22427  if (IsUsingT32()) {
22428    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
22429    const SRegister& sreg = sreglist.GetFirstSRegister();
22430    unsigned len = sreglist.GetLength();
22431    EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
22432    AdvanceIT();
22433    return;
22434  } else {
22435    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
22436    if (cond.IsNotNever()) {
22437      const SRegister& sreg = sreglist.GetFirstSRegister();
22438      unsigned len = sreglist.GetLength();
22439      EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22440              (len & 0xff));
22441      return;
22442    }
22443  }
22444  Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
22445}
22446
22447void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
22448  VIXL_ASSERT(AllowAssembler());
22449  CheckIT(cond);
22450  USE(dt);
22451  if (IsUsingT32()) {
22452    // VPUSH{<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(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
22457      AdvanceIT();
22458      return;
22459    }
22460  } else {
22461    // VPUSH{<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(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22467              (len & 0xff));
22468      return;
22469    }
22470  }
22471  Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
22472}
22473
22474void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
22475  VIXL_ASSERT(AllowAssembler());
22476  CheckIT(cond);
22477  USE(dt);
22478  if (IsUsingT32()) {
22479    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
22480    const SRegister& sreg = sreglist.GetFirstSRegister();
22481    unsigned len = sreglist.GetLength();
22482    EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
22483    AdvanceIT();
22484    return;
22485  } else {
22486    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
22487    if (cond.IsNotNever()) {
22488      const SRegister& sreg = sreglist.GetFirstSRegister();
22489      unsigned len = sreglist.GetLength();
22490      EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22491              (len & 0xff));
22492      return;
22493    }
22494  }
22495  Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
22496}
22497
22498void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
22499  VIXL_ASSERT(AllowAssembler());
22500  CheckIT(cond);
22501  Dt_size_5 encoded_dt(dt);
22502  if (IsUsingT32()) {
22503    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22504    if (encoded_dt.IsValid()) {
22505      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22506        EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
22507                   rd.Encode(22, 12) | rm.Encode(5, 0));
22508        AdvanceIT();
22509        return;
22510      }
22511    }
22512  } else {
22513    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22514    if (encoded_dt.IsValid()) {
22515      if (cond.Is(al)) {
22516        EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
22517                rd.Encode(22, 12) | rm.Encode(5, 0));
22518        return;
22519      }
22520    }
22521  }
22522  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22523}
22524
22525void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
22526  VIXL_ASSERT(AllowAssembler());
22527  CheckIT(cond);
22528  Dt_size_5 encoded_dt(dt);
22529  if (IsUsingT32()) {
22530    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22531    if (encoded_dt.IsValid()) {
22532      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22533        EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
22534                   rd.Encode(22, 12) | rm.Encode(5, 0));
22535        AdvanceIT();
22536        return;
22537      }
22538    }
22539  } else {
22540    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22541    if (encoded_dt.IsValid()) {
22542      if (cond.Is(al)) {
22543        EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
22544                rd.Encode(22, 12) | rm.Encode(5, 0));
22545        return;
22546      }
22547    }
22548  }
22549  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22550}
22551
22552void Assembler::vqadd(
22553    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22554  VIXL_ASSERT(AllowAssembler());
22555  CheckIT(cond);
22556  Dt_U_size_3 encoded_dt(dt);
22557  if (IsUsingT32()) {
22558    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22559    if (encoded_dt.IsValid()) {
22560      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22561        EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22562                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22563                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22564        AdvanceIT();
22565        return;
22566      }
22567    }
22568  } else {
22569    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22570    if (encoded_dt.IsValid()) {
22571      if (cond.Is(al)) {
22572        EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22573                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22574                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22575        return;
22576      }
22577    }
22578  }
22579  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22580}
22581
22582void Assembler::vqadd(
22583    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22584  VIXL_ASSERT(AllowAssembler());
22585  CheckIT(cond);
22586  Dt_U_size_3 encoded_dt(dt);
22587  if (IsUsingT32()) {
22588    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22589    if (encoded_dt.IsValid()) {
22590      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22591        EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22592                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22593                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22594        AdvanceIT();
22595        return;
22596      }
22597    }
22598  } else {
22599    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22600    if (encoded_dt.IsValid()) {
22601      if (cond.Is(al)) {
22602        EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22603                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22604                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22605        return;
22606      }
22607    }
22608  }
22609  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22610}
22611
22612void Assembler::vqdmlal(
22613    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
22614  VIXL_ASSERT(AllowAssembler());
22615  CheckIT(cond);
22616  Dt_size_13 encoded_dt(dt);
22617  if (IsUsingT32()) {
22618    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22619    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22620      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22621        EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
22622                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22623        AdvanceIT();
22624        return;
22625      }
22626    }
22627  } else {
22628    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22629    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22630      if (cond.Is(al)) {
22631        EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
22632                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22633        return;
22634      }
22635    }
22636  }
22637  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
22638}
22639
22640void Assembler::vqdmlal(Condition cond,
22641                        DataType dt,
22642                        QRegister rd,
22643                        DRegister rn,
22644                        DRegister dm,
22645                        unsigned index) {
22646  VIXL_ASSERT(AllowAssembler());
22647  CheckIT(cond);
22648  Dt_size_13 encoded_dt(dt);
22649  if (IsUsingT32()) {
22650    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22651    if (encoded_dt.IsValid() &&
22652        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22653         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22654        (dt.Is(S16) || dt.Is(S32))) {
22655      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22656        uint32_t shift = 4;
22657        if (dt.Is(S16)) {
22658          shift = 3;
22659        }
22660        uint32_t mvm = dm.GetCode() | index << shift;
22661        EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
22662                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22663                   ((mvm & 0x10) << 1));
22664        AdvanceIT();
22665        return;
22666      }
22667    }
22668  } else {
22669    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22670    if (encoded_dt.IsValid() &&
22671        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22672         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22673        (dt.Is(S16) || dt.Is(S32))) {
22674      if (cond.Is(al)) {
22675        uint32_t shift = 4;
22676        if (dt.Is(S16)) {
22677          shift = 3;
22678        }
22679        uint32_t mvm = dm.GetCode() | index << shift;
22680        EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
22681                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22682                ((mvm & 0x10) << 1));
22683        return;
22684      }
22685    }
22686  }
22687  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
22688}
22689
22690void Assembler::vqdmlsl(
22691    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
22692  VIXL_ASSERT(AllowAssembler());
22693  CheckIT(cond);
22694  Dt_size_13 encoded_dt(dt);
22695  if (IsUsingT32()) {
22696    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22697    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22698      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22699        EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
22700                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22701        AdvanceIT();
22702        return;
22703      }
22704    }
22705  } else {
22706    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22707    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22708      if (cond.Is(al)) {
22709        EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
22710                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22711        return;
22712      }
22713    }
22714  }
22715  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
22716}
22717
22718void Assembler::vqdmlsl(Condition cond,
22719                        DataType dt,
22720                        QRegister rd,
22721                        DRegister rn,
22722                        DRegister dm,
22723                        unsigned index) {
22724  VIXL_ASSERT(AllowAssembler());
22725  CheckIT(cond);
22726  Dt_size_13 encoded_dt(dt);
22727  if (IsUsingT32()) {
22728    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22729    if (encoded_dt.IsValid() &&
22730        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22731         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22732        (dt.Is(S16) || dt.Is(S32))) {
22733      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22734        uint32_t shift = 4;
22735        if (dt.Is(S16)) {
22736          shift = 3;
22737        }
22738        uint32_t mvm = dm.GetCode() | index << shift;
22739        EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
22740                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22741                   ((mvm & 0x10) << 1));
22742        AdvanceIT();
22743        return;
22744      }
22745    }
22746  } else {
22747    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22748    if (encoded_dt.IsValid() &&
22749        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22750         (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
22751        (dt.Is(S16) || dt.Is(S32))) {
22752      if (cond.Is(al)) {
22753        uint32_t shift = 4;
22754        if (dt.Is(S16)) {
22755          shift = 3;
22756        }
22757        uint32_t mvm = dm.GetCode() | index << shift;
22758        EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
22759                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22760                ((mvm & 0x10) << 1));
22761        return;
22762      }
22763    }
22764  }
22765  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
22766}
22767
22768void Assembler::vqdmulh(
22769    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22770  VIXL_ASSERT(AllowAssembler());
22771  CheckIT(cond);
22772  Dt_size_13 encoded_dt(dt);
22773  if (IsUsingT32()) {
22774    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22775    if (encoded_dt.IsValid()) {
22776      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22777        EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
22778                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22779        AdvanceIT();
22780        return;
22781      }
22782    }
22783  } else {
22784    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22785    if (encoded_dt.IsValid()) {
22786      if (cond.Is(al)) {
22787        EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
22788                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22789        return;
22790      }
22791    }
22792  }
22793  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22794}
22795
22796void Assembler::vqdmulh(
22797    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22798  VIXL_ASSERT(AllowAssembler());
22799  CheckIT(cond);
22800  Dt_size_13 encoded_dt(dt);
22801  if (IsUsingT32()) {
22802    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22803    if (encoded_dt.IsValid()) {
22804      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22805        EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
22806                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22807        AdvanceIT();
22808        return;
22809      }
22810    }
22811  } else {
22812    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22813    if (encoded_dt.IsValid()) {
22814      if (cond.Is(al)) {
22815        EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
22816                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22817        return;
22818      }
22819    }
22820  }
22821  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22822}
22823
22824void Assembler::vqdmulh(
22825    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
22826  VIXL_ASSERT(AllowAssembler());
22827  CheckIT(cond);
22828  Dt_size_13 encoded_dt(dt);
22829  if (IsUsingT32()) {
22830    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
22831    if (encoded_dt.IsValid() &&
22832        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22833         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22834          (rm.GetLane() <= 1))) &&
22835        (dt.Is(S16) || dt.Is(S32))) {
22836      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22837        EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
22838                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22839        AdvanceIT();
22840        return;
22841      }
22842    }
22843  } else {
22844    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
22845    if (encoded_dt.IsValid() &&
22846        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22847         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22848          (rm.GetLane() <= 1))) &&
22849        (dt.Is(S16) || dt.Is(S32))) {
22850      if (cond.Is(al)) {
22851        EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
22852                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22853        return;
22854      }
22855    }
22856  }
22857  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22858}
22859
22860void Assembler::vqdmulh(
22861    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
22862  VIXL_ASSERT(AllowAssembler());
22863  CheckIT(cond);
22864  Dt_size_13 encoded_dt(dt);
22865  if (IsUsingT32()) {
22866    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
22867    if (encoded_dt.IsValid() &&
22868        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22869         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22870          (rm.GetLane() <= 1))) &&
22871        (dt.Is(S16) || dt.Is(S32))) {
22872      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22873        EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
22874                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22875        AdvanceIT();
22876        return;
22877      }
22878    }
22879  } else {
22880    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
22881    if (encoded_dt.IsValid() &&
22882        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22883         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22884          (rm.GetLane() <= 1))) &&
22885        (dt.Is(S16) || dt.Is(S32))) {
22886      if (cond.Is(al)) {
22887        EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
22888                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22889        return;
22890      }
22891    }
22892  }
22893  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22894}
22895
22896void Assembler::vqdmull(
22897    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
22898  VIXL_ASSERT(AllowAssembler());
22899  CheckIT(cond);
22900  Dt_size_13 encoded_dt(dt);
22901  if (IsUsingT32()) {
22902    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22903    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22904      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22905        EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
22906                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22907        AdvanceIT();
22908        return;
22909      }
22910    }
22911  } else {
22912    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22913    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22914      if (cond.Is(al)) {
22915        EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
22916                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22917        return;
22918      }
22919    }
22920  }
22921  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22922}
22923
22924void Assembler::vqdmull(
22925    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
22926  VIXL_ASSERT(AllowAssembler());
22927  CheckIT(cond);
22928  Dt_size_13 encoded_dt(dt);
22929  if (IsUsingT32()) {
22930    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
22931    if (encoded_dt.IsValid() &&
22932        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22933         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22934          (rm.GetLane() <= 1))) &&
22935        (dt.Is(S16) || dt.Is(S32))) {
22936      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22937        EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
22938                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22939        AdvanceIT();
22940        return;
22941      }
22942    }
22943  } else {
22944    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
22945    if (encoded_dt.IsValid() &&
22946        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22947         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22948          (rm.GetLane() <= 1))) &&
22949        (dt.Is(S16) || dt.Is(S32))) {
22950      if (cond.Is(al)) {
22951        EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
22952                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22953        return;
22954      }
22955    }
22956  }
22957  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22958}
22959
22960void Assembler::vqmovn(Condition cond,
22961                       DataType dt,
22962                       DRegister rd,
22963                       QRegister rm) {
22964  VIXL_ASSERT(AllowAssembler());
22965  CheckIT(cond);
22966  Dt_op_size_3 encoded_dt(dt);
22967  if (IsUsingT32()) {
22968    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
22969    if (encoded_dt.IsValid()) {
22970      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22971        EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22972                   ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22973                   rd.Encode(22, 12) | rm.Encode(5, 0));
22974        AdvanceIT();
22975        return;
22976      }
22977    }
22978  } else {
22979    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
22980    if (encoded_dt.IsValid()) {
22981      if (cond.Is(al)) {
22982        EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22983                ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22984                rd.Encode(22, 12) | rm.Encode(5, 0));
22985        return;
22986      }
22987    }
22988  }
22989  Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
22990}
22991
22992void Assembler::vqmovun(Condition cond,
22993                        DataType dt,
22994                        DRegister rd,
22995                        QRegister rm) {
22996  VIXL_ASSERT(AllowAssembler());
22997  CheckIT(cond);
22998  Dt_size_14 encoded_dt(dt);
22999  if (IsUsingT32()) {
23000    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
23001    if (encoded_dt.IsValid()) {
23002      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23003        EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
23004                   rd.Encode(22, 12) | rm.Encode(5, 0));
23005        AdvanceIT();
23006        return;
23007      }
23008    }
23009  } else {
23010    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
23011    if (encoded_dt.IsValid()) {
23012      if (cond.Is(al)) {
23013        EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
23014                rd.Encode(22, 12) | rm.Encode(5, 0));
23015        return;
23016      }
23017    }
23018  }
23019  Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
23020}
23021
23022void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
23023  VIXL_ASSERT(AllowAssembler());
23024  CheckIT(cond);
23025  Dt_size_5 encoded_dt(dt);
23026  if (IsUsingT32()) {
23027    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23028    if (encoded_dt.IsValid()) {
23029      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23030        EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
23031                   rd.Encode(22, 12) | rm.Encode(5, 0));
23032        AdvanceIT();
23033        return;
23034      }
23035    }
23036  } else {
23037    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23038    if (encoded_dt.IsValid()) {
23039      if (cond.Is(al)) {
23040        EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
23041                rd.Encode(22, 12) | rm.Encode(5, 0));
23042        return;
23043      }
23044    }
23045  }
23046  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23047}
23048
23049void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
23050  VIXL_ASSERT(AllowAssembler());
23051  CheckIT(cond);
23052  Dt_size_5 encoded_dt(dt);
23053  if (IsUsingT32()) {
23054    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23055    if (encoded_dt.IsValid()) {
23056      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23057        EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
23058                   rd.Encode(22, 12) | rm.Encode(5, 0));
23059        AdvanceIT();
23060        return;
23061      }
23062    }
23063  } else {
23064    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23065    if (encoded_dt.IsValid()) {
23066      if (cond.Is(al)) {
23067        EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
23068                rd.Encode(22, 12) | rm.Encode(5, 0));
23069        return;
23070      }
23071    }
23072  }
23073  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23074}
23075
23076void Assembler::vqrdmulh(
23077    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23078  VIXL_ASSERT(AllowAssembler());
23079  CheckIT(cond);
23080  Dt_size_13 encoded_dt(dt);
23081  if (IsUsingT32()) {
23082    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23083    if (encoded_dt.IsValid()) {
23084      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23085        EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
23086                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23087        AdvanceIT();
23088        return;
23089      }
23090    }
23091  } else {
23092    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23093    if (encoded_dt.IsValid()) {
23094      if (cond.Is(al)) {
23095        EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
23096                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23097        return;
23098      }
23099    }
23100  }
23101  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23102}
23103
23104void Assembler::vqrdmulh(
23105    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23106  VIXL_ASSERT(AllowAssembler());
23107  CheckIT(cond);
23108  Dt_size_13 encoded_dt(dt);
23109  if (IsUsingT32()) {
23110    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23111    if (encoded_dt.IsValid()) {
23112      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23113        EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
23114                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23115        AdvanceIT();
23116        return;
23117      }
23118    }
23119  } else {
23120    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23121    if (encoded_dt.IsValid()) {
23122      if (cond.Is(al)) {
23123        EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
23124                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23125        return;
23126      }
23127    }
23128  }
23129  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23130}
23131
23132void Assembler::vqrdmulh(
23133    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
23134  VIXL_ASSERT(AllowAssembler());
23135  CheckIT(cond);
23136  Dt_size_13 encoded_dt(dt);
23137  if (IsUsingT32()) {
23138    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
23139    if (encoded_dt.IsValid() &&
23140        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23141         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23142          (rm.GetLane() <= 1))) &&
23143        (dt.Is(S16) || dt.Is(S32))) {
23144      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23145        EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
23146                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23147        AdvanceIT();
23148        return;
23149      }
23150    }
23151  } else {
23152    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
23153    if (encoded_dt.IsValid() &&
23154        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23155         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23156          (rm.GetLane() <= 1))) &&
23157        (dt.Is(S16) || dt.Is(S32))) {
23158      if (cond.Is(al)) {
23159        EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
23160                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23161        return;
23162      }
23163    }
23164  }
23165  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23166}
23167
23168void Assembler::vqrdmulh(
23169    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
23170  VIXL_ASSERT(AllowAssembler());
23171  CheckIT(cond);
23172  Dt_size_13 encoded_dt(dt);
23173  if (IsUsingT32()) {
23174    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
23175    if (encoded_dt.IsValid() &&
23176        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23177         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23178          (rm.GetLane() <= 1))) &&
23179        (dt.Is(S16) || dt.Is(S32))) {
23180      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23181        EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
23182                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23183        AdvanceIT();
23184        return;
23185      }
23186    }
23187  } else {
23188    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
23189    if (encoded_dt.IsValid() &&
23190        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23191         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23192          (rm.GetLane() <= 1))) &&
23193        (dt.Is(S16) || dt.Is(S32))) {
23194      if (cond.Is(al)) {
23195        EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
23196                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23197        return;
23198      }
23199    }
23200  }
23201  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23202}
23203
23204void Assembler::vqrshl(
23205    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
23206  VIXL_ASSERT(AllowAssembler());
23207  CheckIT(cond);
23208  Dt_U_size_3 encoded_dt(dt);
23209  if (IsUsingT32()) {
23210    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23211    if (encoded_dt.IsValid()) {
23212      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23213        EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23214                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23215                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23216        AdvanceIT();
23217        return;
23218      }
23219    }
23220  } else {
23221    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23222    if (encoded_dt.IsValid()) {
23223      if (cond.Is(al)) {
23224        EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23225                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23226                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23227        return;
23228      }
23229    }
23230  }
23231  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23232}
23233
23234void Assembler::vqrshl(
23235    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
23236  VIXL_ASSERT(AllowAssembler());
23237  CheckIT(cond);
23238  Dt_U_size_3 encoded_dt(dt);
23239  if (IsUsingT32()) {
23240    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23241    if (encoded_dt.IsValid()) {
23242      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23243        EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23244                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23245                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23246        AdvanceIT();
23247        return;
23248      }
23249    }
23250  } else {
23251    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23252    if (encoded_dt.IsValid()) {
23253      if (cond.Is(al)) {
23254        EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23255                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23256                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23257        return;
23258      }
23259    }
23260  }
23261  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23262}
23263
23264void Assembler::vqrshrn(Condition cond,
23265                        DataType dt,
23266                        DRegister rd,
23267                        QRegister rm,
23268                        const QOperand& operand) {
23269  VIXL_ASSERT(AllowAssembler());
23270  CheckIT(cond);
23271  if (operand.IsImmediate()) {
23272    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23273      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23274      Dt_op_size_3 encoded_dt(dt);
23275      Dt_imm6_1 encoded_dt_2(dt);
23276      if (IsUsingT32()) {
23277        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23278        if (encoded_dt.IsValid() && (imm == 0)) {
23279          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23280            EmitT32_32(0xffb20280U |
23281                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23282                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23283                       rd.Encode(22, 12) | rm.Encode(5, 0));
23284            AdvanceIT();
23285            return;
23286          }
23287        }
23288        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23289        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23290          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23291            uint32_t imm6 = dt.GetSize() / 2 - imm;
23292            EmitT32_32(0xef800950U |
23293                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
23294                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23295                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23296            AdvanceIT();
23297            return;
23298          }
23299        }
23300      } else {
23301        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23302        if (encoded_dt.IsValid() && (imm == 0)) {
23303          if (cond.Is(al)) {
23304            EmitA32(0xf3b20280U |
23305                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23306                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23307                    rd.Encode(22, 12) | rm.Encode(5, 0));
23308            return;
23309          }
23310        }
23311        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23312        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23313          if (cond.Is(al)) {
23314            uint32_t imm6 = dt.GetSize() / 2 - imm;
23315            EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23316                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23317                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23318            return;
23319          }
23320        }
23321      }
23322    }
23323  }
23324  Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
23325}
23326
23327void Assembler::vqrshrun(Condition cond,
23328                         DataType dt,
23329                         DRegister rd,
23330                         QRegister rm,
23331                         const QOperand& operand) {
23332  VIXL_ASSERT(AllowAssembler());
23333  CheckIT(cond);
23334  if (operand.IsImmediate()) {
23335    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23336      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23337      Dt_imm6_2 encoded_dt(dt);
23338      Dt_size_14 encoded_dt_2(dt);
23339      if (IsUsingT32()) {
23340        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23341        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23342          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23343            uint32_t imm6 = dt.GetSize() / 2 - imm;
23344            EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
23345                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23346                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23347            AdvanceIT();
23348            return;
23349          }
23350        }
23351        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23352        if (encoded_dt_2.IsValid() && (imm == 0)) {
23353          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23354            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23355                       rd.Encode(22, 12) | rm.Encode(5, 0));
23356            AdvanceIT();
23357            return;
23358          }
23359        }
23360      } else {
23361        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23362        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23363          if (cond.Is(al)) {
23364            uint32_t imm6 = dt.GetSize() / 2 - imm;
23365            EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
23366                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23367                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23368            return;
23369          }
23370        }
23371        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23372        if (encoded_dt_2.IsValid() && (imm == 0)) {
23373          if (cond.Is(al)) {
23374            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23375                    rd.Encode(22, 12) | rm.Encode(5, 0));
23376            return;
23377          }
23378        }
23379      }
23380    }
23381  }
23382  Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
23383}
23384
23385void Assembler::vqshl(Condition cond,
23386                      DataType dt,
23387                      DRegister rd,
23388                      DRegister rm,
23389                      const DOperand& operand) {
23390  VIXL_ASSERT(AllowAssembler());
23391  CheckIT(cond);
23392  if (operand.IsRegister()) {
23393    DRegister rn = operand.GetRegister();
23394    Dt_U_size_3 encoded_dt(dt);
23395    if (IsUsingT32()) {
23396      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23397      if (encoded_dt.IsValid()) {
23398        if (cond.Is(al) || AllowStronglyDiscouraged()) {
23399          EmitT32_32(0xef000410U |
23400                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23401                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23402                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23403          AdvanceIT();
23404          return;
23405        }
23406      }
23407    } else {
23408      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23409      if (encoded_dt.IsValid()) {
23410        if (cond.Is(al)) {
23411          EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23412                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23413                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23414          return;
23415        }
23416      }
23417    }
23418  }
23419  if (operand.IsImmediate()) {
23420    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23421      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23422      Dt_L_imm6_1 encoded_dt(dt);
23423      if (IsUsingT32()) {
23424        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23425        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23426          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23427            uint32_t imm6 = imm;
23428            EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
23429                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23430                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23431                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23432            AdvanceIT();
23433            return;
23434          }
23435        }
23436      } else {
23437        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23438        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23439          if (cond.Is(al)) {
23440            uint32_t imm6 = imm;
23441            EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
23442                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23443                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23444                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23445            return;
23446          }
23447        }
23448      }
23449    }
23450  }
23451  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23452}
23453
23454void Assembler::vqshl(Condition cond,
23455                      DataType dt,
23456                      QRegister rd,
23457                      QRegister rm,
23458                      const QOperand& operand) {
23459  VIXL_ASSERT(AllowAssembler());
23460  CheckIT(cond);
23461  if (operand.IsRegister()) {
23462    QRegister rn = operand.GetRegister();
23463    Dt_U_size_3 encoded_dt(dt);
23464    if (IsUsingT32()) {
23465      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23466      if (encoded_dt.IsValid()) {
23467        if (cond.Is(al) || AllowStronglyDiscouraged()) {
23468          EmitT32_32(0xef000450U |
23469                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23470                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23471                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23472          AdvanceIT();
23473          return;
23474        }
23475      }
23476    } else {
23477      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23478      if (encoded_dt.IsValid()) {
23479        if (cond.Is(al)) {
23480          EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23481                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23482                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23483          return;
23484        }
23485      }
23486    }
23487  }
23488  if (operand.IsImmediate()) {
23489    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23490      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23491      Dt_L_imm6_1 encoded_dt(dt);
23492      if (IsUsingT32()) {
23493        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23494        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23495          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23496            uint32_t imm6 = imm;
23497            EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
23498                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23499                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23500                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23501            AdvanceIT();
23502            return;
23503          }
23504        }
23505      } else {
23506        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23507        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23508          if (cond.Is(al)) {
23509            uint32_t imm6 = imm;
23510            EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
23511                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23512                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23513                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23514            return;
23515          }
23516        }
23517      }
23518    }
23519  }
23520  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23521}
23522
23523void Assembler::vqshlu(Condition cond,
23524                       DataType dt,
23525                       DRegister rd,
23526                       DRegister rm,
23527                       const DOperand& operand) {
23528  VIXL_ASSERT(AllowAssembler());
23529  CheckIT(cond);
23530  if (operand.IsImmediate()) {
23531    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23532      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23533      Dt_L_imm6_2 encoded_dt(dt);
23534      if (IsUsingT32()) {
23535        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23536        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23537          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23538            uint32_t imm6 = imm;
23539            EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
23540                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23541                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23542                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23543            AdvanceIT();
23544            return;
23545          }
23546        }
23547      } else {
23548        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23549        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23550          if (cond.Is(al)) {
23551            uint32_t imm6 = imm;
23552            EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
23553                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23554                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23555                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23556            return;
23557          }
23558        }
23559      }
23560    }
23561  }
23562  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23563}
23564
23565void Assembler::vqshlu(Condition cond,
23566                       DataType dt,
23567                       QRegister rd,
23568                       QRegister rm,
23569                       const QOperand& operand) {
23570  VIXL_ASSERT(AllowAssembler());
23571  CheckIT(cond);
23572  if (operand.IsImmediate()) {
23573    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23574      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23575      Dt_L_imm6_2 encoded_dt(dt);
23576      if (IsUsingT32()) {
23577        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23578        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23579          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23580            uint32_t imm6 = imm;
23581            EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
23582                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23583                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23584                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23585            AdvanceIT();
23586            return;
23587          }
23588        }
23589      } else {
23590        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23591        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23592          if (cond.Is(al)) {
23593            uint32_t imm6 = imm;
23594            EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
23595                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23596                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23597                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23598            return;
23599          }
23600        }
23601      }
23602    }
23603  }
23604  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23605}
23606
23607void Assembler::vqshrn(Condition cond,
23608                       DataType dt,
23609                       DRegister rd,
23610                       QRegister rm,
23611                       const QOperand& operand) {
23612  VIXL_ASSERT(AllowAssembler());
23613  CheckIT(cond);
23614  if (operand.IsImmediate()) {
23615    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23616      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23617      Dt_op_size_3 encoded_dt(dt);
23618      Dt_imm6_1 encoded_dt_2(dt);
23619      if (IsUsingT32()) {
23620        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23621        if (encoded_dt.IsValid() && (imm == 0)) {
23622          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23623            EmitT32_32(0xffb20280U |
23624                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23625                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23626                       rd.Encode(22, 12) | rm.Encode(5, 0));
23627            AdvanceIT();
23628            return;
23629          }
23630        }
23631        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23632        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23633          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23634            uint32_t imm6 = dt.GetSize() / 2 - imm;
23635            EmitT32_32(0xef800910U |
23636                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
23637                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23638                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23639            AdvanceIT();
23640            return;
23641          }
23642        }
23643      } else {
23644        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23645        if (encoded_dt.IsValid() && (imm == 0)) {
23646          if (cond.Is(al)) {
23647            EmitA32(0xf3b20280U |
23648                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23649                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23650                    rd.Encode(22, 12) | rm.Encode(5, 0));
23651            return;
23652          }
23653        }
23654        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23655        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23656          if (cond.Is(al)) {
23657            uint32_t imm6 = dt.GetSize() / 2 - imm;
23658            EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23659                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23660                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23661            return;
23662          }
23663        }
23664      }
23665    }
23666  }
23667  Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
23668}
23669
23670void Assembler::vqshrun(Condition cond,
23671                        DataType dt,
23672                        DRegister rd,
23673                        QRegister rm,
23674                        const QOperand& operand) {
23675  VIXL_ASSERT(AllowAssembler());
23676  CheckIT(cond);
23677  if (operand.IsImmediate()) {
23678    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23679      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23680      Dt_imm6_2 encoded_dt(dt);
23681      Dt_size_14 encoded_dt_2(dt);
23682      if (IsUsingT32()) {
23683        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23684        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23685          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23686            uint32_t imm6 = dt.GetSize() / 2 - imm;
23687            EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
23688                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23689                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23690            AdvanceIT();
23691            return;
23692          }
23693        }
23694        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23695        if (encoded_dt_2.IsValid() && (imm == 0)) {
23696          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23697            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23698                       rd.Encode(22, 12) | rm.Encode(5, 0));
23699            AdvanceIT();
23700            return;
23701          }
23702        }
23703      } else {
23704        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23705        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23706          if (cond.Is(al)) {
23707            uint32_t imm6 = dt.GetSize() / 2 - imm;
23708            EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
23709                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23710                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23711            return;
23712          }
23713        }
23714        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23715        if (encoded_dt_2.IsValid() && (imm == 0)) {
23716          if (cond.Is(al)) {
23717            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23718                    rd.Encode(22, 12) | rm.Encode(5, 0));
23719            return;
23720          }
23721        }
23722      }
23723    }
23724  }
23725  Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
23726}
23727
23728void Assembler::vqsub(
23729    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23730  VIXL_ASSERT(AllowAssembler());
23731  CheckIT(cond);
23732  Dt_U_size_3 encoded_dt(dt);
23733  if (IsUsingT32()) {
23734    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23735    if (encoded_dt.IsValid()) {
23736      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23737        EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23738                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23739                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23740        AdvanceIT();
23741        return;
23742      }
23743    }
23744  } else {
23745    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23746    if (encoded_dt.IsValid()) {
23747      if (cond.Is(al)) {
23748        EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23749                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23750                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23751        return;
23752      }
23753    }
23754  }
23755  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23756}
23757
23758void Assembler::vqsub(
23759    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23760  VIXL_ASSERT(AllowAssembler());
23761  CheckIT(cond);
23762  Dt_U_size_3 encoded_dt(dt);
23763  if (IsUsingT32()) {
23764    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23765    if (encoded_dt.IsValid()) {
23766      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23767        EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23768                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23769                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23770        AdvanceIT();
23771        return;
23772      }
23773    }
23774  } else {
23775    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23776    if (encoded_dt.IsValid()) {
23777      if (cond.Is(al)) {
23778        EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23779                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23780                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23781        return;
23782      }
23783    }
23784  }
23785  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23786}
23787
23788void Assembler::vraddhn(
23789    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
23790  VIXL_ASSERT(AllowAssembler());
23791  CheckIT(cond);
23792  Dt_size_3 encoded_dt(dt);
23793  if (IsUsingT32()) {
23794    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23795    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23796      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23797        EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
23798                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23799        AdvanceIT();
23800        return;
23801      }
23802    }
23803  } else {
23804    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23805    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23806      if (cond.Is(al)) {
23807        EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
23808                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23809        return;
23810      }
23811    }
23812  }
23813  Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
23814}
23815
23816void Assembler::vrecpe(Condition cond,
23817                       DataType dt,
23818                       DRegister rd,
23819                       DRegister rm) {
23820  VIXL_ASSERT(AllowAssembler());
23821  CheckIT(cond);
23822  Dt_F_size_4 encoded_dt(dt);
23823  if (IsUsingT32()) {
23824    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23825    if (encoded_dt.IsValid()) {
23826      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23827        EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23828                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23829                   rd.Encode(22, 12) | rm.Encode(5, 0));
23830        AdvanceIT();
23831        return;
23832      }
23833    }
23834  } else {
23835    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23836    if (encoded_dt.IsValid()) {
23837      if (cond.Is(al)) {
23838        EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23839                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23840                rd.Encode(22, 12) | rm.Encode(5, 0));
23841        return;
23842      }
23843    }
23844  }
23845  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23846}
23847
23848void Assembler::vrecpe(Condition cond,
23849                       DataType dt,
23850                       QRegister rd,
23851                       QRegister rm) {
23852  VIXL_ASSERT(AllowAssembler());
23853  CheckIT(cond);
23854  Dt_F_size_4 encoded_dt(dt);
23855  if (IsUsingT32()) {
23856    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23857    if (encoded_dt.IsValid()) {
23858      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23859        EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23860                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23861                   rd.Encode(22, 12) | rm.Encode(5, 0));
23862        AdvanceIT();
23863        return;
23864      }
23865    }
23866  } else {
23867    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23868    if (encoded_dt.IsValid()) {
23869      if (cond.Is(al)) {
23870        EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23871                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23872                rd.Encode(22, 12) | rm.Encode(5, 0));
23873        return;
23874      }
23875    }
23876  }
23877  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23878}
23879
23880void Assembler::vrecps(
23881    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23882  VIXL_ASSERT(AllowAssembler());
23883  CheckIT(cond);
23884  if (IsUsingT32()) {
23885    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23886    if (dt.Is(F32)) {
23887      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23888        EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23889                   rm.Encode(5, 0));
23890        AdvanceIT();
23891        return;
23892      }
23893    }
23894  } else {
23895    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23896    if (dt.Is(F32)) {
23897      if (cond.Is(al)) {
23898        EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23899                rm.Encode(5, 0));
23900        return;
23901      }
23902    }
23903  }
23904  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23905}
23906
23907void Assembler::vrecps(
23908    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23909  VIXL_ASSERT(AllowAssembler());
23910  CheckIT(cond);
23911  if (IsUsingT32()) {
23912    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23913    if (dt.Is(F32)) {
23914      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23915        EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23916                   rm.Encode(5, 0));
23917        AdvanceIT();
23918        return;
23919      }
23920    }
23921  } else {
23922    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23923    if (dt.Is(F32)) {
23924      if (cond.Is(al)) {
23925        EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23926                rm.Encode(5, 0));
23927        return;
23928      }
23929    }
23930  }
23931  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23932}
23933
23934void Assembler::vrev16(Condition cond,
23935                       DataType dt,
23936                       DRegister rd,
23937                       DRegister rm) {
23938  VIXL_ASSERT(AllowAssembler());
23939  CheckIT(cond);
23940  Dt_size_1 encoded_dt(dt);
23941  if (IsUsingT32()) {
23942    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23943    if (encoded_dt.IsValid()) {
23944      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23945        EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
23946                   rd.Encode(22, 12) | rm.Encode(5, 0));
23947        AdvanceIT();
23948        return;
23949      }
23950    }
23951  } else {
23952    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23953    if (encoded_dt.IsValid()) {
23954      if (cond.Is(al)) {
23955        EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
23956                rd.Encode(22, 12) | rm.Encode(5, 0));
23957        return;
23958      }
23959    }
23960  }
23961  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
23962}
23963
23964void Assembler::vrev16(Condition cond,
23965                       DataType dt,
23966                       QRegister rd,
23967                       QRegister rm) {
23968  VIXL_ASSERT(AllowAssembler());
23969  CheckIT(cond);
23970  Dt_size_1 encoded_dt(dt);
23971  if (IsUsingT32()) {
23972    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23973    if (encoded_dt.IsValid()) {
23974      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23975        EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
23976                   rd.Encode(22, 12) | rm.Encode(5, 0));
23977        AdvanceIT();
23978        return;
23979      }
23980    }
23981  } else {
23982    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23983    if (encoded_dt.IsValid()) {
23984      if (cond.Is(al)) {
23985        EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
23986                rd.Encode(22, 12) | rm.Encode(5, 0));
23987        return;
23988      }
23989    }
23990  }
23991  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
23992}
23993
23994void Assembler::vrev32(Condition cond,
23995                       DataType dt,
23996                       DRegister rd,
23997                       DRegister rm) {
23998  VIXL_ASSERT(AllowAssembler());
23999  CheckIT(cond);
24000  Dt_size_15 encoded_dt(dt);
24001  if (IsUsingT32()) {
24002    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24003    if (encoded_dt.IsValid()) {
24004      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24005        EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
24006                   rd.Encode(22, 12) | rm.Encode(5, 0));
24007        AdvanceIT();
24008        return;
24009      }
24010    }
24011  } else {
24012    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24013    if (encoded_dt.IsValid()) {
24014      if (cond.Is(al)) {
24015        EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
24016                rd.Encode(22, 12) | rm.Encode(5, 0));
24017        return;
24018      }
24019    }
24020  }
24021  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24022}
24023
24024void Assembler::vrev32(Condition cond,
24025                       DataType dt,
24026                       QRegister rd,
24027                       QRegister rm) {
24028  VIXL_ASSERT(AllowAssembler());
24029  CheckIT(cond);
24030  Dt_size_15 encoded_dt(dt);
24031  if (IsUsingT32()) {
24032    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24033    if (encoded_dt.IsValid()) {
24034      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24035        EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
24036                   rd.Encode(22, 12) | rm.Encode(5, 0));
24037        AdvanceIT();
24038        return;
24039      }
24040    }
24041  } else {
24042    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24043    if (encoded_dt.IsValid()) {
24044      if (cond.Is(al)) {
24045        EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
24046                rd.Encode(22, 12) | rm.Encode(5, 0));
24047        return;
24048      }
24049    }
24050  }
24051  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24052}
24053
24054void Assembler::vrev64(Condition cond,
24055                       DataType dt,
24056                       DRegister rd,
24057                       DRegister rm) {
24058  VIXL_ASSERT(AllowAssembler());
24059  CheckIT(cond);
24060  Dt_size_7 encoded_dt(dt);
24061  if (IsUsingT32()) {
24062    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24063    if (encoded_dt.IsValid()) {
24064      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24065        EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
24066                   rd.Encode(22, 12) | rm.Encode(5, 0));
24067        AdvanceIT();
24068        return;
24069      }
24070    }
24071  } else {
24072    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24073    if (encoded_dt.IsValid()) {
24074      if (cond.Is(al)) {
24075        EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
24076                rd.Encode(22, 12) | rm.Encode(5, 0));
24077        return;
24078      }
24079    }
24080  }
24081  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24082}
24083
24084void Assembler::vrev64(Condition cond,
24085                       DataType dt,
24086                       QRegister rd,
24087                       QRegister rm) {
24088  VIXL_ASSERT(AllowAssembler());
24089  CheckIT(cond);
24090  Dt_size_7 encoded_dt(dt);
24091  if (IsUsingT32()) {
24092    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24093    if (encoded_dt.IsValid()) {
24094      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24095        EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
24096                   rd.Encode(22, 12) | rm.Encode(5, 0));
24097        AdvanceIT();
24098        return;
24099      }
24100    }
24101  } else {
24102    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24103    if (encoded_dt.IsValid()) {
24104      if (cond.Is(al)) {
24105        EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
24106                rd.Encode(22, 12) | rm.Encode(5, 0));
24107        return;
24108      }
24109    }
24110  }
24111  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24112}
24113
24114void Assembler::vrhadd(
24115    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
24116  VIXL_ASSERT(AllowAssembler());
24117  CheckIT(cond);
24118  Dt_U_size_1 encoded_dt(dt);
24119  if (IsUsingT32()) {
24120    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
24121    if (encoded_dt.IsValid()) {
24122      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24123        EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24124                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24125                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24126        AdvanceIT();
24127        return;
24128      }
24129    }
24130  } else {
24131    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
24132    if (encoded_dt.IsValid()) {
24133      if (cond.Is(al)) {
24134        EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24135                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24136                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24137        return;
24138      }
24139    }
24140  }
24141  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24142}
24143
24144void Assembler::vrhadd(
24145    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
24146  VIXL_ASSERT(AllowAssembler());
24147  CheckIT(cond);
24148  Dt_U_size_1 encoded_dt(dt);
24149  if (IsUsingT32()) {
24150    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
24151    if (encoded_dt.IsValid()) {
24152      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24153        EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24154                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24155                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24156        AdvanceIT();
24157        return;
24158      }
24159    }
24160  } else {
24161    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
24162    if (encoded_dt.IsValid()) {
24163      if (cond.Is(al)) {
24164        EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24165                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24166                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24167        return;
24168      }
24169    }
24170  }
24171  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24172}
24173
24174void Assembler::vrinta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24175  VIXL_ASSERT(AllowAssembler());
24176  CheckIT(al);
24177  if (IsUsingT32()) {
24178    // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; T1
24179    if (dt1.Is(F32) && dt2.Is(F32)) {
24180      EmitT32_32(0xffba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
24181      AdvanceIT();
24182      return;
24183    }
24184    // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; T1
24185    if (dt1.Is(F64) && dt2.Is(F64)) {
24186      EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24187      AdvanceIT();
24188      return;
24189    }
24190  } else {
24191    // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; A1
24192    if (dt1.Is(F32) && dt2.Is(F32)) {
24193      EmitA32(0xf3ba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
24194      return;
24195    }
24196    // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; A1
24197    if (dt1.Is(F64) && dt2.Is(F64)) {
24198      EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24199      return;
24200    }
24201  }
24202  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24203}
24204
24205void Assembler::vrinta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
24206  VIXL_ASSERT(AllowAssembler());
24207  CheckIT(al);
24208  if (IsUsingT32()) {
24209    // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; T1
24210    if (dt1.Is(F32) && dt2.Is(F32)) {
24211      EmitT32_32(0xffba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
24212      AdvanceIT();
24213      return;
24214    }
24215  } else {
24216    // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; A1
24217    if (dt1.Is(F32) && dt2.Is(F32)) {
24218      EmitA32(0xf3ba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
24219      return;
24220    }
24221  }
24222  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24223}
24224
24225void Assembler::vrinta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24226  VIXL_ASSERT(AllowAssembler());
24227  CheckIT(al);
24228  if (IsUsingT32()) {
24229    // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; T1
24230    if (dt1.Is(F32) && dt2.Is(F32)) {
24231      EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24232      AdvanceIT();
24233      return;
24234    }
24235  } else {
24236    // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; A1
24237    if (dt1.Is(F32) && dt2.Is(F32)) {
24238      EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24239      return;
24240    }
24241  }
24242  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24243}
24244
24245void Assembler::vrintm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24246  VIXL_ASSERT(AllowAssembler());
24247  CheckIT(al);
24248  if (IsUsingT32()) {
24249    // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; T1
24250    if (dt1.Is(F32) && dt2.Is(F32)) {
24251      EmitT32_32(0xffba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
24252      AdvanceIT();
24253      return;
24254    }
24255    // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; T1
24256    if (dt1.Is(F64) && dt2.Is(F64)) {
24257      EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24258      AdvanceIT();
24259      return;
24260    }
24261  } else {
24262    // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; A1
24263    if (dt1.Is(F32) && dt2.Is(F32)) {
24264      EmitA32(0xf3ba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
24265      return;
24266    }
24267    // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; A1
24268    if (dt1.Is(F64) && dt2.Is(F64)) {
24269      EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24270      return;
24271    }
24272  }
24273  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24274}
24275
24276void Assembler::vrintm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
24277  VIXL_ASSERT(AllowAssembler());
24278  CheckIT(al);
24279  if (IsUsingT32()) {
24280    // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; T1
24281    if (dt1.Is(F32) && dt2.Is(F32)) {
24282      EmitT32_32(0xffba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24283      AdvanceIT();
24284      return;
24285    }
24286  } else {
24287    // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; A1
24288    if (dt1.Is(F32) && dt2.Is(F32)) {
24289      EmitA32(0xf3ba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24290      return;
24291    }
24292  }
24293  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24294}
24295
24296void Assembler::vrintm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24297  VIXL_ASSERT(AllowAssembler());
24298  CheckIT(al);
24299  if (IsUsingT32()) {
24300    // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; T1
24301    if (dt1.Is(F32) && dt2.Is(F32)) {
24302      EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24303      AdvanceIT();
24304      return;
24305    }
24306  } else {
24307    // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; A1
24308    if (dt1.Is(F32) && dt2.Is(F32)) {
24309      EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24310      return;
24311    }
24312  }
24313  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24314}
24315
24316void Assembler::vrintn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24317  VIXL_ASSERT(AllowAssembler());
24318  CheckIT(al);
24319  if (IsUsingT32()) {
24320    // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; T1
24321    if (dt1.Is(F32) && dt2.Is(F32)) {
24322      EmitT32_32(0xffba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
24323      AdvanceIT();
24324      return;
24325    }
24326    // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; T1
24327    if (dt1.Is(F64) && dt2.Is(F64)) {
24328      EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24329      AdvanceIT();
24330      return;
24331    }
24332  } else {
24333    // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; A1
24334    if (dt1.Is(F32) && dt2.Is(F32)) {
24335      EmitA32(0xf3ba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
24336      return;
24337    }
24338    // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; A1
24339    if (dt1.Is(F64) && dt2.Is(F64)) {
24340      EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24341      return;
24342    }
24343  }
24344  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24345}
24346
24347void Assembler::vrintn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
24348  VIXL_ASSERT(AllowAssembler());
24349  CheckIT(al);
24350  if (IsUsingT32()) {
24351    // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; T1
24352    if (dt1.Is(F32) && dt2.Is(F32)) {
24353      EmitT32_32(0xffba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
24354      AdvanceIT();
24355      return;
24356    }
24357  } else {
24358    // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; A1
24359    if (dt1.Is(F32) && dt2.Is(F32)) {
24360      EmitA32(0xf3ba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
24361      return;
24362    }
24363  }
24364  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24365}
24366
24367void Assembler::vrintn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24368  VIXL_ASSERT(AllowAssembler());
24369  CheckIT(al);
24370  if (IsUsingT32()) {
24371    // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; T1
24372    if (dt1.Is(F32) && dt2.Is(F32)) {
24373      EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24374      AdvanceIT();
24375      return;
24376    }
24377  } else {
24378    // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; A1
24379    if (dt1.Is(F32) && dt2.Is(F32)) {
24380      EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24381      return;
24382    }
24383  }
24384  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24385}
24386
24387void Assembler::vrintp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24388  VIXL_ASSERT(AllowAssembler());
24389  CheckIT(al);
24390  if (IsUsingT32()) {
24391    // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; T1
24392    if (dt1.Is(F32) && dt2.Is(F32)) {
24393      EmitT32_32(0xffba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
24394      AdvanceIT();
24395      return;
24396    }
24397    // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; T1
24398    if (dt1.Is(F64) && dt2.Is(F64)) {
24399      EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24400      AdvanceIT();
24401      return;
24402    }
24403  } else {
24404    // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; A1
24405    if (dt1.Is(F32) && dt2.Is(F32)) {
24406      EmitA32(0xf3ba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
24407      return;
24408    }
24409    // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; A1
24410    if (dt1.Is(F64) && dt2.Is(F64)) {
24411      EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24412      return;
24413    }
24414  }
24415  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24416}
24417
24418void Assembler::vrintp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
24419  VIXL_ASSERT(AllowAssembler());
24420  CheckIT(al);
24421  if (IsUsingT32()) {
24422    // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; T1
24423    if (dt1.Is(F32) && dt2.Is(F32)) {
24424      EmitT32_32(0xffba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24425      AdvanceIT();
24426      return;
24427    }
24428  } else {
24429    // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; A1
24430    if (dt1.Is(F32) && dt2.Is(F32)) {
24431      EmitA32(0xf3ba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24432      return;
24433    }
24434  }
24435  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24436}
24437
24438void Assembler::vrintp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24439  VIXL_ASSERT(AllowAssembler());
24440  CheckIT(al);
24441  if (IsUsingT32()) {
24442    // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; T1
24443    if (dt1.Is(F32) && dt2.Is(F32)) {
24444      EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24445      AdvanceIT();
24446      return;
24447    }
24448  } else {
24449    // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; A1
24450    if (dt1.Is(F32) && dt2.Is(F32)) {
24451      EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24452      return;
24453    }
24454  }
24455  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24456}
24457
24458void Assembler::vrintr(
24459    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24460  VIXL_ASSERT(AllowAssembler());
24461  CheckIT(cond);
24462  if (IsUsingT32()) {
24463    // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24464    if (dt1.Is(F32) && dt2.Is(F32)) {
24465      EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24466      AdvanceIT();
24467      return;
24468    }
24469  } else {
24470    // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24471    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24472      EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24473              rm.Encode(5, 0));
24474      return;
24475    }
24476  }
24477  Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
24478}
24479
24480void Assembler::vrintr(
24481    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24482  VIXL_ASSERT(AllowAssembler());
24483  CheckIT(cond);
24484  if (IsUsingT32()) {
24485    // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24486    if (dt1.Is(F64) && dt2.Is(F64)) {
24487      EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24488      AdvanceIT();
24489      return;
24490    }
24491  } else {
24492    // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24493    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24494      EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24495              rm.Encode(5, 0));
24496      return;
24497    }
24498  }
24499  Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
24500}
24501
24502void Assembler::vrintx(
24503    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24504  VIXL_ASSERT(AllowAssembler());
24505  CheckIT(cond);
24506  if (IsUsingT32()) {
24507    // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; T1
24508    if (dt1.Is(F32) && dt2.Is(F32)) {
24509      EmitT32_32(0xffba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
24510      AdvanceIT();
24511      return;
24512    }
24513    // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24514    if (dt1.Is(F64) && dt2.Is(F64)) {
24515      EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24516      AdvanceIT();
24517      return;
24518    }
24519  } else {
24520    // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; A1
24521    if (dt1.Is(F32) && dt2.Is(F32)) {
24522      EmitA32(0xf3ba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
24523      return;
24524    }
24525    // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24526    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24527      EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24528              rm.Encode(5, 0));
24529      return;
24530    }
24531  }
24532  Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
24533}
24534
24535void Assembler::vrintx(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
24536  VIXL_ASSERT(AllowAssembler());
24537  CheckIT(al);
24538  if (IsUsingT32()) {
24539    // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; T1
24540    if (dt1.Is(F32) && dt2.Is(F32)) {
24541      EmitT32_32(0xffba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24542      AdvanceIT();
24543      return;
24544    }
24545  } else {
24546    // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; A1
24547    if (dt1.Is(F32) && dt2.Is(F32)) {
24548      EmitA32(0xf3ba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24549      return;
24550    }
24551  }
24552  Delegate(kVrintx, &Assembler::vrintx, dt1, dt2, rd, rm);
24553}
24554
24555void Assembler::vrintx(
24556    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24557  VIXL_ASSERT(AllowAssembler());
24558  CheckIT(cond);
24559  if (IsUsingT32()) {
24560    // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24561    if (dt1.Is(F32) && dt2.Is(F32)) {
24562      EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24563      AdvanceIT();
24564      return;
24565    }
24566  } else {
24567    // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24568    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24569      EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24570              rm.Encode(5, 0));
24571      return;
24572    }
24573  }
24574  Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
24575}
24576
24577void Assembler::vrintz(
24578    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
24579  VIXL_ASSERT(AllowAssembler());
24580  CheckIT(cond);
24581  if (IsUsingT32()) {
24582    // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; T1
24583    if (dt1.Is(F32) && dt2.Is(F32)) {
24584      EmitT32_32(0xffba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
24585      AdvanceIT();
24586      return;
24587    }
24588    // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24589    if (dt1.Is(F64) && dt2.Is(F64)) {
24590      EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24591      AdvanceIT();
24592      return;
24593    }
24594  } else {
24595    // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; A1
24596    if (dt1.Is(F32) && dt2.Is(F32)) {
24597      EmitA32(0xf3ba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
24598      return;
24599    }
24600    // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24601    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24602      EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24603              rm.Encode(5, 0));
24604      return;
24605    }
24606  }
24607  Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
24608}
24609
24610void Assembler::vrintz(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
24611  VIXL_ASSERT(AllowAssembler());
24612  CheckIT(al);
24613  if (IsUsingT32()) {
24614    // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; T1
24615    if (dt1.Is(F32) && dt2.Is(F32)) {
24616      EmitT32_32(0xffba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24617      AdvanceIT();
24618      return;
24619    }
24620  } else {
24621    // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; A1
24622    if (dt1.Is(F32) && dt2.Is(F32)) {
24623      EmitA32(0xf3ba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24624      return;
24625    }
24626  }
24627  Delegate(kVrintz, &Assembler::vrintz, dt1, dt2, rd, rm);
24628}
24629
24630void Assembler::vrintz(
24631    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
24632  VIXL_ASSERT(AllowAssembler());
24633  CheckIT(cond);
24634  if (IsUsingT32()) {
24635    // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24636    if (dt1.Is(F32) && dt2.Is(F32)) {
24637      EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24638      AdvanceIT();
24639      return;
24640    }
24641  } else {
24642    // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24643    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24644      EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24645              rm.Encode(5, 0));
24646      return;
24647    }
24648  }
24649  Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
24650}
24651
24652void Assembler::vrshl(
24653    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
24654  VIXL_ASSERT(AllowAssembler());
24655  CheckIT(cond);
24656  Dt_U_size_3 encoded_dt(dt);
24657  if (IsUsingT32()) {
24658    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24659    if (encoded_dt.IsValid()) {
24660      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24661        EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24662                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24663                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24664        AdvanceIT();
24665        return;
24666      }
24667    }
24668  } else {
24669    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24670    if (encoded_dt.IsValid()) {
24671      if (cond.Is(al)) {
24672        EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24673                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24674                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24675        return;
24676      }
24677    }
24678  }
24679  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24680}
24681
24682void Assembler::vrshl(
24683    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
24684  VIXL_ASSERT(AllowAssembler());
24685  CheckIT(cond);
24686  Dt_U_size_3 encoded_dt(dt);
24687  if (IsUsingT32()) {
24688    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24689    if (encoded_dt.IsValid()) {
24690      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24691        EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24692                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24693                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24694        AdvanceIT();
24695        return;
24696      }
24697    }
24698  } else {
24699    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24700    if (encoded_dt.IsValid()) {
24701      if (cond.Is(al)) {
24702        EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24703                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24704                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24705        return;
24706      }
24707    }
24708  }
24709  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24710}
24711
24712void Assembler::vrshr(Condition cond,
24713                      DataType dt,
24714                      DRegister rd,
24715                      DRegister rm,
24716                      const DOperand& operand) {
24717  VIXL_ASSERT(AllowAssembler());
24718  CheckIT(cond);
24719  if (operand.IsImmediate()) {
24720    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24721      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24722      Dt_L_imm6_1 encoded_dt(dt);
24723      if (IsUsingT32()) {
24724        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24725        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24726          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24727            uint32_t imm6 = dt.GetSize() - imm;
24728            EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
24729                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24730                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24731                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24732            AdvanceIT();
24733            return;
24734          }
24735        }
24736        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24737        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24738          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24739            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24740                       rm.Encode(5, 0));
24741            AdvanceIT();
24742            return;
24743          }
24744        }
24745      } else {
24746        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24747        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24748          if (cond.Is(al)) {
24749            uint32_t imm6 = dt.GetSize() - imm;
24750            EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
24751                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24752                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24753                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24754            return;
24755          }
24756        }
24757        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24758        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24759          if (cond.Is(al)) {
24760            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24761                    rm.Encode(5, 0));
24762            return;
24763          }
24764        }
24765      }
24766    }
24767  }
24768  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24769}
24770
24771void Assembler::vrshr(Condition cond,
24772                      DataType dt,
24773                      QRegister rd,
24774                      QRegister rm,
24775                      const QOperand& operand) {
24776  VIXL_ASSERT(AllowAssembler());
24777  CheckIT(cond);
24778  if (operand.IsImmediate()) {
24779    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24780      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24781      Dt_L_imm6_1 encoded_dt(dt);
24782      if (IsUsingT32()) {
24783        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24784        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24785          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24786            uint32_t imm6 = dt.GetSize() - imm;
24787            EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
24788                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24789                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24790                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24791            AdvanceIT();
24792            return;
24793          }
24794        }
24795        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24796        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24797          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24798            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24799                       rm.Encode(5, 0));
24800            AdvanceIT();
24801            return;
24802          }
24803        }
24804      } else {
24805        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24806        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24807          if (cond.Is(al)) {
24808            uint32_t imm6 = dt.GetSize() - imm;
24809            EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
24810                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24811                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24812                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24813            return;
24814          }
24815        }
24816        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24817        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24818          if (cond.Is(al)) {
24819            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24820                    rm.Encode(5, 0));
24821            return;
24822          }
24823        }
24824      }
24825    }
24826  }
24827  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24828}
24829
24830void Assembler::vrshrn(Condition cond,
24831                       DataType dt,
24832                       DRegister rd,
24833                       QRegister rm,
24834                       const QOperand& operand) {
24835  VIXL_ASSERT(AllowAssembler());
24836  CheckIT(cond);
24837  if (operand.IsImmediate()) {
24838    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24839      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24840      Dt_imm6_3 encoded_dt(dt);
24841      Dt_size_3 encoded_dt_2(dt);
24842      if (IsUsingT32()) {
24843        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24844        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24845          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24846            uint32_t imm6 = dt.GetSize() / 2 - imm;
24847            EmitT32_32(0xef800850U |
24848                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24849                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24850            AdvanceIT();
24851            return;
24852          }
24853        }
24854        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24855        if (encoded_dt_2.IsValid() && (imm == 0)) {
24856          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24857            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24858                       rd.Encode(22, 12) | rm.Encode(5, 0));
24859            AdvanceIT();
24860            return;
24861          }
24862        }
24863      } else {
24864        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24865        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24866          if (cond.Is(al)) {
24867            uint32_t imm6 = dt.GetSize() / 2 - imm;
24868            EmitA32(0xf2800850U |
24869                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24870                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24871            return;
24872          }
24873        }
24874        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24875        if (encoded_dt_2.IsValid() && (imm == 0)) {
24876          if (cond.Is(al)) {
24877            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24878                    rd.Encode(22, 12) | rm.Encode(5, 0));
24879            return;
24880          }
24881        }
24882      }
24883    }
24884  }
24885  Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
24886}
24887
24888void Assembler::vrsqrte(Condition cond,
24889                        DataType dt,
24890                        DRegister rd,
24891                        DRegister rm) {
24892  VIXL_ASSERT(AllowAssembler());
24893  CheckIT(cond);
24894  Dt_F_size_4 encoded_dt(dt);
24895  if (IsUsingT32()) {
24896    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24897    if (encoded_dt.IsValid()) {
24898      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24899        EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24900                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24901                   rd.Encode(22, 12) | rm.Encode(5, 0));
24902        AdvanceIT();
24903        return;
24904      }
24905    }
24906  } else {
24907    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24908    if (encoded_dt.IsValid()) {
24909      if (cond.Is(al)) {
24910        EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24911                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24912                rd.Encode(22, 12) | rm.Encode(5, 0));
24913        return;
24914      }
24915    }
24916  }
24917  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
24918}
24919
24920void Assembler::vrsqrte(Condition cond,
24921                        DataType dt,
24922                        QRegister rd,
24923                        QRegister rm) {
24924  VIXL_ASSERT(AllowAssembler());
24925  CheckIT(cond);
24926  Dt_F_size_4 encoded_dt(dt);
24927  if (IsUsingT32()) {
24928    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24929    if (encoded_dt.IsValid()) {
24930      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24931        EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24932                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24933                   rd.Encode(22, 12) | rm.Encode(5, 0));
24934        AdvanceIT();
24935        return;
24936      }
24937    }
24938  } else {
24939    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24940    if (encoded_dt.IsValid()) {
24941      if (cond.Is(al)) {
24942        EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24943                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24944                rd.Encode(22, 12) | rm.Encode(5, 0));
24945        return;
24946      }
24947    }
24948  }
24949  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
24950}
24951
24952void Assembler::vrsqrts(
24953    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
24954  VIXL_ASSERT(AllowAssembler());
24955  CheckIT(cond);
24956  if (IsUsingT32()) {
24957    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
24958    if (dt.Is(F32)) {
24959      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24960        EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24961                   rm.Encode(5, 0));
24962        AdvanceIT();
24963        return;
24964      }
24965    }
24966  } else {
24967    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
24968    if (dt.Is(F32)) {
24969      if (cond.Is(al)) {
24970        EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24971                rm.Encode(5, 0));
24972        return;
24973      }
24974    }
24975  }
24976  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
24977}
24978
24979void Assembler::vrsqrts(
24980    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
24981  VIXL_ASSERT(AllowAssembler());
24982  CheckIT(cond);
24983  if (IsUsingT32()) {
24984    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
24985    if (dt.Is(F32)) {
24986      if (cond.Is(al) || AllowStronglyDiscouraged()) {
24987        EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24988                   rm.Encode(5, 0));
24989        AdvanceIT();
24990        return;
24991      }
24992    }
24993  } else {
24994    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
24995    if (dt.Is(F32)) {
24996      if (cond.Is(al)) {
24997        EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24998                rm.Encode(5, 0));
24999        return;
25000      }
25001    }
25002  }
25003  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
25004}
25005
25006void Assembler::vrsra(Condition cond,
25007                      DataType dt,
25008                      DRegister rd,
25009                      DRegister rm,
25010                      const DOperand& operand) {
25011  VIXL_ASSERT(AllowAssembler());
25012  CheckIT(cond);
25013  if (operand.IsImmediate()) {
25014    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25015      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25016      Dt_L_imm6_1 encoded_dt(dt);
25017      if (IsUsingT32()) {
25018        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25019        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25020          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25021            uint32_t imm6 = dt.GetSize() - imm;
25022            EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
25023                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25024                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25025                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25026            AdvanceIT();
25027            return;
25028          }
25029        }
25030      } else {
25031        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25032        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25033          if (cond.Is(al)) {
25034            uint32_t imm6 = dt.GetSize() - imm;
25035            EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
25036                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25037                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25038                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25039            return;
25040          }
25041        }
25042      }
25043    }
25044  }
25045  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25046}
25047
25048void Assembler::vrsra(Condition cond,
25049                      DataType dt,
25050                      QRegister rd,
25051                      QRegister rm,
25052                      const QOperand& operand) {
25053  VIXL_ASSERT(AllowAssembler());
25054  CheckIT(cond);
25055  if (operand.IsImmediate()) {
25056    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25057      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25058      Dt_L_imm6_1 encoded_dt(dt);
25059      if (IsUsingT32()) {
25060        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25061        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25062          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25063            uint32_t imm6 = dt.GetSize() - imm;
25064            EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
25065                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25066                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25067                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25068            AdvanceIT();
25069            return;
25070          }
25071        }
25072      } else {
25073        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25074        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25075          if (cond.Is(al)) {
25076            uint32_t imm6 = dt.GetSize() - imm;
25077            EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
25078                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25079                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25080                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25081            return;
25082          }
25083        }
25084      }
25085    }
25086  }
25087  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25088}
25089
25090void Assembler::vrsubhn(
25091    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
25092  VIXL_ASSERT(AllowAssembler());
25093  CheckIT(cond);
25094  Dt_size_3 encoded_dt(dt);
25095  if (IsUsingT32()) {
25096    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
25097    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25098      if (cond.Is(al) || AllowStronglyDiscouraged()) {
25099        EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
25100                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25101        AdvanceIT();
25102        return;
25103      }
25104    }
25105  } else {
25106    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
25107    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25108      if (cond.Is(al)) {
25109        EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
25110                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25111        return;
25112      }
25113    }
25114  }
25115  Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
25116}
25117
25118void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25119  VIXL_ASSERT(AllowAssembler());
25120  CheckIT(al);
25121  if (IsUsingT32()) {
25122    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
25123    if (OutsideITBlock() && dt.Is(F64)) {
25124      EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25125                 rm.Encode(5, 0));
25126      AdvanceIT();
25127      return;
25128    }
25129  } else {
25130    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
25131    if (dt.Is(F64)) {
25132      EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25133              rm.Encode(5, 0));
25134      return;
25135    }
25136  }
25137  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25138}
25139
25140void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25141  VIXL_ASSERT(AllowAssembler());
25142  CheckIT(al);
25143  if (IsUsingT32()) {
25144    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
25145    if (OutsideITBlock() && dt.Is(F32)) {
25146      EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25147                 rm.Encode(5, 0));
25148      AdvanceIT();
25149      return;
25150    }
25151  } else {
25152    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
25153    if (dt.Is(F32)) {
25154      EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25155              rm.Encode(5, 0));
25156      return;
25157    }
25158  }
25159  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25160}
25161
25162void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25163  VIXL_ASSERT(AllowAssembler());
25164  CheckIT(al);
25165  if (IsUsingT32()) {
25166    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
25167    if (OutsideITBlock() && dt.Is(F64)) {
25168      EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25169                 rm.Encode(5, 0));
25170      AdvanceIT();
25171      return;
25172    }
25173  } else {
25174    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
25175    if (dt.Is(F64)) {
25176      EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25177              rm.Encode(5, 0));
25178      return;
25179    }
25180  }
25181  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25182}
25183
25184void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25185  VIXL_ASSERT(AllowAssembler());
25186  CheckIT(al);
25187  if (IsUsingT32()) {
25188    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
25189    if (OutsideITBlock() && dt.Is(F32)) {
25190      EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25191                 rm.Encode(5, 0));
25192      AdvanceIT();
25193      return;
25194    }
25195  } else {
25196    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
25197    if (dt.Is(F32)) {
25198      EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25199              rm.Encode(5, 0));
25200      return;
25201    }
25202  }
25203  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25204}
25205
25206void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25207  VIXL_ASSERT(AllowAssembler());
25208  CheckIT(al);
25209  if (IsUsingT32()) {
25210    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
25211    if (OutsideITBlock() && dt.Is(F64)) {
25212      EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25213                 rm.Encode(5, 0));
25214      AdvanceIT();
25215      return;
25216    }
25217  } else {
25218    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
25219    if (dt.Is(F64)) {
25220      EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25221              rm.Encode(5, 0));
25222      return;
25223    }
25224  }
25225  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25226}
25227
25228void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25229  VIXL_ASSERT(AllowAssembler());
25230  CheckIT(al);
25231  if (IsUsingT32()) {
25232    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
25233    if (OutsideITBlock() && dt.Is(F32)) {
25234      EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25235                 rm.Encode(5, 0));
25236      AdvanceIT();
25237      return;
25238    }
25239  } else {
25240    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
25241    if (dt.Is(F32)) {
25242      EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25243              rm.Encode(5, 0));
25244      return;
25245    }
25246  }
25247  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25248}
25249
25250void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25251  VIXL_ASSERT(AllowAssembler());
25252  CheckIT(al);
25253  if (IsUsingT32()) {
25254    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
25255    if (OutsideITBlock() && dt.Is(F64)) {
25256      EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25257                 rm.Encode(5, 0));
25258      AdvanceIT();
25259      return;
25260    }
25261  } else {
25262    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
25263    if (dt.Is(F64)) {
25264      EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25265              rm.Encode(5, 0));
25266      return;
25267    }
25268  }
25269  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25270}
25271
25272void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
25273  VIXL_ASSERT(AllowAssembler());
25274  CheckIT(al);
25275  if (IsUsingT32()) {
25276    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
25277    if (OutsideITBlock() && dt.Is(F32)) {
25278      EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25279                 rm.Encode(5, 0));
25280      AdvanceIT();
25281      return;
25282    }
25283  } else {
25284    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
25285    if (dt.Is(F32)) {
25286      EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25287              rm.Encode(5, 0));
25288      return;
25289    }
25290  }
25291  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25292}
25293
25294void Assembler::vshl(Condition cond,
25295                     DataType dt,
25296                     DRegister rd,
25297                     DRegister rm,
25298                     const DOperand& operand) {
25299  VIXL_ASSERT(AllowAssembler());
25300  CheckIT(cond);
25301  if (operand.IsImmediate()) {
25302    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25303      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25304      Dt_L_imm6_3 encoded_dt(dt);
25305      if (IsUsingT32()) {
25306        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
25307        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25308          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25309            uint32_t imm6 = imm;
25310            EmitT32_32(0xef800510U |
25311                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25312                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25313                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25314            AdvanceIT();
25315            return;
25316          }
25317        }
25318      } else {
25319        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
25320        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25321          if (cond.Is(al)) {
25322            uint32_t imm6 = imm;
25323            EmitA32(0xf2800510U |
25324                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25325                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25326                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25327            return;
25328          }
25329        }
25330      }
25331    }
25332  }
25333  if (operand.IsRegister()) {
25334    DRegister rn = operand.GetRegister();
25335    Dt_U_size_3 encoded_dt(dt);
25336    if (IsUsingT32()) {
25337      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
25338      if (encoded_dt.IsValid()) {
25339        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25340          EmitT32_32(0xef000400U |
25341                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25342                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25343                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25344          AdvanceIT();
25345          return;
25346        }
25347      }
25348    } else {
25349      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
25350      if (encoded_dt.IsValid()) {
25351        if (cond.Is(al)) {
25352          EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25353                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25354                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25355          return;
25356        }
25357      }
25358    }
25359  }
25360  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25361}
25362
25363void Assembler::vshl(Condition cond,
25364                     DataType dt,
25365                     QRegister rd,
25366                     QRegister rm,
25367                     const QOperand& operand) {
25368  VIXL_ASSERT(AllowAssembler());
25369  CheckIT(cond);
25370  if (operand.IsImmediate()) {
25371    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25372      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25373      Dt_L_imm6_3 encoded_dt(dt);
25374      if (IsUsingT32()) {
25375        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
25376        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25377          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25378            uint32_t imm6 = imm;
25379            EmitT32_32(0xef800550U |
25380                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25381                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25382                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25383            AdvanceIT();
25384            return;
25385          }
25386        }
25387      } else {
25388        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
25389        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25390          if (cond.Is(al)) {
25391            uint32_t imm6 = imm;
25392            EmitA32(0xf2800550U |
25393                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25394                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25395                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25396            return;
25397          }
25398        }
25399      }
25400    }
25401  }
25402  if (operand.IsRegister()) {
25403    QRegister rn = operand.GetRegister();
25404    Dt_U_size_3 encoded_dt(dt);
25405    if (IsUsingT32()) {
25406      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
25407      if (encoded_dt.IsValid()) {
25408        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25409          EmitT32_32(0xef000440U |
25410                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25411                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25412                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25413          AdvanceIT();
25414          return;
25415        }
25416      }
25417    } else {
25418      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
25419      if (encoded_dt.IsValid()) {
25420        if (cond.Is(al)) {
25421          EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25422                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25423                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25424          return;
25425        }
25426      }
25427    }
25428  }
25429  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25430}
25431
25432void Assembler::vshll(Condition cond,
25433                      DataType dt,
25434                      QRegister rd,
25435                      DRegister rm,
25436                      const DOperand& operand) {
25437  VIXL_ASSERT(AllowAssembler());
25438  CheckIT(cond);
25439  if (operand.IsImmediate()) {
25440    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25441      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25442      Dt_imm6_4 encoded_dt(dt);
25443      Dt_size_16 encoded_dt_2(dt);
25444      if (IsUsingT32()) {
25445        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
25446        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25447          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25448            uint32_t imm6 = dt.GetSize() + imm;
25449            EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
25450                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25451                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25452            AdvanceIT();
25453            return;
25454          }
25455        }
25456        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
25457        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25458          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25459            EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25460                       rd.Encode(22, 12) | rm.Encode(5, 0));
25461            AdvanceIT();
25462            return;
25463          }
25464        }
25465      } else {
25466        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
25467        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25468          if (cond.Is(al)) {
25469            uint32_t imm6 = dt.GetSize() + imm;
25470            EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
25471                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25472                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25473            return;
25474          }
25475        }
25476        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
25477        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25478          if (cond.Is(al)) {
25479            EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25480                    rd.Encode(22, 12) | rm.Encode(5, 0));
25481            return;
25482          }
25483        }
25484      }
25485    }
25486  }
25487  Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
25488}
25489
25490void Assembler::vshr(Condition cond,
25491                     DataType dt,
25492                     DRegister rd,
25493                     DRegister rm,
25494                     const DOperand& operand) {
25495  VIXL_ASSERT(AllowAssembler());
25496  CheckIT(cond);
25497  if (operand.IsImmediate()) {
25498    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25499      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25500      Dt_L_imm6_1 encoded_dt(dt);
25501      if (IsUsingT32()) {
25502        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25503        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25504          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25505            uint32_t imm6 = dt.GetSize() - imm;
25506            EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
25507                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25508                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25509                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25510            AdvanceIT();
25511            return;
25512          }
25513        }
25514        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
25515        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25516          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25517            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25518                       rm.Encode(5, 0));
25519            AdvanceIT();
25520            return;
25521          }
25522        }
25523      } else {
25524        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25525        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25526          if (cond.Is(al)) {
25527            uint32_t imm6 = dt.GetSize() - imm;
25528            EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
25529                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25530                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25531                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25532            return;
25533          }
25534        }
25535        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
25536        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25537          if (cond.Is(al)) {
25538            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25539                    rm.Encode(5, 0));
25540            return;
25541          }
25542        }
25543      }
25544    }
25545  }
25546  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25547}
25548
25549void Assembler::vshr(Condition cond,
25550                     DataType dt,
25551                     QRegister rd,
25552                     QRegister rm,
25553                     const QOperand& operand) {
25554  VIXL_ASSERT(AllowAssembler());
25555  CheckIT(cond);
25556  if (operand.IsImmediate()) {
25557    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25558      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25559      Dt_L_imm6_1 encoded_dt(dt);
25560      if (IsUsingT32()) {
25561        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25562        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25563          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25564            uint32_t imm6 = dt.GetSize() - imm;
25565            EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
25566                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25567                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25568                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25569            AdvanceIT();
25570            return;
25571          }
25572        }
25573        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
25574        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25575          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25576            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25577                       rm.Encode(5, 0));
25578            AdvanceIT();
25579            return;
25580          }
25581        }
25582      } else {
25583        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25584        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25585          if (cond.Is(al)) {
25586            uint32_t imm6 = dt.GetSize() - imm;
25587            EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
25588                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25589                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25590                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25591            return;
25592          }
25593        }
25594        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
25595        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25596          if (cond.Is(al)) {
25597            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25598                    rm.Encode(5, 0));
25599            return;
25600          }
25601        }
25602      }
25603    }
25604  }
25605  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25606}
25607
25608void Assembler::vshrn(Condition cond,
25609                      DataType dt,
25610                      DRegister rd,
25611                      QRegister rm,
25612                      const QOperand& operand) {
25613  VIXL_ASSERT(AllowAssembler());
25614  CheckIT(cond);
25615  if (operand.IsImmediate()) {
25616    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25617      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25618      Dt_imm6_3 encoded_dt(dt);
25619      Dt_size_3 encoded_dt_2(dt);
25620      if (IsUsingT32()) {
25621        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
25622        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25623          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25624            uint32_t imm6 = dt.GetSize() / 2 - imm;
25625            EmitT32_32(0xef800810U |
25626                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25627                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25628            AdvanceIT();
25629            return;
25630          }
25631        }
25632        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
25633        if (encoded_dt_2.IsValid() && (imm == 0)) {
25634          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25635            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25636                       rd.Encode(22, 12) | rm.Encode(5, 0));
25637            AdvanceIT();
25638            return;
25639          }
25640        }
25641      } else {
25642        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
25643        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25644          if (cond.Is(al)) {
25645            uint32_t imm6 = dt.GetSize() / 2 - imm;
25646            EmitA32(0xf2800810U |
25647                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25648                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25649            return;
25650          }
25651        }
25652        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
25653        if (encoded_dt_2.IsValid() && (imm == 0)) {
25654          if (cond.Is(al)) {
25655            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25656                    rd.Encode(22, 12) | rm.Encode(5, 0));
25657            return;
25658          }
25659        }
25660      }
25661    }
25662  }
25663  Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
25664}
25665
25666void Assembler::vsli(Condition cond,
25667                     DataType dt,
25668                     DRegister rd,
25669                     DRegister rm,
25670                     const DOperand& operand) {
25671  VIXL_ASSERT(AllowAssembler());
25672  CheckIT(cond);
25673  if (operand.IsImmediate()) {
25674    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25675      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25676      Dt_L_imm6_4 encoded_dt(dt);
25677      if (IsUsingT32()) {
25678        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25679        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25680          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25681            uint32_t imm6 = imm;
25682            EmitT32_32(0xff800510U |
25683                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25684                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25685                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25686            AdvanceIT();
25687            return;
25688          }
25689        }
25690      } else {
25691        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25692        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25693          if (cond.Is(al)) {
25694            uint32_t imm6 = imm;
25695            EmitA32(0xf3800510U |
25696                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25697                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25698                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25699            return;
25700          }
25701        }
25702      }
25703    }
25704  }
25705  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25706}
25707
25708void Assembler::vsli(Condition cond,
25709                     DataType dt,
25710                     QRegister rd,
25711                     QRegister rm,
25712                     const QOperand& operand) {
25713  VIXL_ASSERT(AllowAssembler());
25714  CheckIT(cond);
25715  if (operand.IsImmediate()) {
25716    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25717      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25718      Dt_L_imm6_4 encoded_dt(dt);
25719      if (IsUsingT32()) {
25720        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25721        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25722          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25723            uint32_t imm6 = imm;
25724            EmitT32_32(0xff800550U |
25725                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25726                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25727                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25728            AdvanceIT();
25729            return;
25730          }
25731        }
25732      } else {
25733        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25734        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25735          if (cond.Is(al)) {
25736            uint32_t imm6 = imm;
25737            EmitA32(0xf3800550U |
25738                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25739                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25740                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25741            return;
25742          }
25743        }
25744      }
25745    }
25746  }
25747  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25748}
25749
25750void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
25751  VIXL_ASSERT(AllowAssembler());
25752  CheckIT(cond);
25753  if (IsUsingT32()) {
25754    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
25755    if (dt.Is(F32)) {
25756      EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25757      AdvanceIT();
25758      return;
25759    }
25760  } else {
25761    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
25762    if (dt.Is(F32) && cond.IsNotNever()) {
25763      EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25764              rm.Encode(5, 0));
25765      return;
25766    }
25767  }
25768  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25769}
25770
25771void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
25772  VIXL_ASSERT(AllowAssembler());
25773  CheckIT(cond);
25774  if (IsUsingT32()) {
25775    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
25776    if (dt.Is(F64)) {
25777      EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25778      AdvanceIT();
25779      return;
25780    }
25781  } else {
25782    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
25783    if (dt.Is(F64) && cond.IsNotNever()) {
25784      EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25785              rm.Encode(5, 0));
25786      return;
25787    }
25788  }
25789  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25790}
25791
25792void Assembler::vsra(Condition cond,
25793                     DataType dt,
25794                     DRegister rd,
25795                     DRegister rm,
25796                     const DOperand& operand) {
25797  VIXL_ASSERT(AllowAssembler());
25798  CheckIT(cond);
25799  if (operand.IsImmediate()) {
25800    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25801      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25802      Dt_L_imm6_1 encoded_dt(dt);
25803      if (IsUsingT32()) {
25804        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25805        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25806          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25807            uint32_t imm6 = dt.GetSize() - imm;
25808            EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
25809                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25810                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25811                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25812            AdvanceIT();
25813            return;
25814          }
25815        }
25816      } else {
25817        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25818        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25819          if (cond.Is(al)) {
25820            uint32_t imm6 = dt.GetSize() - imm;
25821            EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
25822                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25823                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25824                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25825            return;
25826          }
25827        }
25828      }
25829    }
25830  }
25831  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25832}
25833
25834void Assembler::vsra(Condition cond,
25835                     DataType dt,
25836                     QRegister rd,
25837                     QRegister rm,
25838                     const QOperand& operand) {
25839  VIXL_ASSERT(AllowAssembler());
25840  CheckIT(cond);
25841  if (operand.IsImmediate()) {
25842    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25843      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25844      Dt_L_imm6_1 encoded_dt(dt);
25845      if (IsUsingT32()) {
25846        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25847        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25848          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25849            uint32_t imm6 = dt.GetSize() - imm;
25850            EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
25851                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25852                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25853                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25854            AdvanceIT();
25855            return;
25856          }
25857        }
25858      } else {
25859        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25860        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25861          if (cond.Is(al)) {
25862            uint32_t imm6 = dt.GetSize() - imm;
25863            EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
25864                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25865                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25866                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25867            return;
25868          }
25869        }
25870      }
25871    }
25872  }
25873  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25874}
25875
25876void Assembler::vsri(Condition cond,
25877                     DataType dt,
25878                     DRegister rd,
25879                     DRegister rm,
25880                     const DOperand& operand) {
25881  VIXL_ASSERT(AllowAssembler());
25882  CheckIT(cond);
25883  if (operand.IsImmediate()) {
25884    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25885      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25886      Dt_L_imm6_4 encoded_dt(dt);
25887      if (IsUsingT32()) {
25888        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25889        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25890          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25891            uint32_t imm6 = dt.GetSize() - imm;
25892            EmitT32_32(0xff800410U |
25893                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25894                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25895                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25896            AdvanceIT();
25897            return;
25898          }
25899        }
25900      } else {
25901        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25902        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25903          if (cond.Is(al)) {
25904            uint32_t imm6 = dt.GetSize() - imm;
25905            EmitA32(0xf3800410U |
25906                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25907                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25908                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25909            return;
25910          }
25911        }
25912      }
25913    }
25914  }
25915  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
25916}
25917
25918void Assembler::vsri(Condition cond,
25919                     DataType dt,
25920                     QRegister rd,
25921                     QRegister rm,
25922                     const QOperand& operand) {
25923  VIXL_ASSERT(AllowAssembler());
25924  CheckIT(cond);
25925  if (operand.IsImmediate()) {
25926    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25927      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25928      Dt_L_imm6_4 encoded_dt(dt);
25929      if (IsUsingT32()) {
25930        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25931        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25932          if (cond.Is(al) || AllowStronglyDiscouraged()) {
25933            uint32_t imm6 = dt.GetSize() - imm;
25934            EmitT32_32(0xff800450U |
25935                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25936                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25937                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25938            AdvanceIT();
25939            return;
25940          }
25941        }
25942      } else {
25943        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25944        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25945          if (cond.Is(al)) {
25946            uint32_t imm6 = dt.GetSize() - imm;
25947            EmitA32(0xf3800450U |
25948                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25949                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25950                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25951            return;
25952          }
25953        }
25954      }
25955    }
25956  }
25957  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
25958}
25959
25960void Assembler::vst1(Condition cond,
25961                     DataType dt,
25962                     const NeonRegisterList& nreglist,
25963                     const AlignedMemOperand& operand) {
25964  VIXL_ASSERT(AllowAssembler());
25965  CheckIT(cond);
25966  if (operand.IsImmediateZero()) {
25967    Register rn = operand.GetBaseRegister();
25968    Alignment align = operand.GetAlignment();
25969    Dt_size_6 encoded_dt(dt);
25970    Dt_size_7 encoded_dt_2(dt);
25971    Align_align_5 encoded_align_1(align, nreglist);
25972    Align_index_align_1 encoded_align_2(align, nreglist, dt);
25973    if (IsUsingT32()) {
25974      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25975      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25976          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
25977          operand.IsOffset() && encoded_align_1.IsValid() &&
25978          (!rn.IsPC() || AllowUnpredictable())) {
25979        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25980          const DRegister& first = nreglist.GetFirstDRegister();
25981          uint32_t len_encoding;
25982          switch (nreglist.GetLength()) {
25983            default:
25984              VIXL_UNREACHABLE_OR_FALLTHROUGH();
25985            case 1:
25986              len_encoding = 0x7;
25987              break;
25988            case 2:
25989              len_encoding = 0xa;
25990              break;
25991            case 3:
25992              len_encoding = 0x6;
25993              break;
25994            case 4:
25995              len_encoding = 0x2;
25996              break;
25997          }
25998          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25999                     (encoded_align_1.GetEncodingValue() << 4) |
26000                     first.Encode(22, 12) | (len_encoding << 8) |
26001                     (rn.GetCode() << 16));
26002          AdvanceIT();
26003          return;
26004        }
26005      }
26006      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26007      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26008          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26009          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26010          (!rn.IsPC() || AllowUnpredictable())) {
26011        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26012          const DRegister& first = nreglist.GetFirstDRegister();
26013          uint32_t len_encoding;
26014          switch (nreglist.GetLength()) {
26015            default:
26016              VIXL_UNREACHABLE_OR_FALLTHROUGH();
26017            case 1:
26018              len_encoding = 0x7;
26019              break;
26020            case 2:
26021              len_encoding = 0xa;
26022              break;
26023            case 3:
26024              len_encoding = 0x6;
26025              break;
26026            case 4:
26027              len_encoding = 0x2;
26028              break;
26029          }
26030          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26031                     (encoded_align_1.GetEncodingValue() << 4) |
26032                     first.Encode(22, 12) | (len_encoding << 8) |
26033                     (rn.GetCode() << 16));
26034          AdvanceIT();
26035          return;
26036        }
26037      }
26038      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26039      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26040          (nreglist.GetLength() == 1) && operand.IsOffset() &&
26041          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26042        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26043          const DRegister& first = nreglist.GetFirstDRegister();
26044          EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26045                     (encoded_align_2.GetEncodingValue() << 4) |
26046                     first.Encode(22, 12) | (rn.GetCode() << 16));
26047          AdvanceIT();
26048          return;
26049        }
26050      }
26051      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26052      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26053          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
26054          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26055        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26056          const DRegister& first = nreglist.GetFirstDRegister();
26057          EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26058                     (encoded_align_2.GetEncodingValue() << 4) |
26059                     first.Encode(22, 12) | (rn.GetCode() << 16));
26060          AdvanceIT();
26061          return;
26062        }
26063      }
26064    } else {
26065      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26066      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26067          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26068          operand.IsOffset() && encoded_align_1.IsValid() &&
26069          (!rn.IsPC() || AllowUnpredictable())) {
26070        if (cond.Is(al)) {
26071          const DRegister& first = nreglist.GetFirstDRegister();
26072          uint32_t len_encoding;
26073          switch (nreglist.GetLength()) {
26074            default:
26075              VIXL_UNREACHABLE_OR_FALLTHROUGH();
26076            case 1:
26077              len_encoding = 0x7;
26078              break;
26079            case 2:
26080              len_encoding = 0xa;
26081              break;
26082            case 3:
26083              len_encoding = 0x6;
26084              break;
26085            case 4:
26086              len_encoding = 0x2;
26087              break;
26088          }
26089          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26090                  (encoded_align_1.GetEncodingValue() << 4) |
26091                  first.Encode(22, 12) | (len_encoding << 8) |
26092                  (rn.GetCode() << 16));
26093          return;
26094        }
26095      }
26096      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26097      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26098          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26099          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26100          (!rn.IsPC() || AllowUnpredictable())) {
26101        if (cond.Is(al)) {
26102          const DRegister& first = nreglist.GetFirstDRegister();
26103          uint32_t len_encoding;
26104          switch (nreglist.GetLength()) {
26105            default:
26106              VIXL_UNREACHABLE_OR_FALLTHROUGH();
26107            case 1:
26108              len_encoding = 0x7;
26109              break;
26110            case 2:
26111              len_encoding = 0xa;
26112              break;
26113            case 3:
26114              len_encoding = 0x6;
26115              break;
26116            case 4:
26117              len_encoding = 0x2;
26118              break;
26119          }
26120          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26121                  (encoded_align_1.GetEncodingValue() << 4) |
26122                  first.Encode(22, 12) | (len_encoding << 8) |
26123                  (rn.GetCode() << 16));
26124          return;
26125        }
26126      }
26127      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26128      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26129          (nreglist.GetLength() == 1) && operand.IsOffset() &&
26130          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26131        if (cond.Is(al)) {
26132          const DRegister& first = nreglist.GetFirstDRegister();
26133          EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26134                  (encoded_align_2.GetEncodingValue() << 4) |
26135                  first.Encode(22, 12) | (rn.GetCode() << 16));
26136          return;
26137        }
26138      }
26139      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26140      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26141          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
26142          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
26143        if (cond.Is(al)) {
26144          const DRegister& first = nreglist.GetFirstDRegister();
26145          EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26146                  (encoded_align_2.GetEncodingValue() << 4) |
26147                  first.Encode(22, 12) | (rn.GetCode() << 16));
26148          return;
26149        }
26150      }
26151    }
26152  }
26153  if (operand.IsPlainRegister()) {
26154    Register rn = operand.GetBaseRegister();
26155    Alignment align = operand.GetAlignment();
26156    Register rm = operand.GetOffsetRegister();
26157    Dt_size_6 encoded_dt(dt);
26158    Dt_size_7 encoded_dt_2(dt);
26159    Align_align_5 encoded_align_1(align, nreglist);
26160    Align_index_align_1 encoded_align_2(align, nreglist, dt);
26161    if (IsUsingT32()) {
26162      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26163      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26164          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26165          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26166        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26167          const DRegister& first = nreglist.GetFirstDRegister();
26168          uint32_t len_encoding;
26169          switch (nreglist.GetLength()) {
26170            default:
26171              VIXL_UNREACHABLE_OR_FALLTHROUGH();
26172            case 1:
26173              len_encoding = 0x7;
26174              break;
26175            case 2:
26176              len_encoding = 0xa;
26177              break;
26178            case 3:
26179              len_encoding = 0x6;
26180              break;
26181            case 4:
26182              len_encoding = 0x2;
26183              break;
26184          }
26185          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26186                     (encoded_align_1.GetEncodingValue() << 4) |
26187                     first.Encode(22, 12) | (len_encoding << 8) |
26188                     (rn.GetCode() << 16) | rm.GetCode());
26189          AdvanceIT();
26190          return;
26191        }
26192      }
26193      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26194      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26195          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26196          (!rn.IsPC() || AllowUnpredictable())) {
26197        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26198          const DRegister& first = nreglist.GetFirstDRegister();
26199          EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26200                     (encoded_align_2.GetEncodingValue() << 4) |
26201                     first.Encode(22, 12) | (rn.GetCode() << 16) |
26202                     rm.GetCode());
26203          AdvanceIT();
26204          return;
26205        }
26206      }
26207    } else {
26208      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26209      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26210          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
26211          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26212        if (cond.Is(al)) {
26213          const DRegister& first = nreglist.GetFirstDRegister();
26214          uint32_t len_encoding;
26215          switch (nreglist.GetLength()) {
26216            default:
26217              VIXL_UNREACHABLE_OR_FALLTHROUGH();
26218            case 1:
26219              len_encoding = 0x7;
26220              break;
26221            case 2:
26222              len_encoding = 0xa;
26223              break;
26224            case 3:
26225              len_encoding = 0x6;
26226              break;
26227            case 4:
26228              len_encoding = 0x2;
26229              break;
26230          }
26231          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26232                  (encoded_align_1.GetEncodingValue() << 4) |
26233                  first.Encode(22, 12) | (len_encoding << 8) |
26234                  (rn.GetCode() << 16) | rm.GetCode());
26235          return;
26236        }
26237      }
26238      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26239      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
26240          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26241          (!rn.IsPC() || AllowUnpredictable())) {
26242        if (cond.Is(al)) {
26243          const DRegister& first = nreglist.GetFirstDRegister();
26244          EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26245                  (encoded_align_2.GetEncodingValue() << 4) |
26246                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26247          return;
26248        }
26249      }
26250    }
26251  }
26252  Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
26253}
26254
26255void Assembler::vst2(Condition cond,
26256                     DataType dt,
26257                     const NeonRegisterList& nreglist,
26258                     const AlignedMemOperand& operand) {
26259  VIXL_ASSERT(AllowAssembler());
26260  CheckIT(cond);
26261  if (operand.IsImmediateZero()) {
26262    Register rn = operand.GetBaseRegister();
26263    Alignment align = operand.GetAlignment();
26264    Dt_size_7 encoded_dt(dt);
26265    Align_align_2 encoded_align_1(align, nreglist);
26266    Align_index_align_2 encoded_align_2(align, nreglist, dt);
26267    if (IsUsingT32()) {
26268      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26269      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26270          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26271           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26272           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26273          operand.IsOffset() && encoded_align_1.IsValid() &&
26274          (!rn.IsPC() || AllowUnpredictable())) {
26275        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26276          const DRegister& first = nreglist.GetFirstDRegister();
26277          uint32_t len_encoding;
26278          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26279            len_encoding = 0x8;
26280          }
26281          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26282            len_encoding = 0x9;
26283          }
26284          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26285            len_encoding = 0x3;
26286          }
26287          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26288                     (encoded_align_1.GetEncodingValue() << 4) |
26289                     first.Encode(22, 12) | (len_encoding << 8) |
26290                     (rn.GetCode() << 16));
26291          AdvanceIT();
26292          return;
26293        }
26294      }
26295      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26296      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26297          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26298           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26299           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26300          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26301          (!rn.IsPC() || AllowUnpredictable())) {
26302        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26303          const DRegister& first = nreglist.GetFirstDRegister();
26304          uint32_t len_encoding;
26305          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26306            len_encoding = 0x8;
26307          }
26308          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26309            len_encoding = 0x9;
26310          }
26311          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26312            len_encoding = 0x3;
26313          }
26314          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26315                     (encoded_align_1.GetEncodingValue() << 4) |
26316                     first.Encode(22, 12) | (len_encoding << 8) |
26317                     (rn.GetCode() << 16));
26318          AdvanceIT();
26319          return;
26320        }
26321      }
26322      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26323      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26324          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26325           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26326          operand.IsOffset() && encoded_align_2.IsValid() &&
26327          (!rn.IsPC() || AllowUnpredictable())) {
26328        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26329          const DRegister& first = nreglist.GetFirstDRegister();
26330          EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
26331                     (encoded_align_2.GetEncodingValue() << 4) |
26332                     first.Encode(22, 12) | (rn.GetCode() << 16));
26333          AdvanceIT();
26334          return;
26335        }
26336      }
26337      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26338      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26339          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26340           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26341          operand.IsPostIndex() && encoded_align_2.IsValid() &&
26342          (!rn.IsPC() || AllowUnpredictable())) {
26343        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26344          const DRegister& first = nreglist.GetFirstDRegister();
26345          EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
26346                     (encoded_align_2.GetEncodingValue() << 4) |
26347                     first.Encode(22, 12) | (rn.GetCode() << 16));
26348          AdvanceIT();
26349          return;
26350        }
26351      }
26352    } else {
26353      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26354      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26355          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26356           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26357           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26358          operand.IsOffset() && encoded_align_1.IsValid() &&
26359          (!rn.IsPC() || AllowUnpredictable())) {
26360        if (cond.Is(al)) {
26361          const DRegister& first = nreglist.GetFirstDRegister();
26362          uint32_t len_encoding;
26363          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26364            len_encoding = 0x8;
26365          }
26366          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26367            len_encoding = 0x9;
26368          }
26369          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26370            len_encoding = 0x3;
26371          }
26372          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26373                  (encoded_align_1.GetEncodingValue() << 4) |
26374                  first.Encode(22, 12) | (len_encoding << 8) |
26375                  (rn.GetCode() << 16));
26376          return;
26377        }
26378      }
26379      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26380      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26381          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26382           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26383           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26384          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26385          (!rn.IsPC() || AllowUnpredictable())) {
26386        if (cond.Is(al)) {
26387          const DRegister& first = nreglist.GetFirstDRegister();
26388          uint32_t len_encoding;
26389          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26390            len_encoding = 0x8;
26391          }
26392          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26393            len_encoding = 0x9;
26394          }
26395          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26396            len_encoding = 0x3;
26397          }
26398          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26399                  (encoded_align_1.GetEncodingValue() << 4) |
26400                  first.Encode(22, 12) | (len_encoding << 8) |
26401                  (rn.GetCode() << 16));
26402          return;
26403        }
26404      }
26405      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26406      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26407          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26408           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26409          operand.IsOffset() && encoded_align_2.IsValid() &&
26410          (!rn.IsPC() || AllowUnpredictable())) {
26411        if (cond.Is(al)) {
26412          const DRegister& first = nreglist.GetFirstDRegister();
26413          EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
26414                  (encoded_align_2.GetEncodingValue() << 4) |
26415                  first.Encode(22, 12) | (rn.GetCode() << 16));
26416          return;
26417        }
26418      }
26419      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26420      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26421          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26422           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26423          operand.IsPostIndex() && encoded_align_2.IsValid() &&
26424          (!rn.IsPC() || AllowUnpredictable())) {
26425        if (cond.Is(al)) {
26426          const DRegister& first = nreglist.GetFirstDRegister();
26427          EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
26428                  (encoded_align_2.GetEncodingValue() << 4) |
26429                  first.Encode(22, 12) | (rn.GetCode() << 16));
26430          return;
26431        }
26432      }
26433    }
26434  }
26435  if (operand.IsPlainRegister()) {
26436    Register rn = operand.GetBaseRegister();
26437    Alignment align = operand.GetAlignment();
26438    Register rm = operand.GetOffsetRegister();
26439    Dt_size_7 encoded_dt(dt);
26440    Align_align_2 encoded_align_1(align, nreglist);
26441    Align_index_align_2 encoded_align_2(align, nreglist, dt);
26442    if (IsUsingT32()) {
26443      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26444      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26445          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26446           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26447           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26448          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26449        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26450          const DRegister& first = nreglist.GetFirstDRegister();
26451          uint32_t len_encoding;
26452          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26453            len_encoding = 0x8;
26454          }
26455          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26456            len_encoding = 0x9;
26457          }
26458          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26459            len_encoding = 0x3;
26460          }
26461          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26462                     (encoded_align_1.GetEncodingValue() << 4) |
26463                     first.Encode(22, 12) | (len_encoding << 8) |
26464                     (rn.GetCode() << 16) | rm.GetCode());
26465          AdvanceIT();
26466          return;
26467        }
26468      }
26469      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26470      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26471          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26472           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26473          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26474        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26475          const DRegister& first = nreglist.GetFirstDRegister();
26476          EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
26477                     (encoded_align_2.GetEncodingValue() << 4) |
26478                     first.Encode(22, 12) | (rn.GetCode() << 16) |
26479                     rm.GetCode());
26480          AdvanceIT();
26481          return;
26482        }
26483      }
26484    } else {
26485      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26486      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26487          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26488           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26489           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
26490          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26491        if (cond.Is(al)) {
26492          const DRegister& first = nreglist.GetFirstDRegister();
26493          uint32_t len_encoding;
26494          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26495            len_encoding = 0x8;
26496          }
26497          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26498            len_encoding = 0x9;
26499          }
26500          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26501            len_encoding = 0x3;
26502          }
26503          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26504                  (encoded_align_1.GetEncodingValue() << 4) |
26505                  first.Encode(22, 12) | (len_encoding << 8) |
26506                  (rn.GetCode() << 16) | rm.GetCode());
26507          return;
26508        }
26509      }
26510      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26511      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26512          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26513           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
26514          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26515        if (cond.Is(al)) {
26516          const DRegister& first = nreglist.GetFirstDRegister();
26517          EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
26518                  (encoded_align_2.GetEncodingValue() << 4) |
26519                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26520          return;
26521        }
26522      }
26523    }
26524  }
26525  Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
26526}
26527
26528void Assembler::vst3(Condition cond,
26529                     DataType dt,
26530                     const NeonRegisterList& nreglist,
26531                     const AlignedMemOperand& operand) {
26532  VIXL_ASSERT(AllowAssembler());
26533  CheckIT(cond);
26534  if (operand.IsImmediateZero()) {
26535    Register rn = operand.GetBaseRegister();
26536    Alignment align = operand.GetAlignment();
26537    Dt_size_7 encoded_dt(dt);
26538    Align_align_3 encoded_align_1(align);
26539    if (IsUsingT32()) {
26540      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26541      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26542          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26543           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26544          operand.IsOffset() && encoded_align_1.IsValid() &&
26545          (!rn.IsPC() || AllowUnpredictable())) {
26546        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26547          const DRegister& first = nreglist.GetFirstDRegister();
26548          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26549          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26550                     (encoded_align_1.GetEncodingValue() << 4) |
26551                     first.Encode(22, 12) | (len_encoding << 8) |
26552                     (rn.GetCode() << 16));
26553          AdvanceIT();
26554          return;
26555        }
26556      }
26557      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26558      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26559          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26560           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26561          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26562          (!rn.IsPC() || AllowUnpredictable())) {
26563        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26564          const DRegister& first = nreglist.GetFirstDRegister();
26565          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26566          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26567                     (encoded_align_1.GetEncodingValue() << 4) |
26568                     first.Encode(22, 12) | (len_encoding << 8) |
26569                     (rn.GetCode() << 16));
26570          AdvanceIT();
26571          return;
26572        }
26573      }
26574    } else {
26575      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26576      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26577          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26578           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26579          operand.IsOffset() && encoded_align_1.IsValid() &&
26580          (!rn.IsPC() || AllowUnpredictable())) {
26581        if (cond.Is(al)) {
26582          const DRegister& first = nreglist.GetFirstDRegister();
26583          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26584          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26585                  (encoded_align_1.GetEncodingValue() << 4) |
26586                  first.Encode(22, 12) | (len_encoding << 8) |
26587                  (rn.GetCode() << 16));
26588          return;
26589        }
26590      }
26591      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26592      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26593          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26594           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26595          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26596          (!rn.IsPC() || AllowUnpredictable())) {
26597        if (cond.Is(al)) {
26598          const DRegister& first = nreglist.GetFirstDRegister();
26599          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26600          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26601                  (encoded_align_1.GetEncodingValue() << 4) |
26602                  first.Encode(22, 12) | (len_encoding << 8) |
26603                  (rn.GetCode() << 16));
26604          return;
26605        }
26606      }
26607    }
26608  }
26609  if (operand.IsPlainRegister()) {
26610    Register rn = operand.GetBaseRegister();
26611    Alignment align = operand.GetAlignment();
26612    Register rm = operand.GetOffsetRegister();
26613    Dt_size_7 encoded_dt(dt);
26614    Align_align_3 encoded_align_1(align);
26615    if (IsUsingT32()) {
26616      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26617      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26618          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26619           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26620          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26621        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26622          const DRegister& first = nreglist.GetFirstDRegister();
26623          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26624          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26625                     (encoded_align_1.GetEncodingValue() << 4) |
26626                     first.Encode(22, 12) | (len_encoding << 8) |
26627                     (rn.GetCode() << 16) | rm.GetCode());
26628          AdvanceIT();
26629          return;
26630        }
26631      }
26632    } else {
26633      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26634      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26635          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26636           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26637          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26638        if (cond.Is(al)) {
26639          const DRegister& first = nreglist.GetFirstDRegister();
26640          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26641          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26642                  (encoded_align_1.GetEncodingValue() << 4) |
26643                  first.Encode(22, 12) | (len_encoding << 8) |
26644                  (rn.GetCode() << 16) | rm.GetCode());
26645          return;
26646        }
26647      }
26648    }
26649  }
26650  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26651}
26652
26653void Assembler::vst3(Condition cond,
26654                     DataType dt,
26655                     const NeonRegisterList& nreglist,
26656                     const MemOperand& operand) {
26657  VIXL_ASSERT(AllowAssembler());
26658  CheckIT(cond);
26659  if (operand.IsImmediateZero()) {
26660    Register rn = operand.GetBaseRegister();
26661    Dt_size_7 encoded_dt(dt);
26662    Index_1 encoded_align_1(nreglist, dt);
26663    if (IsUsingT32()) {
26664      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
26665      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26666          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26667           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26668          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
26669        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26670          const DRegister& first = nreglist.GetFirstDRegister();
26671          EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
26672                     (encoded_align_1.GetEncodingValue() << 4) |
26673                     first.Encode(22, 12) | (rn.GetCode() << 16));
26674          AdvanceIT();
26675          return;
26676        }
26677      }
26678      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
26679      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26680          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26681           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26682          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
26683        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26684          const DRegister& first = nreglist.GetFirstDRegister();
26685          EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
26686                     (encoded_align_1.GetEncodingValue() << 4) |
26687                     first.Encode(22, 12) | (rn.GetCode() << 16));
26688          AdvanceIT();
26689          return;
26690        }
26691      }
26692    } else {
26693      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
26694      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26695          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26696           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26697          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
26698        if (cond.Is(al)) {
26699          const DRegister& first = nreglist.GetFirstDRegister();
26700          EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
26701                  (encoded_align_1.GetEncodingValue() << 4) |
26702                  first.Encode(22, 12) | (rn.GetCode() << 16));
26703          return;
26704        }
26705      }
26706      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
26707      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26708          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26709           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26710          operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
26711        if (cond.Is(al)) {
26712          const DRegister& first = nreglist.GetFirstDRegister();
26713          EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
26714                  (encoded_align_1.GetEncodingValue() << 4) |
26715                  first.Encode(22, 12) | (rn.GetCode() << 16));
26716          return;
26717        }
26718      }
26719    }
26720  }
26721  if (operand.IsPlainRegister()) {
26722    Register rn = operand.GetBaseRegister();
26723    Sign sign = operand.GetSign();
26724    Register rm = operand.GetOffsetRegister();
26725    Dt_size_7 encoded_dt(dt);
26726    Index_1 encoded_align_1(nreglist, dt);
26727    if (IsUsingT32()) {
26728      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
26729      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26730          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26731           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26732          sign.IsPlus() && operand.IsPostIndex() &&
26733          (!rn.IsPC() || AllowUnpredictable())) {
26734        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26735          const DRegister& first = nreglist.GetFirstDRegister();
26736          EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
26737                     (encoded_align_1.GetEncodingValue() << 4) |
26738                     first.Encode(22, 12) | (rn.GetCode() << 16) |
26739                     rm.GetCode());
26740          AdvanceIT();
26741          return;
26742        }
26743      }
26744    } else {
26745      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
26746      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26747          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26748           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
26749          sign.IsPlus() && operand.IsPostIndex() &&
26750          (!rn.IsPC() || AllowUnpredictable())) {
26751        if (cond.Is(al)) {
26752          const DRegister& first = nreglist.GetFirstDRegister();
26753          EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
26754                  (encoded_align_1.GetEncodingValue() << 4) |
26755                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26756          return;
26757        }
26758      }
26759    }
26760  }
26761  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26762}
26763
26764void Assembler::vst4(Condition cond,
26765                     DataType dt,
26766                     const NeonRegisterList& nreglist,
26767                     const AlignedMemOperand& operand) {
26768  VIXL_ASSERT(AllowAssembler());
26769  CheckIT(cond);
26770  if (operand.IsImmediateZero()) {
26771    Register rn = operand.GetBaseRegister();
26772    Alignment align = operand.GetAlignment();
26773    Dt_size_7 encoded_dt(dt);
26774    Align_align_4 encoded_align_1(align);
26775    Align_index_align_3 encoded_align_2(align, nreglist, dt);
26776    if (IsUsingT32()) {
26777      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26778      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26779          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26780           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26781          operand.IsOffset() && encoded_align_1.IsValid() &&
26782          (!rn.IsPC() || AllowUnpredictable())) {
26783        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26784          const DRegister& first = nreglist.GetFirstDRegister();
26785          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26786          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26787                     (encoded_align_1.GetEncodingValue() << 4) |
26788                     first.Encode(22, 12) | (len_encoding << 8) |
26789                     (rn.GetCode() << 16));
26790          AdvanceIT();
26791          return;
26792        }
26793      }
26794      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26795      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26796          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26797           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26798          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26799          (!rn.IsPC() || AllowUnpredictable())) {
26800        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26801          const DRegister& first = nreglist.GetFirstDRegister();
26802          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26803          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26804                     (encoded_align_1.GetEncodingValue() << 4) |
26805                     first.Encode(22, 12) | (len_encoding << 8) |
26806                     (rn.GetCode() << 16));
26807          AdvanceIT();
26808          return;
26809        }
26810      }
26811      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26812      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26813          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26814           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26815          operand.IsOffset() && encoded_align_2.IsValid() &&
26816          (!rn.IsPC() || AllowUnpredictable())) {
26817        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26818          const DRegister& first = nreglist.GetFirstDRegister();
26819          EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
26820                     (encoded_align_2.GetEncodingValue() << 4) |
26821                     first.Encode(22, 12) | (rn.GetCode() << 16));
26822          AdvanceIT();
26823          return;
26824        }
26825      }
26826      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26827      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26828          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26829           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26830          operand.IsPostIndex() && encoded_align_2.IsValid() &&
26831          (!rn.IsPC() || AllowUnpredictable())) {
26832        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26833          const DRegister& first = nreglist.GetFirstDRegister();
26834          EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
26835                     (encoded_align_2.GetEncodingValue() << 4) |
26836                     first.Encode(22, 12) | (rn.GetCode() << 16));
26837          AdvanceIT();
26838          return;
26839        }
26840      }
26841    } else {
26842      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26843      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26844          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26845           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26846          operand.IsOffset() && encoded_align_1.IsValid() &&
26847          (!rn.IsPC() || AllowUnpredictable())) {
26848        if (cond.Is(al)) {
26849          const DRegister& first = nreglist.GetFirstDRegister();
26850          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26851          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26852                  (encoded_align_1.GetEncodingValue() << 4) |
26853                  first.Encode(22, 12) | (len_encoding << 8) |
26854                  (rn.GetCode() << 16));
26855          return;
26856        }
26857      }
26858      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26859      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26860          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26861           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26862          operand.IsPostIndex() && encoded_align_1.IsValid() &&
26863          (!rn.IsPC() || AllowUnpredictable())) {
26864        if (cond.Is(al)) {
26865          const DRegister& first = nreglist.GetFirstDRegister();
26866          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26867          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26868                  (encoded_align_1.GetEncodingValue() << 4) |
26869                  first.Encode(22, 12) | (len_encoding << 8) |
26870                  (rn.GetCode() << 16));
26871          return;
26872        }
26873      }
26874      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26875      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26876          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26877           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26878          operand.IsOffset() && encoded_align_2.IsValid() &&
26879          (!rn.IsPC() || AllowUnpredictable())) {
26880        if (cond.Is(al)) {
26881          const DRegister& first = nreglist.GetFirstDRegister();
26882          EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
26883                  (encoded_align_2.GetEncodingValue() << 4) |
26884                  first.Encode(22, 12) | (rn.GetCode() << 16));
26885          return;
26886        }
26887      }
26888      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26889      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26890          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26891           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26892          operand.IsPostIndex() && encoded_align_2.IsValid() &&
26893          (!rn.IsPC() || AllowUnpredictable())) {
26894        if (cond.Is(al)) {
26895          const DRegister& first = nreglist.GetFirstDRegister();
26896          EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
26897                  (encoded_align_2.GetEncodingValue() << 4) |
26898                  first.Encode(22, 12) | (rn.GetCode() << 16));
26899          return;
26900        }
26901      }
26902    }
26903  }
26904  if (operand.IsPlainRegister()) {
26905    Register rn = operand.GetBaseRegister();
26906    Alignment align = operand.GetAlignment();
26907    Register rm = operand.GetOffsetRegister();
26908    Dt_size_7 encoded_dt(dt);
26909    Align_align_4 encoded_align_1(align);
26910    Align_index_align_3 encoded_align_2(align, nreglist, dt);
26911    if (IsUsingT32()) {
26912      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26913      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26914          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26915           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26916          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26917        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26918          const DRegister& first = nreglist.GetFirstDRegister();
26919          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26920          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26921                     (encoded_align_1.GetEncodingValue() << 4) |
26922                     first.Encode(22, 12) | (len_encoding << 8) |
26923                     (rn.GetCode() << 16) | rm.GetCode());
26924          AdvanceIT();
26925          return;
26926        }
26927      }
26928      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26929      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26930          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26931           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26932          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26933        if (cond.Is(al) || AllowStronglyDiscouraged()) {
26934          const DRegister& first = nreglist.GetFirstDRegister();
26935          EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
26936                     (encoded_align_2.GetEncodingValue() << 4) |
26937                     first.Encode(22, 12) | (rn.GetCode() << 16) |
26938                     rm.GetCode());
26939          AdvanceIT();
26940          return;
26941        }
26942      }
26943    } else {
26944      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26945      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26946          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26947           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26948          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26949        if (cond.Is(al)) {
26950          const DRegister& first = nreglist.GetFirstDRegister();
26951          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26952          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26953                  (encoded_align_1.GetEncodingValue() << 4) |
26954                  first.Encode(22, 12) | (len_encoding << 8) |
26955                  (rn.GetCode() << 16) | rm.GetCode());
26956          return;
26957        }
26958      }
26959      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26960      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26961          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26962           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
26963          !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
26964        if (cond.Is(al)) {
26965          const DRegister& first = nreglist.GetFirstDRegister();
26966          EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
26967                  (encoded_align_2.GetEncodingValue() << 4) |
26968                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26969          return;
26970        }
26971      }
26972    }
26973  }
26974  Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
26975}
26976
26977void Assembler::vstm(Condition cond,
26978                     DataType dt,
26979                     Register rn,
26980                     WriteBack write_back,
26981                     DRegisterList dreglist) {
26982  VIXL_ASSERT(AllowAssembler());
26983  CheckIT(cond);
26984  USE(dt);
26985  if (IsUsingT32()) {
26986    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
26987    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
26988         AllowUnpredictable())) {
26989      const DRegister& dreg = dreglist.GetFirstDRegister();
26990      unsigned len = dreglist.GetLength() * 2;
26991      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
26992                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
26993                 (len & 0xff));
26994      AdvanceIT();
26995      return;
26996    }
26997  } else {
26998    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
26999    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27000                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27001                              AllowUnpredictable())) {
27002      const DRegister& dreg = dreglist.GetFirstDRegister();
27003      unsigned len = dreglist.GetLength() * 2;
27004      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27005              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27006              (len & 0xff));
27007      return;
27008    }
27009  }
27010  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
27011}
27012
27013void Assembler::vstm(Condition cond,
27014                     DataType dt,
27015                     Register rn,
27016                     WriteBack write_back,
27017                     SRegisterList sreglist) {
27018  VIXL_ASSERT(AllowAssembler());
27019  CheckIT(cond);
27020  USE(dt);
27021  if (IsUsingT32()) {
27022    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
27023    if ((!rn.IsPC() || AllowUnpredictable())) {
27024      const SRegister& sreg = sreglist.GetFirstSRegister();
27025      unsigned len = sreglist.GetLength();
27026      EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27027                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27028                 (len & 0xff));
27029      AdvanceIT();
27030      return;
27031    }
27032  } else {
27033    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
27034    if (cond.IsNotNever() &&
27035        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
27036      const SRegister& sreg = sreglist.GetFirstSRegister();
27037      unsigned len = sreglist.GetLength();
27038      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27039              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27040              (len & 0xff));
27041      return;
27042    }
27043  }
27044  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
27045}
27046
27047void Assembler::vstmdb(Condition cond,
27048                       DataType dt,
27049                       Register rn,
27050                       WriteBack write_back,
27051                       DRegisterList dreglist) {
27052  VIXL_ASSERT(AllowAssembler());
27053  CheckIT(cond);
27054  USE(dt);
27055  if (IsUsingT32()) {
27056    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
27057    if (write_back.DoesWriteBack() &&
27058        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27059         AllowUnpredictable())) {
27060      const DRegister& dreg = dreglist.GetFirstDRegister();
27061      unsigned len = dreglist.GetLength() * 2;
27062      EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
27063                 (len & 0xff));
27064      AdvanceIT();
27065      return;
27066    }
27067  } else {
27068    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
27069    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
27070        (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27071         AllowUnpredictable())) {
27072      const DRegister& dreg = dreglist.GetFirstDRegister();
27073      unsigned len = dreglist.GetLength() * 2;
27074      EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27075              dreg.Encode(22, 12) | (len & 0xff));
27076      return;
27077    }
27078  }
27079  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
27080}
27081
27082void Assembler::vstmdb(Condition cond,
27083                       DataType dt,
27084                       Register rn,
27085                       WriteBack write_back,
27086                       SRegisterList sreglist) {
27087  VIXL_ASSERT(AllowAssembler());
27088  CheckIT(cond);
27089  USE(dt);
27090  if (IsUsingT32()) {
27091    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
27092    if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
27093      const SRegister& sreg = sreglist.GetFirstSRegister();
27094      unsigned len = sreglist.GetLength();
27095      EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
27096                 (len & 0xff));
27097      AdvanceIT();
27098      return;
27099    }
27100  } else {
27101    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
27102    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
27103        (!rn.IsPC() || AllowUnpredictable())) {
27104      const SRegister& sreg = sreglist.GetFirstSRegister();
27105      unsigned len = sreglist.GetLength();
27106      EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27107              sreg.Encode(22, 12) | (len & 0xff));
27108      return;
27109    }
27110  }
27111  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
27112}
27113
27114void Assembler::vstmia(Condition cond,
27115                       DataType dt,
27116                       Register rn,
27117                       WriteBack write_back,
27118                       DRegisterList dreglist) {
27119  VIXL_ASSERT(AllowAssembler());
27120  CheckIT(cond);
27121  USE(dt);
27122  if (IsUsingT32()) {
27123    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
27124    if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27125         AllowUnpredictable())) {
27126      const DRegister& dreg = dreglist.GetFirstDRegister();
27127      unsigned len = dreglist.GetLength() * 2;
27128      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27129                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27130                 (len & 0xff));
27131      AdvanceIT();
27132      return;
27133    }
27134  } else {
27135    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
27136    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27137                               (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27138                              AllowUnpredictable())) {
27139      const DRegister& dreg = dreglist.GetFirstDRegister();
27140      unsigned len = dreglist.GetLength() * 2;
27141      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27142              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27143              (len & 0xff));
27144      return;
27145    }
27146  }
27147  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
27148}
27149
27150void Assembler::vstmia(Condition cond,
27151                       DataType dt,
27152                       Register rn,
27153                       WriteBack write_back,
27154                       SRegisterList sreglist) {
27155  VIXL_ASSERT(AllowAssembler());
27156  CheckIT(cond);
27157  USE(dt);
27158  if (IsUsingT32()) {
27159    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
27160    if ((!rn.IsPC() || AllowUnpredictable())) {
27161      const SRegister& sreg = sreglist.GetFirstSRegister();
27162      unsigned len = sreglist.GetLength();
27163      EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27164                 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27165                 (len & 0xff));
27166      AdvanceIT();
27167      return;
27168    }
27169  } else {
27170    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
27171    if (cond.IsNotNever() &&
27172        ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
27173      const SRegister& sreg = sreglist.GetFirstSRegister();
27174      unsigned len = sreglist.GetLength();
27175      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27176              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27177              (len & 0xff));
27178      return;
27179    }
27180  }
27181  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
27182}
27183
27184void Assembler::vstr(Condition cond,
27185                     DataType dt,
27186                     DRegister rd,
27187                     const MemOperand& operand) {
27188  VIXL_ASSERT(AllowAssembler());
27189  CheckIT(cond);
27190  if (operand.IsImmediate()) {
27191    Register rn = operand.GetBaseRegister();
27192    int32_t offset = operand.GetOffsetImmediate();
27193    if (IsUsingT32()) {
27194      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
27195      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
27196          ((offset % 4) == 0) && operand.IsOffset() &&
27197          (!rn.IsPC() || AllowUnpredictable())) {
27198        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27199        uint32_t offset_ = abs(offset) >> 2;
27200        EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27201                   offset_ | (sign << 23));
27202        AdvanceIT();
27203        return;
27204      }
27205    } else {
27206      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
27207      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
27208          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
27209        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27210        uint32_t offset_ = abs(offset) >> 2;
27211        EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27212                (rn.GetCode() << 16) | offset_ | (sign << 23));
27213        return;
27214      }
27215    }
27216  }
27217  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27218}
27219
27220void Assembler::vstr(Condition cond,
27221                     DataType dt,
27222                     SRegister rd,
27223                     const MemOperand& operand) {
27224  VIXL_ASSERT(AllowAssembler());
27225  CheckIT(cond);
27226  if (operand.IsImmediate()) {
27227    Register rn = operand.GetBaseRegister();
27228    int32_t offset = operand.GetOffsetImmediate();
27229    if (IsUsingT32()) {
27230      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
27231      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
27232          ((offset % 4) == 0) && operand.IsOffset() &&
27233          (!rn.IsPC() || AllowUnpredictable())) {
27234        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27235        uint32_t offset_ = abs(offset) >> 2;
27236        EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27237                   offset_ | (sign << 23));
27238        AdvanceIT();
27239        return;
27240      }
27241    } else {
27242      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
27243      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
27244          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
27245        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27246        uint32_t offset_ = abs(offset) >> 2;
27247        EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27248                (rn.GetCode() << 16) | offset_ | (sign << 23));
27249        return;
27250      }
27251    }
27252  }
27253  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27254}
27255
27256void Assembler::vsub(
27257    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
27258  VIXL_ASSERT(AllowAssembler());
27259  CheckIT(cond);
27260  Dt_size_2 encoded_dt(dt);
27261  if (IsUsingT32()) {
27262    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
27263    if (dt.Is(F32)) {
27264      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27265        EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27266                   rm.Encode(5, 0));
27267        AdvanceIT();
27268        return;
27269      }
27270    }
27271    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
27272    if (dt.Is(F64)) {
27273      EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27274                 rm.Encode(5, 0));
27275      AdvanceIT();
27276      return;
27277    }
27278    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27279    if (encoded_dt.IsValid()) {
27280      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27281        EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
27282                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27283        AdvanceIT();
27284        return;
27285      }
27286    }
27287  } else {
27288    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
27289    if (dt.Is(F32)) {
27290      if (cond.Is(al)) {
27291        EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27292                rm.Encode(5, 0));
27293        return;
27294      }
27295    }
27296    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
27297    if (dt.Is(F64) && cond.IsNotNever()) {
27298      EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27299              rn.Encode(7, 16) | rm.Encode(5, 0));
27300      return;
27301    }
27302    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27303    if (encoded_dt.IsValid()) {
27304      if (cond.Is(al)) {
27305        EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
27306                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27307        return;
27308      }
27309    }
27310  }
27311  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27312}
27313
27314void Assembler::vsub(
27315    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
27316  VIXL_ASSERT(AllowAssembler());
27317  CheckIT(cond);
27318  Dt_size_2 encoded_dt(dt);
27319  if (IsUsingT32()) {
27320    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
27321    if (dt.Is(F32)) {
27322      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27323        EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27324                   rm.Encode(5, 0));
27325        AdvanceIT();
27326        return;
27327      }
27328    }
27329    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27330    if (encoded_dt.IsValid()) {
27331      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27332        EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
27333                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27334        AdvanceIT();
27335        return;
27336      }
27337    }
27338  } else {
27339    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
27340    if (dt.Is(F32)) {
27341      if (cond.Is(al)) {
27342        EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27343                rm.Encode(5, 0));
27344        return;
27345      }
27346    }
27347    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27348    if (encoded_dt.IsValid()) {
27349      if (cond.Is(al)) {
27350        EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
27351                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27352        return;
27353      }
27354    }
27355  }
27356  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27357}
27358
27359void Assembler::vsub(
27360    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
27361  VIXL_ASSERT(AllowAssembler());
27362  CheckIT(cond);
27363  if (IsUsingT32()) {
27364    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
27365    if (dt.Is(F32)) {
27366      EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27367                 rm.Encode(5, 0));
27368      AdvanceIT();
27369      return;
27370    }
27371  } else {
27372    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
27373    if (dt.Is(F32) && cond.IsNotNever()) {
27374      EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27375              rn.Encode(7, 16) | rm.Encode(5, 0));
27376      return;
27377    }
27378  }
27379  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27380}
27381
27382void Assembler::vsubhn(
27383    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
27384  VIXL_ASSERT(AllowAssembler());
27385  CheckIT(cond);
27386  Dt_size_3 encoded_dt(dt);
27387  if (IsUsingT32()) {
27388    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
27389    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27390      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27391        EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
27392                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27393        AdvanceIT();
27394        return;
27395      }
27396    }
27397  } else {
27398    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
27399    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27400      if (cond.Is(al)) {
27401        EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
27402                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27403        return;
27404      }
27405    }
27406  }
27407  Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
27408}
27409
27410void Assembler::vsubl(
27411    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
27412  VIXL_ASSERT(AllowAssembler());
27413  CheckIT(cond);
27414  Dt_U_size_1 encoded_dt(dt);
27415  if (IsUsingT32()) {
27416    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
27417    if (encoded_dt.IsValid()) {
27418      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27419        EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27420                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27421                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27422        AdvanceIT();
27423        return;
27424      }
27425    }
27426  } else {
27427    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
27428    if (encoded_dt.IsValid()) {
27429      if (cond.Is(al)) {
27430        EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27431                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27432                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27433        return;
27434      }
27435    }
27436  }
27437  Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
27438}
27439
27440void Assembler::vsubw(
27441    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
27442  VIXL_ASSERT(AllowAssembler());
27443  CheckIT(cond);
27444  Dt_U_size_1 encoded_dt(dt);
27445  if (IsUsingT32()) {
27446    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
27447    if (encoded_dt.IsValid()) {
27448      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27449        EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27450                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27451                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27452        AdvanceIT();
27453        return;
27454      }
27455    }
27456  } else {
27457    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
27458    if (encoded_dt.IsValid()) {
27459      if (cond.Is(al)) {
27460        EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27461                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27462                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27463        return;
27464      }
27465    }
27466  }
27467  Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
27468}
27469
27470void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27471  VIXL_ASSERT(AllowAssembler());
27472  CheckIT(cond);
27473  USE(dt);
27474  if (IsUsingT32()) {
27475    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
27476    if (cond.Is(al) || AllowStronglyDiscouraged()) {
27477      EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27478      AdvanceIT();
27479      return;
27480    }
27481  } else {
27482    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
27483    if (cond.Is(al)) {
27484      EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27485      return;
27486    }
27487  }
27488  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27489}
27490
27491void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27492  VIXL_ASSERT(AllowAssembler());
27493  CheckIT(cond);
27494  USE(dt);
27495  if (IsUsingT32()) {
27496    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
27497    if (cond.Is(al) || AllowStronglyDiscouraged()) {
27498      EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27499      AdvanceIT();
27500      return;
27501    }
27502  } else {
27503    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
27504    if (cond.Is(al)) {
27505      EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27506      return;
27507    }
27508  }
27509  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27510}
27511
27512void Assembler::vtbl(Condition cond,
27513                     DataType dt,
27514                     DRegister rd,
27515                     const NeonRegisterList& nreglist,
27516                     DRegister rm) {
27517  VIXL_ASSERT(AllowAssembler());
27518  CheckIT(cond);
27519  if (IsUsingT32()) {
27520    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27521    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27522        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27523      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27524        const DRegister& first = nreglist.GetFirstDRegister();
27525        uint32_t len_encoding = nreglist.GetLength() - 1;
27526        EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27527                   (len_encoding << 8) | rm.Encode(5, 0));
27528        AdvanceIT();
27529        return;
27530      }
27531    }
27532  } else {
27533    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27534    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27535        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27536      if (cond.Is(al)) {
27537        const DRegister& first = nreglist.GetFirstDRegister();
27538        uint32_t len_encoding = nreglist.GetLength() - 1;
27539        EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27540                (len_encoding << 8) | rm.Encode(5, 0));
27541        return;
27542      }
27543    }
27544  }
27545  Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
27546}
27547
27548void Assembler::vtbx(Condition cond,
27549                     DataType dt,
27550                     DRegister rd,
27551                     const NeonRegisterList& nreglist,
27552                     DRegister rm) {
27553  VIXL_ASSERT(AllowAssembler());
27554  CheckIT(cond);
27555  if (IsUsingT32()) {
27556    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27557    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27558        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27559      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27560        const DRegister& first = nreglist.GetFirstDRegister();
27561        uint32_t len_encoding = nreglist.GetLength() - 1;
27562        EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27563                   (len_encoding << 8) | rm.Encode(5, 0));
27564        AdvanceIT();
27565        return;
27566      }
27567    }
27568  } else {
27569    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27570    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27571        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27572      if (cond.Is(al)) {
27573        const DRegister& first = nreglist.GetFirstDRegister();
27574        uint32_t len_encoding = nreglist.GetLength() - 1;
27575        EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27576                (len_encoding << 8) | rm.Encode(5, 0));
27577        return;
27578      }
27579    }
27580  }
27581  Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
27582}
27583
27584void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27585  VIXL_ASSERT(AllowAssembler());
27586  CheckIT(cond);
27587  Dt_size_7 encoded_dt(dt);
27588  if (IsUsingT32()) {
27589    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27590    if (encoded_dt.IsValid()) {
27591      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27592        EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
27593                   rd.Encode(22, 12) | rm.Encode(5, 0));
27594        AdvanceIT();
27595        return;
27596      }
27597    }
27598  } else {
27599    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27600    if (encoded_dt.IsValid()) {
27601      if (cond.Is(al)) {
27602        EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
27603                rd.Encode(22, 12) | rm.Encode(5, 0));
27604        return;
27605      }
27606    }
27607  }
27608  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27609}
27610
27611void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27612  VIXL_ASSERT(AllowAssembler());
27613  CheckIT(cond);
27614  Dt_size_7 encoded_dt(dt);
27615  if (IsUsingT32()) {
27616    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27617    if (encoded_dt.IsValid()) {
27618      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27619        EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
27620                   rd.Encode(22, 12) | rm.Encode(5, 0));
27621        AdvanceIT();
27622        return;
27623      }
27624    }
27625  } else {
27626    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27627    if (encoded_dt.IsValid()) {
27628      if (cond.Is(al)) {
27629        EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
27630                rd.Encode(22, 12) | rm.Encode(5, 0));
27631        return;
27632      }
27633    }
27634  }
27635  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27636}
27637
27638void Assembler::vtst(
27639    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
27640  VIXL_ASSERT(AllowAssembler());
27641  CheckIT(cond);
27642  Dt_size_7 encoded_dt(dt);
27643  if (IsUsingT32()) {
27644    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27645    if (encoded_dt.IsValid()) {
27646      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27647        EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
27648                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27649        AdvanceIT();
27650        return;
27651      }
27652    }
27653  } else {
27654    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27655    if (encoded_dt.IsValid()) {
27656      if (cond.Is(al)) {
27657        EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
27658                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27659        return;
27660      }
27661    }
27662  }
27663  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27664}
27665
27666void Assembler::vtst(
27667    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
27668  VIXL_ASSERT(AllowAssembler());
27669  CheckIT(cond);
27670  Dt_size_7 encoded_dt(dt);
27671  if (IsUsingT32()) {
27672    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27673    if (encoded_dt.IsValid()) {
27674      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27675        EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
27676                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27677        AdvanceIT();
27678        return;
27679      }
27680    }
27681  } else {
27682    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27683    if (encoded_dt.IsValid()) {
27684      if (cond.Is(al)) {
27685        EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
27686                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27687        return;
27688      }
27689    }
27690  }
27691  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27692}
27693
27694void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27695  VIXL_ASSERT(AllowAssembler());
27696  CheckIT(cond);
27697  Dt_size_15 encoded_dt(dt);
27698  if (IsUsingT32()) {
27699    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27700    if (encoded_dt.IsValid()) {
27701      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27702        EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
27703                   rd.Encode(22, 12) | rm.Encode(5, 0));
27704        AdvanceIT();
27705        return;
27706      }
27707    }
27708    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27709    if (dt.Is(Untyped32)) {
27710      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27711        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27712        AdvanceIT();
27713        return;
27714      }
27715    }
27716  } else {
27717    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27718    if (encoded_dt.IsValid()) {
27719      if (cond.Is(al)) {
27720        EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
27721                rd.Encode(22, 12) | rm.Encode(5, 0));
27722        return;
27723      }
27724    }
27725    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27726    if (dt.Is(Untyped32)) {
27727      if (cond.Is(al)) {
27728        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27729        return;
27730      }
27731    }
27732  }
27733  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27734}
27735
27736void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27737  VIXL_ASSERT(AllowAssembler());
27738  CheckIT(cond);
27739  Dt_size_7 encoded_dt(dt);
27740  if (IsUsingT32()) {
27741    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27742    if (encoded_dt.IsValid()) {
27743      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27744        EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
27745                   rd.Encode(22, 12) | rm.Encode(5, 0));
27746        AdvanceIT();
27747        return;
27748      }
27749    }
27750  } else {
27751    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27752    if (encoded_dt.IsValid()) {
27753      if (cond.Is(al)) {
27754        EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
27755                rd.Encode(22, 12) | rm.Encode(5, 0));
27756        return;
27757      }
27758    }
27759  }
27760  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27761}
27762
27763void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
27764  VIXL_ASSERT(AllowAssembler());
27765  CheckIT(cond);
27766  Dt_size_15 encoded_dt(dt);
27767  if (IsUsingT32()) {
27768    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27769    if (encoded_dt.IsValid()) {
27770      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27771        EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
27772                   rd.Encode(22, 12) | rm.Encode(5, 0));
27773        AdvanceIT();
27774        return;
27775      }
27776    }
27777    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27778    if (dt.Is(Untyped32)) {
27779      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27780        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27781        AdvanceIT();
27782        return;
27783      }
27784    }
27785  } else {
27786    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27787    if (encoded_dt.IsValid()) {
27788      if (cond.Is(al)) {
27789        EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
27790                rd.Encode(22, 12) | rm.Encode(5, 0));
27791        return;
27792      }
27793    }
27794    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27795    if (dt.Is(Untyped32)) {
27796      if (cond.Is(al)) {
27797        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27798        return;
27799      }
27800    }
27801  }
27802  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27803}
27804
27805void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
27806  VIXL_ASSERT(AllowAssembler());
27807  CheckIT(cond);
27808  Dt_size_7 encoded_dt(dt);
27809  if (IsUsingT32()) {
27810    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27811    if (encoded_dt.IsValid()) {
27812      if (cond.Is(al) || AllowStronglyDiscouraged()) {
27813        EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
27814                   rd.Encode(22, 12) | rm.Encode(5, 0));
27815        AdvanceIT();
27816        return;
27817      }
27818    }
27819  } else {
27820    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27821    if (encoded_dt.IsValid()) {
27822      if (cond.Is(al)) {
27823        EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
27824                rd.Encode(22, 12) | rm.Encode(5, 0));
27825        return;
27826      }
27827    }
27828  }
27829  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27830}
27831
27832void Assembler::yield(Condition cond, EncodingSize size) {
27833  VIXL_ASSERT(AllowAssembler());
27834  CheckIT(cond);
27835  if (IsUsingT32()) {
27836    // YIELD{<c>}{<q>} ; T1
27837    if (!size.IsWide()) {
27838      EmitT32_16(0xbf10);
27839      AdvanceIT();
27840      return;
27841    }
27842    // YIELD{<c>}.W ; T2
27843    if (!size.IsNarrow()) {
27844      EmitT32_32(0xf3af8001U);
27845      AdvanceIT();
27846      return;
27847    }
27848  } else {
27849    // YIELD{<c>}{<q>} ; A1
27850    if (cond.IsNotNever()) {
27851      EmitA32(0x0320f001U | (cond.GetCondition() << 28));
27852      return;
27853    }
27854  }
27855  Delegate(kYield, &Assembler::yield, cond, size);
27856}
27857// End of generated code.
27858
27859}  // namespace aarch32
27860}  // namespace vixl
27861