assembler-aarch32.cc revision 8ee2cef99dc4fae4129430834d2778d97cb5e076
1// Copyright 2015, 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>  // NOLINT
36
37#include "utils-vixl.h"
38#include "aarch32/constants-aarch32.h"
39#include "aarch32/instructions-aarch32.h"
40#include "aarch32/operand-aarch32.h"
41#include "aarch32/assembler-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    first_condition_ =
72        Condition((first_condition_.GetCondition() & 0xe) | (it_mask_ >> 3));
73    // For A32, AdavanceIT() is not called by the assembler. We must call it
74    // in order to check that IT instructions are used consistently with
75    // the following conditional instructions.
76    if (IsUsingA32()) AdvanceIT();
77  }
78}
79#endif
80
81
82uint32_t Assembler::Link(uint32_t instr,
83                         Label* label,
84                         const Label::LabelEmitOperator& op) {
85  if (label->IsBound()) {
86    return op.Encode(instr,
87                     GetCursorOffset() + GetArchitectureStatePCOffset(),
88                     label);
89  }
90  label->AddForwardRef(GetCursorOffset(), IsUsingT32(), op);
91  return instr;
92}
93
94
95void Assembler::EncodeLabelFor(const Label::ForwardReference& forward,
96                               Label* label) {
97  const uint32_t location = forward.GetLocation();
98  const uint32_t from = location + forward.GetStatePCOffset();
99  const Label::LabelEmitOperator& encoder = forward.GetEmitOperator();
100  if (forward.IsUsingT32()) {
101    uint16_t* instr_ptr = buffer_.GetOffsetAddress<uint16_t*>(location);
102    if (Is16BitEncoding(instr_ptr[0])) {
103      // The Encode methods always deals with uint32_t types so we need
104      // to explicitely cast it.
105      uint32_t instr = static_cast<uint32_t>(instr_ptr[0]);
106      instr = encoder.Encode(instr, from, label);
107      // The Encode method should not ever set the top 16 bits.
108      VIXL_ASSERT((instr & ~0xffff) == 0);
109      instr_ptr[0] = static_cast<uint16_t>(instr);
110    } else {
111      uint32_t instr =
112          instr_ptr[1] | (static_cast<uint32_t>(instr_ptr[0]) << 16);
113      instr = encoder.Encode(instr, from, label);
114      instr_ptr[0] = static_cast<uint16_t>(instr >> 16);
115      instr_ptr[1] = static_cast<uint16_t>(instr);
116    }
117  } else {
118    uint32_t* instr_ptr = buffer_.GetOffsetAddress<uint32_t*>(location);
119    instr_ptr[0] = encoder.Encode(instr_ptr[0], from, label);
120  }
121}
122
123
124void Assembler::bind(Label* label) {
125  VIXL_ASSERT(!label->IsBound());
126  label->Bind(GetCursorOffset(), IsUsingT32());
127
128  for (Label::ForwardRefList::iterator ref = label->GetFirstForwardRef();
129       ref != label->GetEndForwardRef();
130       ref++) {
131    EncodeLabelFor(*ref, label);
132  }
133}
134
135
136// Start of generated code.
137class Dt_L_imm6_1 : public EncodingValue {
138  uint32_t type_;
139
140 public:
141  explicit Dt_L_imm6_1(DataType dt);
142  uint32_t GetTypeEncodingValue() const { return type_; }
143};
144
145Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
146  switch (dt.GetValue()) {
147    case S8:
148      type_ = 0x0;
149      SetEncodingValue(0x1);
150      break;
151    case U8:
152      type_ = 0x1;
153      SetEncodingValue(0x1);
154      break;
155    case S16:
156      type_ = 0x0;
157      SetEncodingValue(0x2);
158      break;
159    case U16:
160      type_ = 0x1;
161      SetEncodingValue(0x2);
162      break;
163    case S32:
164      type_ = 0x0;
165      SetEncodingValue(0x4);
166      break;
167    case U32:
168      type_ = 0x1;
169      SetEncodingValue(0x4);
170      break;
171    case S64:
172      type_ = 0x0;
173      SetEncodingValue(0x8);
174      break;
175    case U64:
176      type_ = 0x1;
177      SetEncodingValue(0x8);
178      break;
179    default:
180      VIXL_UNREACHABLE();
181      type_ = 0x0;
182      break;
183  }
184}
185
186class Dt_L_imm6_2 : public EncodingValue {
187  uint32_t type_;
188
189 public:
190  explicit Dt_L_imm6_2(DataType dt);
191  uint32_t GetTypeEncodingValue() const { return type_; }
192};
193
194Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
195  switch (dt.GetValue()) {
196    case S8:
197      type_ = 0x1;
198      SetEncodingValue(0x1);
199      break;
200    case S16:
201      type_ = 0x1;
202      SetEncodingValue(0x2);
203      break;
204    case S32:
205      type_ = 0x1;
206      SetEncodingValue(0x4);
207      break;
208    case S64:
209      type_ = 0x1;
210      SetEncodingValue(0x8);
211      break;
212    default:
213      VIXL_UNREACHABLE();
214      type_ = 0x0;
215      break;
216  }
217}
218
219class Dt_L_imm6_3 : public EncodingValue {
220 public:
221  explicit Dt_L_imm6_3(DataType dt);
222};
223
224Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
225  switch (dt.GetValue()) {
226    case I8:
227      SetEncodingValue(0x1);
228      break;
229    case I16:
230      SetEncodingValue(0x2);
231      break;
232    case I32:
233      SetEncodingValue(0x4);
234      break;
235    case I64:
236      SetEncodingValue(0x8);
237      break;
238    default:
239      break;
240  }
241}
242
243class Dt_L_imm6_4 : public EncodingValue {
244 public:
245  explicit Dt_L_imm6_4(DataType dt);
246};
247
248Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
249  switch (dt.GetValue()) {
250    case Untyped8:
251      SetEncodingValue(0x1);
252      break;
253    case Untyped16:
254      SetEncodingValue(0x2);
255      break;
256    case Untyped32:
257      SetEncodingValue(0x4);
258      break;
259    case Untyped64:
260      SetEncodingValue(0x8);
261      break;
262    default:
263      break;
264  }
265}
266
267class Dt_imm6_1 : public EncodingValue {
268  uint32_t type_;
269
270 public:
271  explicit Dt_imm6_1(DataType dt);
272  uint32_t GetTypeEncodingValue() const { return type_; }
273};
274
275Dt_imm6_1::Dt_imm6_1(DataType dt) {
276  switch (dt.GetValue()) {
277    case S16:
278      type_ = 0x0;
279      SetEncodingValue(0x1);
280      break;
281    case U16:
282      type_ = 0x1;
283      SetEncodingValue(0x1);
284      break;
285    case S32:
286      type_ = 0x0;
287      SetEncodingValue(0x2);
288      break;
289    case U32:
290      type_ = 0x1;
291      SetEncodingValue(0x2);
292      break;
293    case S64:
294      type_ = 0x0;
295      SetEncodingValue(0x4);
296      break;
297    case U64:
298      type_ = 0x1;
299      SetEncodingValue(0x4);
300      break;
301    default:
302      VIXL_UNREACHABLE();
303      type_ = 0x0;
304      break;
305  }
306}
307
308class Dt_imm6_2 : public EncodingValue {
309  uint32_t type_;
310
311 public:
312  explicit Dt_imm6_2(DataType dt);
313  uint32_t GetTypeEncodingValue() const { return type_; }
314};
315
316Dt_imm6_2::Dt_imm6_2(DataType dt) {
317  switch (dt.GetValue()) {
318    case S16:
319      type_ = 0x1;
320      SetEncodingValue(0x1);
321      break;
322    case S32:
323      type_ = 0x1;
324      SetEncodingValue(0x2);
325      break;
326    case S64:
327      type_ = 0x1;
328      SetEncodingValue(0x4);
329      break;
330    default:
331      VIXL_UNREACHABLE();
332      type_ = 0x0;
333      break;
334  }
335}
336
337class Dt_imm6_3 : public EncodingValue {
338 public:
339  explicit Dt_imm6_3(DataType dt);
340};
341
342Dt_imm6_3::Dt_imm6_3(DataType dt) {
343  switch (dt.GetValue()) {
344    case I16:
345      SetEncodingValue(0x1);
346      break;
347    case I32:
348      SetEncodingValue(0x2);
349      break;
350    case I64:
351      SetEncodingValue(0x4);
352      break;
353    default:
354      break;
355  }
356}
357
358class Dt_imm6_4 : public EncodingValue {
359  uint32_t type_;
360
361 public:
362  explicit Dt_imm6_4(DataType dt);
363  uint32_t GetTypeEncodingValue() const { return type_; }
364};
365
366Dt_imm6_4::Dt_imm6_4(DataType dt) {
367  switch (dt.GetValue()) {
368    case S8:
369      type_ = 0x0;
370      SetEncodingValue(0x1);
371      break;
372    case U8:
373      type_ = 0x1;
374      SetEncodingValue(0x1);
375      break;
376    case S16:
377      type_ = 0x0;
378      SetEncodingValue(0x2);
379      break;
380    case U16:
381      type_ = 0x1;
382      SetEncodingValue(0x2);
383      break;
384    case S32:
385      type_ = 0x0;
386      SetEncodingValue(0x4);
387      break;
388    case U32:
389      type_ = 0x1;
390      SetEncodingValue(0x4);
391      break;
392    default:
393      VIXL_UNREACHABLE();
394      type_ = 0x0;
395      break;
396  }
397}
398
399class Dt_op_U_size_1 : public EncodingValue {
400 public:
401  explicit Dt_op_U_size_1(DataType dt);
402};
403
404Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
405  switch (dt.GetValue()) {
406    case S8:
407      SetEncodingValue(0x0);
408      break;
409    case S16:
410      SetEncodingValue(0x1);
411      break;
412    case S32:
413      SetEncodingValue(0x2);
414      break;
415    case U8:
416      SetEncodingValue(0x4);
417      break;
418    case U16:
419      SetEncodingValue(0x5);
420      break;
421    case U32:
422      SetEncodingValue(0x6);
423      break;
424    case P8:
425      SetEncodingValue(0x8);
426      break;
427    case P64:
428      SetEncodingValue(0xa);
429      break;
430    default:
431      break;
432  }
433}
434
435class Dt_op_size_1 : public EncodingValue {
436 public:
437  explicit Dt_op_size_1(DataType dt);
438};
439
440Dt_op_size_1::Dt_op_size_1(DataType dt) {
441  switch (dt.GetValue()) {
442    case I8:
443      SetEncodingValue(0x0);
444      break;
445    case I16:
446      SetEncodingValue(0x1);
447      break;
448    case I32:
449      SetEncodingValue(0x2);
450      break;
451    case P8:
452      SetEncodingValue(0x4);
453      break;
454    default:
455      break;
456  }
457}
458
459class Dt_op_size_2 : public EncodingValue {
460 public:
461  explicit Dt_op_size_2(DataType dt);
462};
463
464Dt_op_size_2::Dt_op_size_2(DataType dt) {
465  switch (dt.GetValue()) {
466    case S8:
467      SetEncodingValue(0x0);
468      break;
469    case S16:
470      SetEncodingValue(0x1);
471      break;
472    case S32:
473      SetEncodingValue(0x2);
474      break;
475    case U8:
476      SetEncodingValue(0x4);
477      break;
478    case U16:
479      SetEncodingValue(0x5);
480      break;
481    case U32:
482      SetEncodingValue(0x6);
483      break;
484    default:
485      break;
486  }
487}
488
489class Dt_op_size_3 : public EncodingValue {
490 public:
491  explicit Dt_op_size_3(DataType dt);
492};
493
494Dt_op_size_3::Dt_op_size_3(DataType dt) {
495  switch (dt.GetValue()) {
496    case S16:
497      SetEncodingValue(0x0);
498      break;
499    case S32:
500      SetEncodingValue(0x1);
501      break;
502    case S64:
503      SetEncodingValue(0x2);
504      break;
505    case U16:
506      SetEncodingValue(0x4);
507      break;
508    case U32:
509      SetEncodingValue(0x5);
510      break;
511    case U64:
512      SetEncodingValue(0x6);
513      break;
514    default:
515      break;
516  }
517}
518
519class Dt_U_imm3H_1 : public EncodingValue {
520 public:
521  explicit Dt_U_imm3H_1(DataType dt);
522};
523
524Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
525  switch (dt.GetValue()) {
526    case S8:
527      SetEncodingValue(0x1);
528      break;
529    case S16:
530      SetEncodingValue(0x2);
531      break;
532    case S32:
533      SetEncodingValue(0x4);
534      break;
535    case U8:
536      SetEncodingValue(0x9);
537      break;
538    case U16:
539      SetEncodingValue(0xa);
540      break;
541    case U32:
542      SetEncodingValue(0xc);
543      break;
544    default:
545      break;
546  }
547}
548
549class Dt_U_opc1_opc2_1 : public EncodingValue {
550 public:
551  explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
552};
553
554Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
555  switch (dt.GetValue()) {
556    case S8:
557      if ((lane.GetLane() & 7) != lane.GetLane()) {
558        return;
559      }
560      SetEncodingValue(0x8 | lane.GetLane());
561      break;
562    case S16:
563      if ((lane.GetLane() & 3) != lane.GetLane()) {
564        return;
565      }
566      SetEncodingValue(0x1 | (lane.GetLane() << 1));
567      break;
568    case U8:
569      if ((lane.GetLane() & 7) != lane.GetLane()) {
570        return;
571      }
572      SetEncodingValue(0x18 | lane.GetLane());
573      break;
574    case U16:
575      if ((lane.GetLane() & 3) != lane.GetLane()) {
576        return;
577      }
578      SetEncodingValue(0x11 | (lane.GetLane() << 1));
579      break;
580    case Untyped32:
581      if ((lane.GetLane() & 1) != lane.GetLane()) {
582        return;
583      }
584      SetEncodingValue(0x0 | (lane.GetLane() << 2));
585      break;
586    case kDataTypeValueNone:
587      if ((lane.GetLane() & 1) != lane.GetLane()) {
588        return;
589      }
590      SetEncodingValue(0x0 | (lane.GetLane() << 2));
591      break;
592    default:
593      break;
594  }
595}
596
597class Dt_opc1_opc2_1 : public EncodingValue {
598 public:
599  explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
600};
601
602Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
603  switch (dt.GetValue()) {
604    case Untyped8:
605      if ((lane.GetLane() & 7) != lane.GetLane()) {
606        return;
607      }
608      SetEncodingValue(0x8 | lane.GetLane());
609      break;
610    case Untyped16:
611      if ((lane.GetLane() & 3) != lane.GetLane()) {
612        return;
613      }
614      SetEncodingValue(0x1 | (lane.GetLane() << 1));
615      break;
616    case Untyped32:
617      if ((lane.GetLane() & 1) != lane.GetLane()) {
618        return;
619      }
620      SetEncodingValue(0x0 | (lane.GetLane() << 2));
621      break;
622    case kDataTypeValueNone:
623      if ((lane.GetLane() & 1) != lane.GetLane()) {
624        return;
625      }
626      SetEncodingValue(0x0 | (lane.GetLane() << 2));
627      break;
628    default:
629      break;
630  }
631}
632
633class Dt_imm4_1 : public EncodingValue {
634 public:
635  explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
636};
637
638Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
639  switch (dt.GetValue()) {
640    case Untyped8:
641      if ((lane.GetLane() & 7) != lane.GetLane()) {
642        return;
643      }
644      SetEncodingValue(0x1 | (lane.GetLane() << 1));
645      break;
646    case Untyped16:
647      if ((lane.GetLane() & 3) != lane.GetLane()) {
648        return;
649      }
650      SetEncodingValue(0x2 | (lane.GetLane() << 2));
651      break;
652    case Untyped32:
653      if ((lane.GetLane() & 1) != lane.GetLane()) {
654        return;
655      }
656      SetEncodingValue(0x4 | (lane.GetLane() << 3));
657      break;
658    default:
659      break;
660  }
661}
662
663class Dt_B_E_1 : public EncodingValue {
664 public:
665  explicit Dt_B_E_1(DataType dt);
666};
667
668Dt_B_E_1::Dt_B_E_1(DataType dt) {
669  switch (dt.GetValue()) {
670    case Untyped8:
671      SetEncodingValue(0x2);
672      break;
673    case Untyped16:
674      SetEncodingValue(0x1);
675      break;
676    case Untyped32:
677      SetEncodingValue(0x0);
678      break;
679    default:
680      break;
681  }
682}
683
684class Dt_op_1 : public EncodingValue {
685 public:
686  Dt_op_1(DataType dt1, DataType dt2);
687};
688
689Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
690  if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
691    SetEncodingValue(0x0);
692    return;
693  }
694  if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
695    SetEncodingValue(0x1);
696    return;
697  }
698  if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
699    SetEncodingValue(0x2);
700    return;
701  }
702  if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
703    SetEncodingValue(0x3);
704    return;
705  }
706}
707
708class Dt_op_2 : public EncodingValue {
709 public:
710  explicit Dt_op_2(DataType dt);
711};
712
713Dt_op_2::Dt_op_2(DataType dt) {
714  switch (dt.GetValue()) {
715    case U32:
716      SetEncodingValue(0x0);
717      break;
718    case S32:
719      SetEncodingValue(0x1);
720      break;
721    default:
722      break;
723  }
724}
725
726class Dt_op_3 : public EncodingValue {
727 public:
728  explicit Dt_op_3(DataType dt);
729};
730
731Dt_op_3::Dt_op_3(DataType dt) {
732  switch (dt.GetValue()) {
733    case S32:
734      SetEncodingValue(0x0);
735      break;
736    case U32:
737      SetEncodingValue(0x1);
738      break;
739    default:
740      break;
741  }
742}
743
744class Dt_U_sx_1 : public EncodingValue {
745 public:
746  explicit Dt_U_sx_1(DataType dt);
747};
748
749Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
750  switch (dt.GetValue()) {
751    case S16:
752      SetEncodingValue(0x0);
753      break;
754    case S32:
755      SetEncodingValue(0x1);
756      break;
757    case U16:
758      SetEncodingValue(0x2);
759      break;
760    case U32:
761      SetEncodingValue(0x3);
762      break;
763    default:
764      break;
765  }
766}
767
768class Dt_op_U_1 : public EncodingValue {
769 public:
770  Dt_op_U_1(DataType dt1, DataType dt2);
771};
772
773Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
774  if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
775    SetEncodingValue(0x0);
776    return;
777  }
778  if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
779    SetEncodingValue(0x1);
780    return;
781  }
782  if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
783    SetEncodingValue(0x2);
784    return;
785  }
786  if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
787    SetEncodingValue(0x3);
788    return;
789  }
790}
791
792class Dt_sz_1 : public EncodingValue {
793 public:
794  explicit Dt_sz_1(DataType dt);
795};
796
797Dt_sz_1::Dt_sz_1(DataType dt) {
798  switch (dt.GetValue()) {
799    case F32:
800      SetEncodingValue(0x0);
801      break;
802    default:
803      break;
804  }
805}
806
807class Dt_F_size_1 : public EncodingValue {
808 public:
809  explicit Dt_F_size_1(DataType dt);
810};
811
812Dt_F_size_1::Dt_F_size_1(DataType dt) {
813  switch (dt.GetValue()) {
814    case S8:
815      SetEncodingValue(0x0);
816      break;
817    case S16:
818      SetEncodingValue(0x1);
819      break;
820    case S32:
821      SetEncodingValue(0x2);
822      break;
823    case F32:
824      SetEncodingValue(0x6);
825      break;
826    default:
827      break;
828  }
829}
830
831class Dt_F_size_2 : public EncodingValue {
832 public:
833  explicit Dt_F_size_2(DataType dt);
834};
835
836Dt_F_size_2::Dt_F_size_2(DataType dt) {
837  switch (dt.GetValue()) {
838    case I8:
839      SetEncodingValue(0x0);
840      break;
841    case I16:
842      SetEncodingValue(0x1);
843      break;
844    case I32:
845      SetEncodingValue(0x2);
846      break;
847    case F32:
848      SetEncodingValue(0x6);
849      break;
850    default:
851      break;
852  }
853}
854
855class Dt_F_size_3 : public EncodingValue {
856 public:
857  explicit Dt_F_size_3(DataType dt);
858};
859
860Dt_F_size_3::Dt_F_size_3(DataType dt) {
861  switch (dt.GetValue()) {
862    case I16:
863      SetEncodingValue(0x1);
864      break;
865    case I32:
866      SetEncodingValue(0x2);
867      break;
868    case F32:
869      SetEncodingValue(0x6);
870      break;
871    default:
872      break;
873  }
874}
875
876class Dt_F_size_4 : public EncodingValue {
877 public:
878  explicit Dt_F_size_4(DataType dt);
879};
880
881Dt_F_size_4::Dt_F_size_4(DataType dt) {
882  switch (dt.GetValue()) {
883    case U32:
884      SetEncodingValue(0x2);
885      break;
886    case F32:
887      SetEncodingValue(0x6);
888      break;
889    default:
890      break;
891  }
892}
893
894class Dt_U_size_1 : public EncodingValue {
895 public:
896  explicit Dt_U_size_1(DataType dt);
897};
898
899Dt_U_size_1::Dt_U_size_1(DataType dt) {
900  switch (dt.GetValue()) {
901    case S8:
902      SetEncodingValue(0x0);
903      break;
904    case S16:
905      SetEncodingValue(0x1);
906      break;
907    case S32:
908      SetEncodingValue(0x2);
909      break;
910    case U8:
911      SetEncodingValue(0x4);
912      break;
913    case U16:
914      SetEncodingValue(0x5);
915      break;
916    case U32:
917      SetEncodingValue(0x6);
918      break;
919    default:
920      break;
921  }
922}
923
924class Dt_U_size_2 : public EncodingValue {
925 public:
926  explicit Dt_U_size_2(DataType dt);
927};
928
929Dt_U_size_2::Dt_U_size_2(DataType dt) {
930  switch (dt.GetValue()) {
931    case S16:
932      SetEncodingValue(0x1);
933      break;
934    case S32:
935      SetEncodingValue(0x2);
936      break;
937    case U16:
938      SetEncodingValue(0x5);
939      break;
940    case U32:
941      SetEncodingValue(0x6);
942      break;
943    default:
944      break;
945  }
946}
947
948class Dt_U_size_3 : public EncodingValue {
949 public:
950  explicit Dt_U_size_3(DataType dt);
951};
952
953Dt_U_size_3::Dt_U_size_3(DataType dt) {
954  switch (dt.GetValue()) {
955    case S8:
956      SetEncodingValue(0x0);
957      break;
958    case S16:
959      SetEncodingValue(0x1);
960      break;
961    case S32:
962      SetEncodingValue(0x2);
963      break;
964    case S64:
965      SetEncodingValue(0x3);
966      break;
967    case U8:
968      SetEncodingValue(0x4);
969      break;
970    case U16:
971      SetEncodingValue(0x5);
972      break;
973    case U32:
974      SetEncodingValue(0x6);
975      break;
976    case U64:
977      SetEncodingValue(0x7);
978      break;
979    default:
980      break;
981  }
982}
983
984class Dt_size_1 : public EncodingValue {
985 public:
986  explicit Dt_size_1(DataType dt);
987};
988
989Dt_size_1::Dt_size_1(DataType dt) {
990  switch (dt.GetValue()) {
991    case Untyped8:
992      SetEncodingValue(0x0);
993      break;
994    default:
995      break;
996  }
997}
998
999class Dt_size_2 : public EncodingValue {
1000 public:
1001  explicit Dt_size_2(DataType dt);
1002};
1003
1004Dt_size_2::Dt_size_2(DataType dt) {
1005  switch (dt.GetValue()) {
1006    case I8:
1007      SetEncodingValue(0x0);
1008      break;
1009    case I16:
1010      SetEncodingValue(0x1);
1011      break;
1012    case I32:
1013      SetEncodingValue(0x2);
1014      break;
1015    case I64:
1016      SetEncodingValue(0x3);
1017      break;
1018    default:
1019      break;
1020  }
1021}
1022
1023class Dt_size_3 : public EncodingValue {
1024 public:
1025  explicit Dt_size_3(DataType dt);
1026};
1027
1028Dt_size_3::Dt_size_3(DataType dt) {
1029  switch (dt.GetValue()) {
1030    case I16:
1031      SetEncodingValue(0x0);
1032      break;
1033    case I32:
1034      SetEncodingValue(0x1);
1035      break;
1036    case I64:
1037      SetEncodingValue(0x2);
1038      break;
1039    default:
1040      break;
1041  }
1042}
1043
1044class Dt_size_4 : public EncodingValue {
1045 public:
1046  explicit Dt_size_4(DataType dt);
1047};
1048
1049Dt_size_4::Dt_size_4(DataType dt) {
1050  switch (dt.GetValue()) {
1051    case I8:
1052      SetEncodingValue(0x0);
1053      break;
1054    case I16:
1055      SetEncodingValue(0x1);
1056      break;
1057    case I32:
1058      SetEncodingValue(0x2);
1059      break;
1060    default:
1061      break;
1062  }
1063}
1064
1065class Dt_size_5 : public EncodingValue {
1066 public:
1067  explicit Dt_size_5(DataType dt);
1068};
1069
1070Dt_size_5::Dt_size_5(DataType dt) {
1071  switch (dt.GetValue()) {
1072    case S8:
1073      SetEncodingValue(0x0);
1074      break;
1075    case S16:
1076      SetEncodingValue(0x1);
1077      break;
1078    case S32:
1079      SetEncodingValue(0x2);
1080      break;
1081    default:
1082      break;
1083  }
1084}
1085
1086class Dt_size_6 : public EncodingValue {
1087 public:
1088  explicit Dt_size_6(DataType dt);
1089};
1090
1091Dt_size_6::Dt_size_6(DataType dt) {
1092  switch (dt.GetValue()) {
1093    case Untyped8:
1094      SetEncodingValue(0x0);
1095      break;
1096    case Untyped16:
1097      SetEncodingValue(0x1);
1098      break;
1099    case Untyped32:
1100      SetEncodingValue(0x2);
1101      break;
1102    case Untyped64:
1103      SetEncodingValue(0x3);
1104      break;
1105    default:
1106      break;
1107  }
1108}
1109
1110class Dt_size_7 : public EncodingValue {
1111 public:
1112  explicit Dt_size_7(DataType dt);
1113};
1114
1115Dt_size_7::Dt_size_7(DataType dt) {
1116  switch (dt.GetValue()) {
1117    case Untyped8:
1118      SetEncodingValue(0x0);
1119      break;
1120    case Untyped16:
1121      SetEncodingValue(0x1);
1122      break;
1123    case Untyped32:
1124      SetEncodingValue(0x2);
1125      break;
1126    default:
1127      break;
1128  }
1129}
1130
1131class Dt_size_8 : public EncodingValue {
1132 public:
1133  Dt_size_8(DataType dt, Alignment align);
1134};
1135
1136Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
1137  switch (dt.GetValue()) {
1138    case Untyped8:
1139      SetEncodingValue(0x0);
1140      break;
1141    case Untyped16:
1142      SetEncodingValue(0x1);
1143      break;
1144    case Untyped32:
1145      if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
1146        SetEncodingValue(0x2);
1147      } else if (align.Is(k128BitAlign)) {
1148        SetEncodingValue(0x3);
1149      }
1150      break;
1151    default:
1152      break;
1153  }
1154}
1155
1156class Dt_size_9 : public EncodingValue {
1157  uint32_t type_;
1158
1159 public:
1160  explicit Dt_size_9(DataType dt);
1161  uint32_t GetTypeEncodingValue() const { return type_; }
1162};
1163
1164Dt_size_9::Dt_size_9(DataType dt) {
1165  switch (dt.GetValue()) {
1166    case I16:
1167      type_ = 0x0;
1168      SetEncodingValue(0x1);
1169      break;
1170    case I32:
1171      type_ = 0x0;
1172      SetEncodingValue(0x2);
1173      break;
1174    case F32:
1175      type_ = 0x1;
1176      SetEncodingValue(0x2);
1177      break;
1178    default:
1179      VIXL_UNREACHABLE();
1180      type_ = 0x0;
1181      break;
1182  }
1183}
1184
1185class Dt_size_10 : public EncodingValue {
1186 public:
1187  explicit Dt_size_10(DataType dt);
1188};
1189
1190Dt_size_10::Dt_size_10(DataType dt) {
1191  switch (dt.GetValue()) {
1192    case S8:
1193    case U8:
1194    case I8:
1195      SetEncodingValue(0x0);
1196      break;
1197    case S16:
1198    case U16:
1199    case I16:
1200      SetEncodingValue(0x1);
1201      break;
1202    case S32:
1203    case U32:
1204    case I32:
1205      SetEncodingValue(0x2);
1206      break;
1207    default:
1208      break;
1209  }
1210}
1211
1212class Dt_size_11 : public EncodingValue {
1213  uint32_t type_;
1214
1215 public:
1216  explicit Dt_size_11(DataType dt);
1217  uint32_t GetTypeEncodingValue() const { return type_; }
1218};
1219
1220Dt_size_11::Dt_size_11(DataType dt) {
1221  switch (dt.GetValue()) {
1222    case S16:
1223      type_ = 0x0;
1224      SetEncodingValue(0x1);
1225      break;
1226    case U16:
1227      type_ = 0x1;
1228      SetEncodingValue(0x1);
1229      break;
1230    case S32:
1231      type_ = 0x0;
1232      SetEncodingValue(0x2);
1233      break;
1234    case U32:
1235      type_ = 0x1;
1236      SetEncodingValue(0x2);
1237      break;
1238    default:
1239      VIXL_UNREACHABLE();
1240      type_ = 0x0;
1241      break;
1242  }
1243}
1244
1245class Dt_size_12 : public EncodingValue {
1246  uint32_t type_;
1247
1248 public:
1249  explicit Dt_size_12(DataType dt);
1250  uint32_t GetTypeEncodingValue() const { return type_; }
1251};
1252
1253Dt_size_12::Dt_size_12(DataType dt) {
1254  switch (dt.GetValue()) {
1255    case S8:
1256      type_ = 0x0;
1257      SetEncodingValue(0x0);
1258      break;
1259    case U8:
1260      type_ = 0x1;
1261      SetEncodingValue(0x0);
1262      break;
1263    case S16:
1264      type_ = 0x0;
1265      SetEncodingValue(0x1);
1266      break;
1267    case U16:
1268      type_ = 0x1;
1269      SetEncodingValue(0x1);
1270      break;
1271    case S32:
1272      type_ = 0x0;
1273      SetEncodingValue(0x2);
1274      break;
1275    case U32:
1276      type_ = 0x1;
1277      SetEncodingValue(0x2);
1278      break;
1279    default:
1280      VIXL_UNREACHABLE();
1281      type_ = 0x0;
1282      break;
1283  }
1284}
1285
1286class Dt_size_13 : public EncodingValue {
1287 public:
1288  explicit Dt_size_13(DataType dt);
1289};
1290
1291Dt_size_13::Dt_size_13(DataType dt) {
1292  switch (dt.GetValue()) {
1293    case S16:
1294      SetEncodingValue(0x1);
1295      break;
1296    case S32:
1297      SetEncodingValue(0x2);
1298      break;
1299    default:
1300      break;
1301  }
1302}
1303
1304class Dt_size_14 : public EncodingValue {
1305 public:
1306  explicit Dt_size_14(DataType dt);
1307};
1308
1309Dt_size_14::Dt_size_14(DataType dt) {
1310  switch (dt.GetValue()) {
1311    case S16:
1312      SetEncodingValue(0x0);
1313      break;
1314    case S32:
1315      SetEncodingValue(0x1);
1316      break;
1317    case S64:
1318      SetEncodingValue(0x2);
1319      break;
1320    default:
1321      break;
1322  }
1323}
1324
1325class Dt_size_15 : public EncodingValue {
1326 public:
1327  explicit Dt_size_15(DataType dt);
1328};
1329
1330Dt_size_15::Dt_size_15(DataType dt) {
1331  switch (dt.GetValue()) {
1332    case Untyped8:
1333      SetEncodingValue(0x0);
1334      break;
1335    case Untyped16:
1336      SetEncodingValue(0x1);
1337      break;
1338    default:
1339      break;
1340  }
1341}
1342
1343class Dt_size_16 : public EncodingValue {
1344 public:
1345  explicit Dt_size_16(DataType dt);
1346};
1347
1348Dt_size_16::Dt_size_16(DataType dt) {
1349  switch (dt.GetValue()) {
1350    case I8:
1351      SetEncodingValue(0x0);
1352      break;
1353    case I16:
1354      SetEncodingValue(0x1);
1355      break;
1356    case I32:
1357      SetEncodingValue(0x2);
1358      break;
1359    default:
1360      break;
1361  }
1362}
1363
1364class Index_1 : public EncodingValue {
1365 public:
1366  Index_1(const NeonRegisterList& nreglist, DataType dt);
1367};
1368
1369Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1370  switch (dt.GetValue()) {
1371    case Untyped8: {
1372      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1373        return;
1374      }
1375      uint32_t value = nreglist.GetTransferLane() << 1;
1376      if (!nreglist.IsSingleSpaced()) return;
1377      SetEncodingValue(value);
1378      break;
1379    }
1380    case Untyped16: {
1381      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1382        return;
1383      }
1384      uint32_t value = nreglist.GetTransferLane() << 2;
1385      if (nreglist.IsDoubleSpaced()) value |= 2;
1386      SetEncodingValue(value);
1387      break;
1388    }
1389    case Untyped32: {
1390      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1391        return;
1392      }
1393      uint32_t value = nreglist.GetTransferLane() << 3;
1394      if (nreglist.IsDoubleSpaced()) value |= 4;
1395      SetEncodingValue(value);
1396      break;
1397    }
1398    default:
1399      break;
1400  }
1401}
1402
1403class Align_index_align_1 : public EncodingValue {
1404 public:
1405  Align_index_align_1(Alignment align,
1406                      const NeonRegisterList& nreglist,
1407                      DataType dt);
1408};
1409
1410Align_index_align_1::Align_index_align_1(Alignment align,
1411                                         const NeonRegisterList& nreglist,
1412                                         DataType dt) {
1413  switch (dt.GetValue()) {
1414    case Untyped8: {
1415      uint32_t value;
1416      if (align.GetType() == kNoAlignment) {
1417        value = 0;
1418      } else {
1419        return;
1420      }
1421      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1422        return;
1423      }
1424      value |= nreglist.GetTransferLane() << 1;
1425      SetEncodingValue(value);
1426      break;
1427    }
1428    case Untyped16: {
1429      uint32_t value;
1430      if (align.GetType() == k16BitAlign) {
1431        value = 1;
1432      } else if (align.GetType() == kNoAlignment) {
1433        value = 0;
1434      } else {
1435        return;
1436      }
1437      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1438        return;
1439      }
1440      value |= nreglist.GetTransferLane() << 2;
1441      SetEncodingValue(value);
1442      break;
1443    }
1444    case Untyped32: {
1445      uint32_t value;
1446      if (align.GetType() == k32BitAlign) {
1447        value = 3;
1448      } else if (align.GetType() == kNoAlignment) {
1449        value = 0;
1450      } else {
1451        return;
1452      }
1453      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1454        return;
1455      }
1456      value |= nreglist.GetTransferLane() << 3;
1457      SetEncodingValue(value);
1458      break;
1459    }
1460    default:
1461      break;
1462  }
1463}
1464
1465class Align_index_align_2 : public EncodingValue {
1466 public:
1467  Align_index_align_2(Alignment align,
1468                      const NeonRegisterList& nreglist,
1469                      DataType dt);
1470};
1471
1472Align_index_align_2::Align_index_align_2(Alignment align,
1473                                         const NeonRegisterList& nreglist,
1474                                         DataType dt) {
1475  switch (dt.GetValue()) {
1476    case Untyped8: {
1477      uint32_t value;
1478      if (align.GetType() == k16BitAlign) {
1479        value = 1;
1480      } else if (align.GetType() == kNoAlignment) {
1481        value = 0;
1482      } else {
1483        return;
1484      }
1485      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1486        return;
1487      }
1488      value |= nreglist.GetTransferLane() << 1;
1489      if (!nreglist.IsSingleSpaced()) return;
1490      SetEncodingValue(value);
1491      break;
1492    }
1493    case Untyped16: {
1494      uint32_t value;
1495      if (align.GetType() == k32BitAlign) {
1496        value = 1;
1497      } else if (align.GetType() == kNoAlignment) {
1498        value = 0;
1499      } else {
1500        return;
1501      }
1502      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1503        return;
1504      }
1505      value |= nreglist.GetTransferLane() << 2;
1506      if (nreglist.IsDoubleSpaced()) value |= 2;
1507      SetEncodingValue(value);
1508      break;
1509    }
1510    case Untyped32: {
1511      uint32_t value;
1512      if (align.GetType() == k64BitAlign) {
1513        value = 1;
1514      } else if (align.GetType() == kNoAlignment) {
1515        value = 0;
1516      } else {
1517        return;
1518      }
1519      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1520        return;
1521      }
1522      value |= nreglist.GetTransferLane() << 3;
1523      if (nreglist.IsDoubleSpaced()) value |= 4;
1524      SetEncodingValue(value);
1525      break;
1526    }
1527    default:
1528      break;
1529  }
1530}
1531
1532class Align_index_align_3 : public EncodingValue {
1533 public:
1534  Align_index_align_3(Alignment align,
1535                      const NeonRegisterList& nreglist,
1536                      DataType dt);
1537};
1538
1539Align_index_align_3::Align_index_align_3(Alignment align,
1540                                         const NeonRegisterList& nreglist,
1541                                         DataType dt) {
1542  switch (dt.GetValue()) {
1543    case Untyped8: {
1544      uint32_t value;
1545      if (align.GetType() == k32BitAlign) {
1546        value = 1;
1547      } else if (align.GetType() == kNoAlignment) {
1548        value = 0;
1549      } else {
1550        return;
1551      }
1552      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1553        return;
1554      }
1555      value |= nreglist.GetTransferLane() << 1;
1556      if (!nreglist.IsSingleSpaced()) return;
1557      SetEncodingValue(value);
1558      break;
1559    }
1560    case Untyped16: {
1561      uint32_t value;
1562      if (align.GetType() == k64BitAlign) {
1563        value = 1;
1564      } else if (align.GetType() == kNoAlignment) {
1565        value = 0;
1566      } else {
1567        return;
1568      }
1569      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1570        return;
1571      }
1572      value |= nreglist.GetTransferLane() << 2;
1573      if (nreglist.IsDoubleSpaced()) value |= 2;
1574      SetEncodingValue(value);
1575      break;
1576    }
1577    case Untyped32: {
1578      uint32_t value;
1579      if (align.GetType() == k64BitAlign) {
1580        value = 1;
1581      } else if (align.GetType() == k128BitAlign) {
1582        value = 2;
1583      } else if (align.GetType() == kNoAlignment) {
1584        value = 0;
1585      } else {
1586        return;
1587      }
1588      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1589        return;
1590      }
1591      value |= nreglist.GetTransferLane() << 3;
1592      if (nreglist.IsDoubleSpaced()) value |= 4;
1593      SetEncodingValue(value);
1594      break;
1595    }
1596    default:
1597      break;
1598  }
1599}
1600
1601class Align_a_1 : public EncodingValue {
1602 public:
1603  Align_a_1(Alignment align, DataType dt);
1604};
1605
1606Align_a_1::Align_a_1(Alignment align, DataType dt) {
1607  switch (align.GetType()) {
1608    case k16BitAlign:
1609      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1610      break;
1611    case k32BitAlign:
1612      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1613      break;
1614    case kNoAlignment:
1615      SetEncodingValue(0x0);
1616      break;
1617    default:
1618      break;
1619  }
1620}
1621
1622class Align_a_2 : public EncodingValue {
1623 public:
1624  Align_a_2(Alignment align, DataType dt);
1625};
1626
1627Align_a_2::Align_a_2(Alignment align, DataType dt) {
1628  switch (align.GetType()) {
1629    case k16BitAlign:
1630      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1631      break;
1632    case k32BitAlign:
1633      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1634      break;
1635    case k64BitAlign:
1636      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1637      break;
1638    case kNoAlignment:
1639      SetEncodingValue(0x0);
1640      break;
1641    default:
1642      break;
1643  }
1644}
1645
1646class Align_a_3 : public EncodingValue {
1647 public:
1648  Align_a_3(Alignment align, DataType dt);
1649};
1650
1651Align_a_3::Align_a_3(Alignment align, DataType dt) {
1652  switch (align.GetType()) {
1653    case k32BitAlign:
1654      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1655      break;
1656    case k64BitAlign:
1657      if (dt.Is(Untyped16))
1658        SetEncodingValue(0x1);
1659      else if (dt.Is(Untyped32))
1660        SetEncodingValue(0x1);
1661      break;
1662    case k128BitAlign:
1663      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1664      break;
1665    case kNoAlignment:
1666      SetEncodingValue(0x0);
1667      break;
1668    default:
1669      break;
1670  }
1671}
1672
1673class Align_align_1 : public EncodingValue {
1674 public:
1675  Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1676};
1677
1678Align_align_1::Align_align_1(Alignment align,
1679                             const NeonRegisterList& nreglist) {
1680  switch (align.GetType()) {
1681    case k64BitAlign:
1682      SetEncodingValue(0x1);
1683      break;
1684    case k128BitAlign:
1685      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1686        SetEncodingValue(0x2);
1687      break;
1688    case k256BitAlign:
1689      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1690        SetEncodingValue(0x3);
1691      break;
1692    case kNoAlignment:
1693      SetEncodingValue(0x0);
1694      break;
1695    default:
1696      break;
1697  }
1698}
1699
1700class Align_align_2 : public EncodingValue {
1701 public:
1702  Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1703};
1704
1705Align_align_2::Align_align_2(Alignment align,
1706                             const NeonRegisterList& nreglist) {
1707  switch (align.GetType()) {
1708    case k64BitAlign:
1709      SetEncodingValue(0x1);
1710      break;
1711    case k128BitAlign:
1712      SetEncodingValue(0x2);
1713      break;
1714    case k256BitAlign:
1715      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1716      break;
1717    case kNoAlignment:
1718      SetEncodingValue(0x0);
1719      break;
1720    default:
1721      break;
1722  }
1723}
1724
1725class Align_align_3 : public EncodingValue {
1726 public:
1727  explicit Align_align_3(Alignment align);
1728};
1729
1730Align_align_3::Align_align_3(Alignment align) {
1731  switch (align.GetType()) {
1732    case k64BitAlign:
1733      SetEncodingValue(0x1);
1734      break;
1735    case kNoAlignment:
1736      SetEncodingValue(0x0);
1737      break;
1738    default:
1739      break;
1740  }
1741}
1742
1743class Align_align_4 : public EncodingValue {
1744 public:
1745  explicit Align_align_4(Alignment align);
1746};
1747
1748Align_align_4::Align_align_4(Alignment align) {
1749  switch (align.GetType()) {
1750    case k64BitAlign:
1751      SetEncodingValue(0x1);
1752      break;
1753    case k128BitAlign:
1754      SetEncodingValue(0x2);
1755      break;
1756    case k256BitAlign:
1757      SetEncodingValue(0x3);
1758      break;
1759    case kNoAlignment:
1760      SetEncodingValue(0x0);
1761      break;
1762    default:
1763      break;
1764  }
1765}
1766
1767class Align_align_5 : public EncodingValue {
1768 public:
1769  Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1770};
1771
1772Align_align_5::Align_align_5(Alignment align,
1773                             const NeonRegisterList& nreglist) {
1774  switch (align.GetType()) {
1775    case k64BitAlign:
1776      SetEncodingValue(0x1);
1777      break;
1778    case k128BitAlign:
1779      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1780        SetEncodingValue(0x2);
1781      break;
1782    case k256BitAlign:
1783      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1784      break;
1785    case kNoAlignment:
1786      SetEncodingValue(0x0);
1787      break;
1788    default:
1789      break;
1790  }
1791}
1792
1793
1794void Assembler::adc(Condition cond,
1795                    EncodingSize size,
1796                    Register rd,
1797                    Register rn,
1798                    const Operand& operand) {
1799  VIXL_ASSERT(AllowAssembler());
1800  CheckIT(cond);
1801  if (operand.IsImmediate()) {
1802    uint32_t imm = operand.GetImmediate();
1803    if (IsUsingT32()) {
1804      ImmediateT32 immediate_t32(imm);
1805      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1806      if (!size.IsNarrow() && immediate_t32.IsValid()) {
1807        EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1808                   (immediate_t32.GetEncodingValue() & 0xff) |
1809                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1810                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1811        AdvanceIT();
1812        return;
1813      }
1814    } else {
1815      ImmediateA32 immediate_a32(imm);
1816      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1817      if (immediate_a32.IsValid() && cond.IsNotNever()) {
1818        EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1819                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1820                immediate_a32.GetEncodingValue());
1821        return;
1822      }
1823    }
1824  }
1825  if (operand.IsImmediateShiftedRegister()) {
1826    Register rm = operand.GetBaseRegister();
1827    if (operand.IsPlainRegister()) {
1828      if (IsUsingT32()) {
1829        // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1830        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1831            rm.IsLow()) {
1832          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1833          AdvanceIT();
1834          return;
1835        }
1836      }
1837    }
1838    Shift shift = operand.GetShift();
1839    uint32_t amount = operand.GetShiftAmount();
1840    if (IsUsingT32()) {
1841      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1842      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
1843        uint32_t amount_ = amount % 32;
1844        EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1845                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1846                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1847        AdvanceIT();
1848        return;
1849      }
1850    } else {
1851      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1852      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1853        uint32_t amount_ = amount % 32;
1854        EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1855                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1856                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1857        return;
1858      }
1859    }
1860  }
1861  if (operand.IsRegisterShiftedRegister()) {
1862    Register rm = operand.GetBaseRegister();
1863    Shift shift = operand.GetShift();
1864    if (IsUsingA32()) {
1865      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1866      if (cond.IsNotNever()) {
1867        EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
1868                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1869                (shift.GetType() << 5) |
1870                (operand.GetShiftRegister().GetCode() << 8));
1871        return;
1872      }
1873    }
1874  }
1875  Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
1876}
1877
1878void Assembler::adcs(Condition cond,
1879                     EncodingSize size,
1880                     Register rd,
1881                     Register rn,
1882                     const Operand& operand) {
1883  VIXL_ASSERT(AllowAssembler());
1884  CheckIT(cond);
1885  if (operand.IsImmediate()) {
1886    uint32_t imm = operand.GetImmediate();
1887    if (IsUsingT32()) {
1888      ImmediateT32 immediate_t32(imm);
1889      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1890      if (!size.IsNarrow() && immediate_t32.IsValid()) {
1891        EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1892                   (immediate_t32.GetEncodingValue() & 0xff) |
1893                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1894                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1895        AdvanceIT();
1896        return;
1897      }
1898    } else {
1899      ImmediateA32 immediate_a32(imm);
1900      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1901      if (immediate_a32.IsValid() && cond.IsNotNever()) {
1902        EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
1903                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1904                immediate_a32.GetEncodingValue());
1905        return;
1906      }
1907    }
1908  }
1909  if (operand.IsImmediateShiftedRegister()) {
1910    Register rm = operand.GetBaseRegister();
1911    if (operand.IsPlainRegister()) {
1912      if (IsUsingT32()) {
1913        // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1914        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1915            rm.IsLow()) {
1916          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1917          AdvanceIT();
1918          return;
1919        }
1920      }
1921    }
1922    Shift shift = operand.GetShift();
1923    uint32_t amount = operand.GetShiftAmount();
1924    if (IsUsingT32()) {
1925      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1926      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
1927        uint32_t amount_ = amount % 32;
1928        EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1929                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1930                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1931        AdvanceIT();
1932        return;
1933      }
1934    } else {
1935      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1936      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1937        uint32_t amount_ = amount % 32;
1938        EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
1939                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1940                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1941        return;
1942      }
1943    }
1944  }
1945  if (operand.IsRegisterShiftedRegister()) {
1946    Register rm = operand.GetBaseRegister();
1947    Shift shift = operand.GetShift();
1948    if (IsUsingA32()) {
1949      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1950      if (cond.IsNotNever()) {
1951        EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
1952                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1953                (shift.GetType() << 5) |
1954                (operand.GetShiftRegister().GetCode() << 8));
1955        return;
1956      }
1957    }
1958  }
1959  Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
1960}
1961
1962void Assembler::add(Condition cond,
1963                    EncodingSize size,
1964                    Register rd,
1965                    Register rn,
1966                    const Operand& operand) {
1967  VIXL_ASSERT(AllowAssembler());
1968  CheckIT(cond);
1969  if (operand.IsImmediate()) {
1970    uint32_t imm = operand.GetImmediate();
1971    if (IsUsingT32()) {
1972      ImmediateT32 immediate_t32(imm);
1973      // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
1974      if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
1975          ((imm % 4) == 0)) {
1976        uint32_t imm_ = imm >> 2;
1977        EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
1978        AdvanceIT();
1979        return;
1980      }
1981      // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
1982      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
1983          (imm <= 7)) {
1984        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
1985        AdvanceIT();
1986        return;
1987      }
1988      // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
1989      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1990          (imm <= 255)) {
1991        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
1992        AdvanceIT();
1993        return;
1994      }
1995      // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
1996      if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
1997          ((imm % 4) == 0)) {
1998        uint32_t imm_ = imm >> 2;
1999        EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2000        AdvanceIT();
2001        return;
2002      }
2003      // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2004      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2005          ((imm % 4) == 0)) {
2006        uint32_t imm_ = imm >> 2;
2007        EmitT32_16(0xb000 | imm_);
2008        AdvanceIT();
2009        return;
2010      }
2011      // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2012      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) {
2013        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2014                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2015        AdvanceIT();
2016        return;
2017      }
2018      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2019      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp)) {
2020        EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2021                   (immediate_t32.GetEncodingValue() & 0xff) |
2022                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2023                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2024        AdvanceIT();
2025        return;
2026      }
2027      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2028      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
2029        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2030                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2031        AdvanceIT();
2032        return;
2033      }
2034      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2035      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid()) {
2036        EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2037                   (immediate_t32.GetEncodingValue() & 0xff) |
2038                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2039                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2040        AdvanceIT();
2041        return;
2042      }
2043      // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2044      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095)) {
2045        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2046                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2047        AdvanceIT();
2048        return;
2049      }
2050    } else {
2051      ImmediateA32 immediate_a32(imm);
2052      // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2053      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2054        EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2055                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2056        return;
2057      }
2058      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2059      if (immediate_a32.IsValid() && cond.IsNotNever() &&
2060          ((rn.GetCode() & 0xd) != 0xd)) {
2061        EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2062                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2063                immediate_a32.GetEncodingValue());
2064        return;
2065      }
2066      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2067      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2068        EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2069                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2070        return;
2071      }
2072    }
2073  }
2074  if (operand.IsImmediateShiftedRegister()) {
2075    Register rm = operand.GetBaseRegister();
2076    if (operand.IsPlainRegister()) {
2077      if (IsUsingT32()) {
2078        // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2079        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2080            rm.IsLow()) {
2081          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2082                     (rm.GetCode() << 6));
2083          AdvanceIT();
2084          return;
2085        }
2086        // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
2087        if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp)) {
2088          EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2089                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2090          AdvanceIT();
2091          return;
2092        }
2093        // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
2094        if (!size.IsWide() && rd.Is(rm) && rn.Is(sp)) {
2095          EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2096                     ((rd.GetCode() & 0x8) << 4));
2097          AdvanceIT();
2098          return;
2099        }
2100        // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2101        if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2102          EmitT32_16(0x4485 | (rm.GetCode() << 3));
2103          AdvanceIT();
2104          return;
2105        }
2106      }
2107    }
2108    Shift shift = operand.GetShift();
2109    uint32_t amount = operand.GetShiftAmount();
2110    if (IsUsingT32()) {
2111      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2112      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp)) {
2113        uint32_t amount_ = amount % 32;
2114        EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2115                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2116                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2117        AdvanceIT();
2118        return;
2119      }
2120      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2121      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount)) {
2122        uint32_t amount_ = amount % 32;
2123        EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2124                   (operand.GetTypeEncodingValue() << 4) |
2125                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2126        AdvanceIT();
2127        return;
2128      }
2129    } else {
2130      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2131      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2132        uint32_t amount_ = amount % 32;
2133        EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2134                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2135                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2136        return;
2137      }
2138      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2139      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2140        uint32_t amount_ = amount % 32;
2141        EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2142                (rd.GetCode() << 12) | rm.GetCode() |
2143                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2144        return;
2145      }
2146    }
2147  }
2148  if (operand.IsRegisterShiftedRegister()) {
2149    Register rm = operand.GetBaseRegister();
2150    Shift shift = operand.GetShift();
2151    if (IsUsingA32()) {
2152      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2153      if (cond.IsNotNever()) {
2154        EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2155                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2156                (shift.GetType() << 5) |
2157                (operand.GetShiftRegister().GetCode() << 8));
2158        return;
2159      }
2160    }
2161  }
2162  Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2163}
2164
2165void Assembler::add(Condition cond, Register rd, const Operand& operand) {
2166  VIXL_ASSERT(AllowAssembler());
2167  CheckIT(cond);
2168  if (operand.IsImmediate()) {
2169    uint32_t imm = operand.GetImmediate();
2170    if (IsUsingT32()) {
2171      // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2172      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2173        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2174        AdvanceIT();
2175        return;
2176      }
2177    }
2178  }
2179  if (operand.IsPlainRegister()) {
2180    Register rm = operand.GetBaseRegister();
2181    if (IsUsingT32()) {
2182      // ADD<c>{<q>} <Rdn>, <Rm> ; T2
2183      if (InITBlock() && !rm.Is(sp)) {
2184        EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2185                   (rm.GetCode() << 3));
2186        AdvanceIT();
2187        return;
2188      }
2189    }
2190  }
2191  Delegate(kAdd, &Assembler::add, cond, rd, operand);
2192}
2193
2194void Assembler::adds(Condition cond,
2195                     EncodingSize size,
2196                     Register rd,
2197                     Register rn,
2198                     const Operand& operand) {
2199  VIXL_ASSERT(AllowAssembler());
2200  CheckIT(cond);
2201  if (operand.IsImmediate()) {
2202    uint32_t imm = operand.GetImmediate();
2203    if (IsUsingT32()) {
2204      ImmediateT32 immediate_t32(imm);
2205      // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2206      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2207          (imm <= 7)) {
2208        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2209        AdvanceIT();
2210        return;
2211      }
2212      // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2213      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2214          (imm <= 255)) {
2215        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2216        AdvanceIT();
2217        return;
2218      }
2219      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2220      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2221          !rd.Is(pc)) {
2222        EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2223                   (immediate_t32.GetEncodingValue() & 0xff) |
2224                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2225                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2226        AdvanceIT();
2227        return;
2228      }
2229      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2230      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2231          !rd.Is(pc)) {
2232        EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2233                   (immediate_t32.GetEncodingValue() & 0xff) |
2234                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2235                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2236        AdvanceIT();
2237        return;
2238      }
2239    } else {
2240      ImmediateA32 immediate_a32(imm);
2241      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2242      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2243        EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2244                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2245                immediate_a32.GetEncodingValue());
2246        return;
2247      }
2248      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2249      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2250        EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2251                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2252        return;
2253      }
2254    }
2255  }
2256  if (operand.IsImmediateShiftedRegister()) {
2257    Register rm = operand.GetBaseRegister();
2258    if (operand.IsPlainRegister()) {
2259      if (IsUsingT32()) {
2260        // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2261        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2262            rm.IsLow()) {
2263          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2264                     (rm.GetCode() << 6));
2265          AdvanceIT();
2266          return;
2267        }
2268      }
2269    }
2270    Shift shift = operand.GetShift();
2271    uint32_t amount = operand.GetShiftAmount();
2272    if (IsUsingT32()) {
2273      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2274      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2275          !rd.Is(pc)) {
2276        uint32_t amount_ = amount % 32;
2277        EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2278                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2279                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2280        AdvanceIT();
2281        return;
2282      }
2283      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2284      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2285          !rd.Is(pc)) {
2286        uint32_t amount_ = amount % 32;
2287        EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2288                   (operand.GetTypeEncodingValue() << 4) |
2289                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2290        AdvanceIT();
2291        return;
2292      }
2293    } else {
2294      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2295      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2296        uint32_t amount_ = amount % 32;
2297        EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2298                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2299                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2300        return;
2301      }
2302      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2303      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2304        uint32_t amount_ = amount % 32;
2305        EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2306                (rd.GetCode() << 12) | rm.GetCode() |
2307                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2308        return;
2309      }
2310    }
2311  }
2312  if (operand.IsRegisterShiftedRegister()) {
2313    Register rm = operand.GetBaseRegister();
2314    Shift shift = operand.GetShift();
2315    if (IsUsingA32()) {
2316      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2317      if (cond.IsNotNever()) {
2318        EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2319                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2320                (shift.GetType() << 5) |
2321                (operand.GetShiftRegister().GetCode() << 8));
2322        return;
2323      }
2324    }
2325  }
2326  Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2327}
2328
2329void Assembler::adds(Register rd, const Operand& operand) {
2330  VIXL_ASSERT(AllowAssembler());
2331  CheckIT(al);
2332  if (operand.IsImmediate()) {
2333    uint32_t imm = operand.GetImmediate();
2334    if (IsUsingT32()) {
2335      // ADDS{<q>} <Rdn>, #<imm8> ; T2
2336      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2337        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2338        AdvanceIT();
2339        return;
2340      }
2341    }
2342  }
2343  Delegate(kAdds, &Assembler::adds, rd, operand);
2344}
2345
2346void Assembler::addw(Condition cond,
2347                     Register rd,
2348                     Register rn,
2349                     const Operand& operand) {
2350  VIXL_ASSERT(AllowAssembler());
2351  CheckIT(cond);
2352  if (operand.IsImmediate()) {
2353    uint32_t imm = operand.GetImmediate();
2354    if (IsUsingT32()) {
2355      // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2356      if (rn.Is(pc) && (imm <= 4095)) {
2357        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2358                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2359        AdvanceIT();
2360        return;
2361      }
2362      // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2363      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
2364        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2365                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2366        AdvanceIT();
2367        return;
2368      }
2369      // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2370      if (rn.Is(sp) && (imm <= 4095)) {
2371        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2372                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2373        AdvanceIT();
2374        return;
2375      }
2376    }
2377  }
2378  Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2379}
2380
2381void Assembler::adr(Condition cond,
2382                    EncodingSize size,
2383                    Register rd,
2384                    Label* label) {
2385  VIXL_ASSERT(AllowAssembler());
2386  CheckIT(cond);
2387  Label::Offset offset =
2388      label->IsBound()
2389          ? label->GetLocation() -
2390                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2391          : 0;
2392  if (IsUsingT32()) {
2393    int32_t neg_offset = -offset;
2394    // ADR{<c>}{<q>} <Rd>, <label> ; T1
2395    if (!size.IsWide() && rd.IsLow() &&
2396        ((label->IsBound() && (offset >= 0) && (offset <= 1020) &&
2397          ((offset & 0x3) == 0)) ||
2398         (!label->IsBound() && size.IsNarrow()))) {
2399      static class EmitOp : public Label::LabelEmitOperator {
2400       public:
2401        EmitOp() : Label::LabelEmitOperator(0, 1020) {}
2402        uint32_t Encode(uint32_t instr,
2403                        Label::Offset pc,
2404                        const Label* label) const {
2405          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2406          VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2407                      ((offset & 0x3) == 0));
2408          const int32_t target = offset >> 2;
2409          return instr | (target & 0xff);
2410        }
2411      } immop;
2412      EmitT32_16(Link(0xa000 | (rd.GetCode() << 8), label, immop));
2413      AdvanceIT();
2414      return;
2415    }
2416    // ADR{<c>}{<q>} <Rd>, <label> ; T2
2417    if (!size.IsNarrow() && label->IsBound() && (neg_offset > 0) &&
2418        (neg_offset <= 4095)) {
2419      EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2420                 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2421      AdvanceIT();
2422      return;
2423    }
2424    // ADR{<c>}{<q>} <Rd>, <label> ; T3
2425    if (!size.IsNarrow() &&
2426        (!label->IsBound() || ((offset >= 0) && (offset <= 4095)))) {
2427      static class EmitOp : public Label::LabelEmitOperator {
2428       public:
2429        EmitOp() : Label::LabelEmitOperator(0, 4095) {}
2430        uint32_t Encode(uint32_t instr,
2431                        Label::Offset pc,
2432                        const Label* label) const {
2433          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2434          int32_t target;
2435          if ((offset >= 0) && (offset <= 4095) && !label->IsMinusZero()) {
2436            target = offset;
2437          } else {
2438            target = -offset;
2439            VIXL_ASSERT((target >= 0) && (target <= 4095));
2440            // Emit the T2 encoding.
2441            instr |= 0x00a00000;
2442          }
2443          return instr | (target & 0xff) | ((target & 0x700) << 4) |
2444                 ((target & 0x800) << 15);
2445        }
2446      } immop;
2447      EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8), label, immop));
2448      AdvanceIT();
2449      return;
2450    }
2451  } else {
2452    ImmediateA32 positive_immediate_a32(offset);
2453    ImmediateA32 negative_immediate_a32(-offset);
2454    // ADR{<c>}{<q>} <Rd>, <label> ; A1
2455    if ((!label->IsBound() || positive_immediate_a32.IsValid()) &&
2456        cond.IsNotNever()) {
2457      static class EmitOp : public Label::LabelEmitOperator {
2458       public:
2459        EmitOp() : Label::LabelEmitOperator(0, 255) {}
2460        uint32_t Encode(uint32_t instr,
2461                        Label::Offset pc,
2462                        const Label* label) const {
2463          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2464          int32_t target;
2465          ImmediateA32 positive_immediate_a32(offset);
2466          if (positive_immediate_a32.IsValid()) {
2467            target = positive_immediate_a32.GetEncodingValue();
2468          } else {
2469            ImmediateA32 negative_immediate_a32(-offset);
2470            VIXL_ASSERT(negative_immediate_a32.IsValid());
2471            // Emit the A2 encoding.
2472            target = negative_immediate_a32.GetEncodingValue();
2473            instr = (instr & ~0x00f00000) | 0x00400000;
2474          }
2475          return instr | (target & 0xfff);
2476        }
2477      } immop;
2478      EmitA32(
2479          Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
2480               label,
2481               immop));
2482      return;
2483    }
2484    // ADR{<c>}{<q>} <Rd>, <label> ; A2
2485    if (label->IsBound() && negative_immediate_a32.IsValid() &&
2486        cond.IsNotNever()) {
2487      EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2488              negative_immediate_a32.GetEncodingValue());
2489      return;
2490    }
2491  }
2492  Delegate(kAdr, &Assembler::adr, cond, size, rd, label);
2493}
2494
2495void Assembler::and_(Condition cond,
2496                     EncodingSize size,
2497                     Register rd,
2498                     Register rn,
2499                     const Operand& operand) {
2500  VIXL_ASSERT(AllowAssembler());
2501  CheckIT(cond);
2502  if (operand.IsImmediate()) {
2503    uint32_t imm = operand.GetImmediate();
2504    if (IsUsingT32()) {
2505      ImmediateT32 immediate_t32(imm);
2506      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2507      if (!size.IsNarrow() && immediate_t32.IsValid()) {
2508        EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2509                   (immediate_t32.GetEncodingValue() & 0xff) |
2510                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2511                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2512        AdvanceIT();
2513        return;
2514      }
2515    } else {
2516      ImmediateA32 immediate_a32(imm);
2517      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2518      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2519        EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2520                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2521                immediate_a32.GetEncodingValue());
2522        return;
2523      }
2524    }
2525  }
2526  if (operand.IsImmediateShiftedRegister()) {
2527    Register rm = operand.GetBaseRegister();
2528    if (operand.IsPlainRegister()) {
2529      if (IsUsingT32()) {
2530        // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2531        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2532            rm.IsLow()) {
2533          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2534          AdvanceIT();
2535          return;
2536        }
2537      }
2538    }
2539    Shift shift = operand.GetShift();
2540    uint32_t amount = operand.GetShiftAmount();
2541    if (IsUsingT32()) {
2542      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2543      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
2544        uint32_t amount_ = amount % 32;
2545        EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2546                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2547                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2548        AdvanceIT();
2549        return;
2550      }
2551    } else {
2552      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2553      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2554        uint32_t amount_ = amount % 32;
2555        EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2556                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2557                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2558        return;
2559      }
2560    }
2561  }
2562  if (operand.IsRegisterShiftedRegister()) {
2563    Register rm = operand.GetBaseRegister();
2564    Shift shift = operand.GetShift();
2565    if (IsUsingA32()) {
2566      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2567      if (cond.IsNotNever()) {
2568        EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2569                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2570                (shift.GetType() << 5) |
2571                (operand.GetShiftRegister().GetCode() << 8));
2572        return;
2573      }
2574    }
2575  }
2576  Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2577}
2578
2579void Assembler::ands(Condition cond,
2580                     EncodingSize size,
2581                     Register rd,
2582                     Register rn,
2583                     const Operand& operand) {
2584  VIXL_ASSERT(AllowAssembler());
2585  CheckIT(cond);
2586  if (operand.IsImmediate()) {
2587    uint32_t imm = operand.GetImmediate();
2588    if (IsUsingT32()) {
2589      ImmediateT32 immediate_t32(imm);
2590      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2591      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc)) {
2592        EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2593                   (immediate_t32.GetEncodingValue() & 0xff) |
2594                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2595                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2596        AdvanceIT();
2597        return;
2598      }
2599    } else {
2600      ImmediateA32 immediate_a32(imm);
2601      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2602      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2603        EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2604                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2605                immediate_a32.GetEncodingValue());
2606        return;
2607      }
2608    }
2609  }
2610  if (operand.IsImmediateShiftedRegister()) {
2611    Register rm = operand.GetBaseRegister();
2612    if (operand.IsPlainRegister()) {
2613      if (IsUsingT32()) {
2614        // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2615        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2616            rm.IsLow()) {
2617          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2618          AdvanceIT();
2619          return;
2620        }
2621      }
2622    }
2623    Shift shift = operand.GetShift();
2624    uint32_t amount = operand.GetShiftAmount();
2625    if (IsUsingT32()) {
2626      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2627      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc)) {
2628        uint32_t amount_ = amount % 32;
2629        EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2630                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2631                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2632        AdvanceIT();
2633        return;
2634      }
2635    } else {
2636      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2637      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2638        uint32_t amount_ = amount % 32;
2639        EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2640                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2641                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2642        return;
2643      }
2644    }
2645  }
2646  if (operand.IsRegisterShiftedRegister()) {
2647    Register rm = operand.GetBaseRegister();
2648    Shift shift = operand.GetShift();
2649    if (IsUsingA32()) {
2650      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2651      if (cond.IsNotNever()) {
2652        EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2653                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2654                (shift.GetType() << 5) |
2655                (operand.GetShiftRegister().GetCode() << 8));
2656        return;
2657      }
2658    }
2659  }
2660  Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2661}
2662
2663void Assembler::asr(Condition cond,
2664                    EncodingSize size,
2665                    Register rd,
2666                    Register rm,
2667                    const Operand& operand) {
2668  VIXL_ASSERT(AllowAssembler());
2669  CheckIT(cond);
2670  if (operand.IsImmediate()) {
2671    uint32_t imm = operand.GetImmediate();
2672    if (IsUsingT32()) {
2673      // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2674      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2675          (imm >= 1) && (imm <= 32)) {
2676        uint32_t amount_ = imm % 32;
2677        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2678                   (amount_ << 6));
2679        AdvanceIT();
2680        return;
2681      }
2682      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2683      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
2684        uint32_t amount_ = imm % 32;
2685        EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2686                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2687        AdvanceIT();
2688        return;
2689      }
2690    } else {
2691      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2692      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2693        uint32_t amount_ = imm % 32;
2694        EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2695                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2696        return;
2697      }
2698    }
2699  }
2700  if (operand.IsPlainRegister()) {
2701    Register rs = operand.GetBaseRegister();
2702    if (IsUsingT32()) {
2703      // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2704      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2705          rs.IsLow()) {
2706        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2707        AdvanceIT();
2708        return;
2709      }
2710      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2711      if (!size.IsNarrow()) {
2712        EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2713                   rs.GetCode());
2714        AdvanceIT();
2715        return;
2716      }
2717    } else {
2718      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2719      if (cond.IsNotNever()) {
2720        EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2721                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2722        return;
2723      }
2724    }
2725  }
2726  Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2727}
2728
2729void Assembler::asrs(Condition cond,
2730                     EncodingSize size,
2731                     Register rd,
2732                     Register rm,
2733                     const Operand& operand) {
2734  VIXL_ASSERT(AllowAssembler());
2735  CheckIT(cond);
2736  if (operand.IsImmediate()) {
2737    uint32_t imm = operand.GetImmediate();
2738    if (IsUsingT32()) {
2739      // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2740      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2741          (imm >= 1) && (imm <= 32)) {
2742        uint32_t amount_ = imm % 32;
2743        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2744                   (amount_ << 6));
2745        AdvanceIT();
2746        return;
2747      }
2748      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2749      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
2750        uint32_t amount_ = imm % 32;
2751        EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2752                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2753        AdvanceIT();
2754        return;
2755      }
2756    } else {
2757      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2758      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2759        uint32_t amount_ = imm % 32;
2760        EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2761                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2762        return;
2763      }
2764    }
2765  }
2766  if (operand.IsPlainRegister()) {
2767    Register rs = operand.GetBaseRegister();
2768    if (IsUsingT32()) {
2769      // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2770      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2771          rs.IsLow()) {
2772        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2773        AdvanceIT();
2774        return;
2775      }
2776      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2777      if (!size.IsNarrow()) {
2778        EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2779                   rs.GetCode());
2780        AdvanceIT();
2781        return;
2782      }
2783    } else {
2784      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2785      if (cond.IsNotNever()) {
2786        EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
2787                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2788        return;
2789      }
2790    }
2791  }
2792  Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
2793}
2794
2795void Assembler::b(Condition cond, EncodingSize size, Label* label) {
2796  VIXL_ASSERT(AllowAssembler());
2797  Label::Offset offset =
2798      label->IsBound()
2799          ? label->GetLocation() -
2800                (GetCursorOffset() + GetArchitectureStatePCOffset())
2801          : 0;
2802  if (IsUsingT32()) {
2803    // B<c>{<q>} <label> ; T1
2804    if (OutsideITBlock() && !size.IsWide() &&
2805        ((label->IsBound() && (offset >= -256) && (offset <= 254) &&
2806          ((offset & 0x1) == 0)) ||
2807         (!label->IsBound() && size.IsNarrow())) &&
2808        !cond.Is(al) && cond.IsNotNever()) {
2809      static class EmitOp : public Label::LabelEmitOperator {
2810       public:
2811        EmitOp() : Label::LabelEmitOperator(-256, 254) {}
2812        uint32_t Encode(uint32_t instr,
2813                        Label::Offset pc,
2814                        const Label* label) const {
2815          Label::Offset offset = label->GetLocation() - pc;
2816          VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
2817                      ((offset & 0x1) == 0));
2818          const int32_t target = offset >> 1;
2819          return instr | (target & 0xff);
2820        }
2821      } immop;
2822      EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8), label, immop));
2823      AdvanceIT();
2824      return;
2825    }
2826    // B{<c>}{<q>} <label> ; T2
2827    if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
2828        ((label->IsBound() && (offset >= -2048) && (offset <= 2046) &&
2829          ((offset & 0x1) == 0)) ||
2830         (!label->IsBound() && size.IsNarrow()))) {
2831      CheckIT(cond);
2832      static class EmitOp : public Label::LabelEmitOperator {
2833       public:
2834        EmitOp() : Label::LabelEmitOperator(-2048, 2046) {}
2835        uint32_t Encode(uint32_t instr,
2836                        Label::Offset pc,
2837                        const Label* label) const {
2838          Label::Offset offset = label->GetLocation() - pc;
2839          VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
2840                      ((offset & 0x1) == 0));
2841          const int32_t target = offset >> 1;
2842          return instr | (target & 0x7ff);
2843        }
2844      } immop;
2845      EmitT32_16(Link(0xe000, label, immop));
2846      AdvanceIT();
2847      return;
2848    }
2849    // B<c>{<q>} <label> ; T3
2850    if (OutsideITBlock() && !size.IsNarrow() &&
2851        ((label->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
2852          ((offset & 0x1) == 0)) ||
2853         !label->IsBound()) &&
2854        !cond.Is(al) && cond.IsNotNever()) {
2855      static class EmitOp : public Label::LabelEmitOperator {
2856       public:
2857        EmitOp() : Label::LabelEmitOperator(-1048576, 1048574) {}
2858        uint32_t Encode(uint32_t instr,
2859                        Label::Offset pc,
2860                        const Label* label) const {
2861          Label::Offset offset = label->GetLocation() - pc;
2862          VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
2863                      ((offset & 0x1) == 0));
2864          const int32_t target = offset >> 1;
2865          return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
2866                 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
2867                 ((target & 0x80000) << 7);
2868        }
2869      } immop;
2870      EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22), label, immop));
2871      AdvanceIT();
2872      return;
2873    }
2874    // B{<c>}{<q>} <label> ; T4
2875    if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
2876        ((label->IsBound() && (offset >= -16777216) && (offset <= 16777214) &&
2877          ((offset & 0x1) == 0)) ||
2878         !label->IsBound())) {
2879      CheckIT(cond);
2880      static class EmitOp : public Label::LabelEmitOperator {
2881       public:
2882        EmitOp() : Label::LabelEmitOperator(-16777216, 16777214) {}
2883        uint32_t Encode(uint32_t instr,
2884                        Label::Offset pc,
2885                        const Label* label) const {
2886          Label::Offset offset = label->GetLocation() - pc;
2887          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
2888                      ((offset & 0x1) == 0));
2889          int32_t target = offset >> 1;
2890          uint32_t S = target & (1 << 23);
2891          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
2892          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
2893                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
2894                 ((target & 0x800000) << 3);
2895        }
2896      } immop;
2897      EmitT32_32(Link(0xf0009000U, label, immop));
2898      AdvanceIT();
2899      return;
2900    }
2901  } else {
2902    // B{<c>}{<q>} <label> ; A1
2903    if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554428) &&
2904          ((offset & 0x3) == 0)) ||
2905         !label->IsBound()) &&
2906        cond.IsNotNever()) {
2907      static class EmitOp : public Label::LabelEmitOperator {
2908       public:
2909        EmitOp() : Label::LabelEmitOperator(-33554432, 33554428) {}
2910        uint32_t Encode(uint32_t instr,
2911                        Label::Offset pc,
2912                        const Label* label) const {
2913          Label::Offset offset = label->GetLocation() - pc;
2914          VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
2915                      ((offset & 0x3) == 0));
2916          const int32_t target = offset >> 2;
2917          return instr | (target & 0xffffff);
2918        }
2919      } immop;
2920      EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28), label, immop));
2921      return;
2922    }
2923  }
2924  Delegate(kB, &Assembler::b, cond, size, label);
2925}
2926
2927void Assembler::bfc(Condition cond,
2928                    Register rd,
2929                    uint32_t lsb,
2930                    const Operand& operand) {
2931  VIXL_ASSERT(AllowAssembler());
2932  CheckIT(cond);
2933  if (operand.IsImmediate()) {
2934    uint32_t width = operand.GetImmediate();
2935    if (IsUsingT32()) {
2936      // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
2937      if ((lsb <= 31) &&
2938          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2939        uint32_t msb = lsb + width - 1;
2940        EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
2941                   ((lsb & 0x1c) << 10) | msb);
2942        AdvanceIT();
2943        return;
2944      }
2945    } else {
2946      // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
2947      if ((lsb <= 31) && cond.IsNotNever() &&
2948          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2949        uint32_t msb = lsb + width - 1;
2950        EmitA32(0x07c0001fU | (cond.GetCondition() << 28) |
2951                (rd.GetCode() << 12) | (lsb << 7) | (msb << 16));
2952        return;
2953      }
2954    }
2955  }
2956  Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, operand);
2957}
2958
2959void Assembler::bfi(Condition cond,
2960                    Register rd,
2961                    Register rn,
2962                    uint32_t lsb,
2963                    const Operand& operand) {
2964  VIXL_ASSERT(AllowAssembler());
2965  CheckIT(cond);
2966  if (operand.IsImmediate()) {
2967    uint32_t width = operand.GetImmediate();
2968    if (IsUsingT32()) {
2969      // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
2970      if ((lsb <= 31) && !rn.Is(pc) &&
2971          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2972        uint32_t msb = lsb + width - 1;
2973        EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2974                   ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
2975        AdvanceIT();
2976        return;
2977      }
2978    } else {
2979      // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
2980      if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
2981          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2982        uint32_t msb = lsb + width - 1;
2983        EmitA32(0x07c00010U | (cond.GetCondition() << 28) |
2984                (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) | (msb << 16));
2985        return;
2986      }
2987    }
2988  }
2989  Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, operand);
2990}
2991
2992void Assembler::bic(Condition cond,
2993                    EncodingSize size,
2994                    Register rd,
2995                    Register rn,
2996                    const Operand& operand) {
2997  VIXL_ASSERT(AllowAssembler());
2998  CheckIT(cond);
2999  if (operand.IsImmediate()) {
3000    uint32_t imm = operand.GetImmediate();
3001    if (IsUsingT32()) {
3002      ImmediateT32 immediate_t32(imm);
3003      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3004      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3005        EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3006                   (immediate_t32.GetEncodingValue() & 0xff) |
3007                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3008                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3009        AdvanceIT();
3010        return;
3011      }
3012    } else {
3013      ImmediateA32 immediate_a32(imm);
3014      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3015      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3016        EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3017                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3018                immediate_a32.GetEncodingValue());
3019        return;
3020      }
3021    }
3022  }
3023  if (operand.IsImmediateShiftedRegister()) {
3024    Register rm = operand.GetBaseRegister();
3025    if (operand.IsPlainRegister()) {
3026      if (IsUsingT32()) {
3027        // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3028        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3029            rm.IsLow()) {
3030          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3031          AdvanceIT();
3032          return;
3033        }
3034      }
3035    }
3036    Shift shift = operand.GetShift();
3037    uint32_t amount = operand.GetShiftAmount();
3038    if (IsUsingT32()) {
3039      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3040      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3041        uint32_t amount_ = amount % 32;
3042        EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3043                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3044                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3045        AdvanceIT();
3046        return;
3047      }
3048    } else {
3049      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3050      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3051        uint32_t amount_ = amount % 32;
3052        EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3053                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3054                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3055        return;
3056      }
3057    }
3058  }
3059  if (operand.IsRegisterShiftedRegister()) {
3060    Register rm = operand.GetBaseRegister();
3061    Shift shift = operand.GetShift();
3062    if (IsUsingA32()) {
3063      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3064      if (cond.IsNotNever()) {
3065        EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3066                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3067                (shift.GetType() << 5) |
3068                (operand.GetShiftRegister().GetCode() << 8));
3069        return;
3070      }
3071    }
3072  }
3073  Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3074}
3075
3076void Assembler::bics(Condition cond,
3077                     EncodingSize size,
3078                     Register rd,
3079                     Register rn,
3080                     const Operand& operand) {
3081  VIXL_ASSERT(AllowAssembler());
3082  CheckIT(cond);
3083  if (operand.IsImmediate()) {
3084    uint32_t imm = operand.GetImmediate();
3085    if (IsUsingT32()) {
3086      ImmediateT32 immediate_t32(imm);
3087      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3088      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3089        EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3090                   (immediate_t32.GetEncodingValue() & 0xff) |
3091                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3092                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3093        AdvanceIT();
3094        return;
3095      }
3096    } else {
3097      ImmediateA32 immediate_a32(imm);
3098      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3099      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3100        EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3101                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3102                immediate_a32.GetEncodingValue());
3103        return;
3104      }
3105    }
3106  }
3107  if (operand.IsImmediateShiftedRegister()) {
3108    Register rm = operand.GetBaseRegister();
3109    if (operand.IsPlainRegister()) {
3110      if (IsUsingT32()) {
3111        // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3112        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3113            rm.IsLow()) {
3114          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3115          AdvanceIT();
3116          return;
3117        }
3118      }
3119    }
3120    Shift shift = operand.GetShift();
3121    uint32_t amount = operand.GetShiftAmount();
3122    if (IsUsingT32()) {
3123      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3124      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3125        uint32_t amount_ = amount % 32;
3126        EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3127                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3128                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3129        AdvanceIT();
3130        return;
3131      }
3132    } else {
3133      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3134      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3135        uint32_t amount_ = amount % 32;
3136        EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3137                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3138                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3139        return;
3140      }
3141    }
3142  }
3143  if (operand.IsRegisterShiftedRegister()) {
3144    Register rm = operand.GetBaseRegister();
3145    Shift shift = operand.GetShift();
3146    if (IsUsingA32()) {
3147      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3148      if (cond.IsNotNever()) {
3149        EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3150                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3151                (shift.GetType() << 5) |
3152                (operand.GetShiftRegister().GetCode() << 8));
3153        return;
3154      }
3155    }
3156  }
3157  Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3158}
3159
3160void Assembler::bkpt(Condition cond, uint32_t imm) {
3161  VIXL_ASSERT(AllowAssembler());
3162  CheckIT(cond);
3163  if (IsUsingT32()) {
3164    // BKPT{<q>} {#}<imm> ; T1
3165    if ((imm <= 255)) {
3166      EmitT32_16(0xbe00 | imm);
3167      AdvanceIT();
3168      return;
3169    }
3170  } else {
3171    // BKPT{<q>} {#}<imm> ; A1
3172    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3173      EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3174              ((imm & 0xfff0) << 4));
3175      return;
3176    }
3177  }
3178  Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3179}
3180
3181void Assembler::bl(Condition cond, Label* label) {
3182  VIXL_ASSERT(AllowAssembler());
3183  CheckIT(cond);
3184  Label::Offset offset =
3185      label->IsBound()
3186          ? label->GetLocation() -
3187                (GetCursorOffset() + GetArchitectureStatePCOffset())
3188          : 0;
3189  if (IsUsingT32()) {
3190    // BL{<c>}{<q>} <label> ; T1
3191    if (((label->IsBound() && (offset >= -16777216) && (offset <= 16777214) &&
3192          ((offset & 0x1) == 0)) ||
3193         !label->IsBound())) {
3194      static class EmitOp : public Label::LabelEmitOperator {
3195       public:
3196        EmitOp() : Label::LabelEmitOperator(-16777216, 16777214) {}
3197        uint32_t Encode(uint32_t instr,
3198                        Label::Offset pc,
3199                        const Label* label) const {
3200          Label::Offset offset = label->GetLocation() - pc;
3201          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3202                      ((offset & 0x1) == 0));
3203          int32_t target = offset >> 1;
3204          uint32_t S = target & (1 << 23);
3205          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3206          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3207                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3208                 ((target & 0x800000) << 3);
3209        }
3210      } immop;
3211      EmitT32_32(Link(0xf000d000U, label, immop));
3212      AdvanceIT();
3213      return;
3214    }
3215  } else {
3216    // BL{<c>}{<q>} <label> ; A1
3217    if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554428) &&
3218          ((offset & 0x3) == 0)) ||
3219         !label->IsBound()) &&
3220        cond.IsNotNever()) {
3221      static class EmitOp : public Label::LabelEmitOperator {
3222       public:
3223        EmitOp() : Label::LabelEmitOperator(-33554432, 33554428) {}
3224        uint32_t Encode(uint32_t instr,
3225                        Label::Offset pc,
3226                        const Label* label) const {
3227          Label::Offset offset = label->GetLocation() - pc;
3228          VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3229                      ((offset & 0x3) == 0));
3230          const int32_t target = offset >> 2;
3231          return instr | (target & 0xffffff);
3232        }
3233      } immop;
3234      EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28), label, immop));
3235      return;
3236    }
3237  }
3238  Delegate(kBl, &Assembler::bl, cond, label);
3239}
3240
3241void Assembler::blx(Condition cond, Label* label) {
3242  VIXL_ASSERT(AllowAssembler());
3243  CheckIT(cond);
3244  Label::Offset offset =
3245      label->IsBound()
3246          ? label->GetLocation() -
3247                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3248          : 0;
3249  if (IsUsingT32()) {
3250    // BLX{<c>}{<q>} <label> ; T2
3251    if (((label->IsBound() && (offset >= -16777216) && (offset <= 16777212) &&
3252          ((offset & 0x3) == 0)) ||
3253         !label->IsBound())) {
3254      static class EmitOp : public Label::LabelEmitOperator {
3255       public:
3256        EmitOp() : Label::LabelEmitOperator(-16777216, 16777212) {}
3257        uint32_t Encode(uint32_t instr,
3258                        Label::Offset pc,
3259                        const Label* label) const {
3260          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
3261          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3262                      ((offset & 0x3) == 0));
3263          int32_t target = offset >> 2;
3264          uint32_t S = target & (1 << 22);
3265          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3266          return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3267                 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3268                 ((target & 0x400000) << 4);
3269        }
3270      } immop;
3271      EmitT32_32(Link(0xf000c000U, label, immop));
3272      AdvanceIT();
3273      return;
3274    }
3275  } else {
3276    // BLX{<c>}{<q>} <label> ; A2
3277    if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554430) &&
3278          ((offset & 0x1) == 0)) ||
3279         !label->IsBound())) {
3280      if (cond.Is(al) || AllowStronglyDiscouraged()) {
3281        static class EmitOp : public Label::LabelEmitOperator {
3282         public:
3283          EmitOp() : Label::LabelEmitOperator(-33554432, 33554430) {}
3284          uint32_t Encode(uint32_t instr,
3285                          Label::Offset pc,
3286                          const Label* label) const {
3287            Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
3288            VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3289                        ((offset & 0x1) == 0));
3290            const int32_t target = offset >> 1;
3291            return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3292          }
3293        } immop;
3294        EmitA32(Link(0xfa000000U, label, immop));
3295        return;
3296      }
3297    }
3298  }
3299  Delegate(kBlx, &Assembler::blx, cond, label);
3300}
3301
3302void Assembler::blx(Condition cond, Register rm) {
3303  VIXL_ASSERT(AllowAssembler());
3304  CheckIT(cond);
3305  if (IsUsingT32()) {
3306    // BLX{<c>}{<q>} <Rm> ; T1
3307    EmitT32_16(0x4780 | (rm.GetCode() << 3));
3308    AdvanceIT();
3309    return;
3310  } else {
3311    // BLX{<c>}{<q>} <Rm> ; A1
3312    if (cond.IsNotNever()) {
3313      EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3314      return;
3315    }
3316  }
3317  Delegate(kBlx, &Assembler::blx, cond, rm);
3318}
3319
3320void Assembler::bx(Condition cond, Register rm) {
3321  VIXL_ASSERT(AllowAssembler());
3322  CheckIT(cond);
3323  if (IsUsingT32()) {
3324    // BX{<c>}{<q>} <Rm> ; T1
3325    EmitT32_16(0x4700 | (rm.GetCode() << 3));
3326    AdvanceIT();
3327    return;
3328  } else {
3329    // BX{<c>}{<q>} <Rm> ; A1
3330    if (cond.IsNotNever()) {
3331      EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3332      return;
3333    }
3334  }
3335  Delegate(kBx, &Assembler::bx, cond, rm);
3336}
3337
3338void Assembler::bxj(Condition cond, Register rm) {
3339  VIXL_ASSERT(AllowAssembler());
3340  CheckIT(cond);
3341  if (IsUsingT32()) {
3342    // BXJ{<c>}{<q>} <Rm> ; T1
3343    EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3344    AdvanceIT();
3345    return;
3346  } else {
3347    // BXJ{<c>}{<q>} <Rm> ; A1
3348    if (cond.IsNotNever()) {
3349      EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3350      return;
3351    }
3352  }
3353  Delegate(kBxj, &Assembler::bxj, cond, rm);
3354}
3355
3356void Assembler::cbnz(Register rn, Label* label) {
3357  VIXL_ASSERT(AllowAssembler());
3358  CheckIT(al);
3359  Label::Offset offset =
3360      label->IsBound()
3361          ? label->GetLocation() -
3362                (GetCursorOffset() + GetArchitectureStatePCOffset())
3363          : 0;
3364  if (IsUsingT32()) {
3365    // CBNZ{<q>} <Rn>, <label> ; T1
3366    if (rn.IsLow() && ((label->IsBound() && (offset >= 0) && (offset <= 126) &&
3367                        ((offset & 0x1) == 0)) ||
3368                       !label->IsBound())) {
3369      static class EmitOp : public Label::LabelEmitOperator {
3370       public:
3371        EmitOp() : Label::LabelEmitOperator(0, 126) {}
3372        uint32_t Encode(uint32_t instr,
3373                        Label::Offset pc,
3374                        const Label* label) const {
3375          Label::Offset offset = label->GetLocation() - pc;
3376          VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3377                      ((offset & 0x1) == 0));
3378          const int32_t target = offset >> 1;
3379          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3380        }
3381      } immop;
3382      EmitT32_16(Link(0xb900 | rn.GetCode(), label, immop));
3383      AdvanceIT();
3384      return;
3385    }
3386  }
3387  Delegate(kCbnz, &Assembler::cbnz, rn, label);
3388}
3389
3390void Assembler::cbz(Register rn, Label* label) {
3391  VIXL_ASSERT(AllowAssembler());
3392  CheckIT(al);
3393  Label::Offset offset =
3394      label->IsBound()
3395          ? label->GetLocation() -
3396                (GetCursorOffset() + GetArchitectureStatePCOffset())
3397          : 0;
3398  if (IsUsingT32()) {
3399    // CBZ{<q>} <Rn>, <label> ; T1
3400    if (rn.IsLow() && ((label->IsBound() && (offset >= 0) && (offset <= 126) &&
3401                        ((offset & 0x1) == 0)) ||
3402                       !label->IsBound())) {
3403      static class EmitOp : public Label::LabelEmitOperator {
3404       public:
3405        EmitOp() : Label::LabelEmitOperator(0, 126) {}
3406        uint32_t Encode(uint32_t instr,
3407                        Label::Offset pc,
3408                        const Label* label) const {
3409          Label::Offset offset = label->GetLocation() - pc;
3410          VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3411                      ((offset & 0x1) == 0));
3412          const int32_t target = offset >> 1;
3413          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3414        }
3415      } immop;
3416      EmitT32_16(Link(0xb100 | rn.GetCode(), label, immop));
3417      AdvanceIT();
3418      return;
3419    }
3420  }
3421  Delegate(kCbz, &Assembler::cbz, rn, label);
3422}
3423
3424void Assembler::clrex(Condition cond) {
3425  VIXL_ASSERT(AllowAssembler());
3426  CheckIT(cond);
3427  if (IsUsingT32()) {
3428    // CLREX{<c>}{<q>} ; T1
3429    EmitT32_32(0xf3bf8f2fU);
3430    AdvanceIT();
3431    return;
3432  } else {
3433    // CLREX{<c>}{<q>} ; A1
3434    if (cond.Is(al)) {
3435      EmitA32(0xf57ff01fU);
3436      return;
3437    }
3438  }
3439  Delegate(kClrex, &Assembler::clrex, cond);
3440}
3441
3442void Assembler::clz(Condition cond, Register rd, Register rm) {
3443  VIXL_ASSERT(AllowAssembler());
3444  CheckIT(cond);
3445  if (IsUsingT32()) {
3446    // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
3447    EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3448               (rm.GetCode() << 16));
3449    AdvanceIT();
3450    return;
3451  } else {
3452    // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
3453    if (cond.IsNotNever()) {
3454      EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3455              rm.GetCode());
3456      return;
3457    }
3458  }
3459  Delegate(kClz, &Assembler::clz, cond, rd, rm);
3460}
3461
3462void Assembler::cmn(Condition cond,
3463                    EncodingSize size,
3464                    Register rn,
3465                    const Operand& operand) {
3466  VIXL_ASSERT(AllowAssembler());
3467  CheckIT(cond);
3468  if (operand.IsImmediate()) {
3469    uint32_t imm = operand.GetImmediate();
3470    if (IsUsingT32()) {
3471      ImmediateT32 immediate_t32(imm);
3472      // CMN{<c>}{<q>} <Rn>, #<const> ; T1
3473      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3474        EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3475                   (immediate_t32.GetEncodingValue() & 0xff) |
3476                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3477                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3478        AdvanceIT();
3479        return;
3480      }
3481    } else {
3482      ImmediateA32 immediate_a32(imm);
3483      // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3484      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3485        EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3486                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3487        return;
3488      }
3489    }
3490  }
3491  if (operand.IsImmediateShiftedRegister()) {
3492    Register rm = operand.GetBaseRegister();
3493    if (operand.IsPlainRegister()) {
3494      if (IsUsingT32()) {
3495        // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3496        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3497          EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3498          AdvanceIT();
3499          return;
3500        }
3501      }
3502    }
3503    Shift shift = operand.GetShift();
3504    uint32_t amount = operand.GetShiftAmount();
3505    if (IsUsingT32()) {
3506      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
3507      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3508        uint32_t amount_ = amount % 32;
3509        EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3510                   (operand.GetTypeEncodingValue() << 4) |
3511                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3512        AdvanceIT();
3513        return;
3514      }
3515    } else {
3516      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3517      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3518        uint32_t amount_ = amount % 32;
3519        EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3520                (rn.GetCode() << 16) | rm.GetCode() |
3521                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3522        return;
3523      }
3524    }
3525  }
3526  if (operand.IsRegisterShiftedRegister()) {
3527    Register rm = operand.GetBaseRegister();
3528    Shift shift = operand.GetShift();
3529    if (IsUsingA32()) {
3530      // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3531      if (cond.IsNotNever()) {
3532        EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3533                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3534                (operand.GetShiftRegister().GetCode() << 8));
3535        return;
3536      }
3537    }
3538  }
3539  Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3540}
3541
3542void Assembler::cmp(Condition cond,
3543                    EncodingSize size,
3544                    Register rn,
3545                    const Operand& operand) {
3546  VIXL_ASSERT(AllowAssembler());
3547  CheckIT(cond);
3548  if (operand.IsImmediate()) {
3549    uint32_t imm = operand.GetImmediate();
3550    if (IsUsingT32()) {
3551      ImmediateT32 immediate_t32(imm);
3552      // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3553      if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3554        EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3555        AdvanceIT();
3556        return;
3557      }
3558      // CMP{<c>}{<q>} <Rn>, #<const> ; T2
3559      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3560        EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3561                   (immediate_t32.GetEncodingValue() & 0xff) |
3562                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3563                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3564        AdvanceIT();
3565        return;
3566      }
3567    } else {
3568      ImmediateA32 immediate_a32(imm);
3569      // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3570      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3571        EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3572                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3573        return;
3574      }
3575    }
3576  }
3577  if (operand.IsImmediateShiftedRegister()) {
3578    Register rm = operand.GetBaseRegister();
3579    if (operand.IsPlainRegister()) {
3580      if (IsUsingT32()) {
3581        // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3582        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3583          EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3584          AdvanceIT();
3585          return;
3586        }
3587        // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
3588        if (!size.IsWide()) {
3589          EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3590                     ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3591          AdvanceIT();
3592          return;
3593        }
3594      }
3595    }
3596    Shift shift = operand.GetShift();
3597    uint32_t amount = operand.GetShiftAmount();
3598    if (IsUsingT32()) {
3599      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
3600      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3601        uint32_t amount_ = amount % 32;
3602        EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3603                   (operand.GetTypeEncodingValue() << 4) |
3604                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3605        AdvanceIT();
3606        return;
3607      }
3608    } else {
3609      // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3610      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3611        uint32_t amount_ = amount % 32;
3612        EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3613                (rn.GetCode() << 16) | rm.GetCode() |
3614                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3615        return;
3616      }
3617    }
3618  }
3619  if (operand.IsRegisterShiftedRegister()) {
3620    Register rm = operand.GetBaseRegister();
3621    Shift shift = operand.GetShift();
3622    if (IsUsingA32()) {
3623      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3624      if (cond.IsNotNever()) {
3625        EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3626                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3627                (operand.GetShiftRegister().GetCode() << 8));
3628        return;
3629      }
3630    }
3631  }
3632  Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
3633}
3634
3635void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
3636  VIXL_ASSERT(AllowAssembler());
3637  CheckIT(cond);
3638  if (IsUsingT32()) {
3639    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
3640    EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3641               rm.GetCode());
3642    AdvanceIT();
3643    return;
3644  } else {
3645    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
3646    if ((cond.Is(al) || AllowUnpredictable())) {
3647      EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3648              (rn.GetCode() << 16) | rm.GetCode());
3649      return;
3650    }
3651  }
3652  Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
3653}
3654
3655void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
3656  VIXL_ASSERT(AllowAssembler());
3657  CheckIT(cond);
3658  if (IsUsingT32()) {
3659    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
3660    EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3661               rm.GetCode());
3662    AdvanceIT();
3663    return;
3664  } else {
3665    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
3666    if ((cond.Is(al) || AllowUnpredictable())) {
3667      EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3668              (rn.GetCode() << 16) | rm.GetCode());
3669      return;
3670    }
3671  }
3672  Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
3673}
3674
3675void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
3676  VIXL_ASSERT(AllowAssembler());
3677  CheckIT(cond);
3678  if (IsUsingT32()) {
3679    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
3680    EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3681               rm.GetCode());
3682    AdvanceIT();
3683    return;
3684  } else {
3685    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
3686    if ((cond.Is(al) || AllowUnpredictable())) {
3687      EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3688              (rn.GetCode() << 16) | rm.GetCode());
3689      return;
3690    }
3691  }
3692  Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
3693}
3694
3695void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
3696  VIXL_ASSERT(AllowAssembler());
3697  CheckIT(cond);
3698  if (IsUsingT32()) {
3699    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
3700    EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3701               rm.GetCode());
3702    AdvanceIT();
3703    return;
3704  } else {
3705    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
3706    if ((cond.Is(al) || AllowUnpredictable())) {
3707      EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3708              (rn.GetCode() << 16) | rm.GetCode());
3709      return;
3710    }
3711  }
3712  Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
3713}
3714
3715void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
3716  VIXL_ASSERT(AllowAssembler());
3717  CheckIT(cond);
3718  if (IsUsingT32()) {
3719    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
3720    EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3721               rm.GetCode());
3722    AdvanceIT();
3723    return;
3724  } else {
3725    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
3726    if ((cond.Is(al) || AllowUnpredictable())) {
3727      EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3728              (rn.GetCode() << 16) | rm.GetCode());
3729      return;
3730    }
3731  }
3732  Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
3733}
3734
3735void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
3736  VIXL_ASSERT(AllowAssembler());
3737  CheckIT(cond);
3738  if (IsUsingT32()) {
3739    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
3740    EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3741               rm.GetCode());
3742    AdvanceIT();
3743    return;
3744  } else {
3745    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
3746    if ((cond.Is(al) || AllowUnpredictable())) {
3747      EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3748              (rn.GetCode() << 16) | rm.GetCode());
3749      return;
3750    }
3751  }
3752  Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
3753}
3754
3755void Assembler::dmb(Condition cond, MemoryBarrier option) {
3756  VIXL_ASSERT(AllowAssembler());
3757  CheckIT(cond);
3758  if (IsUsingT32()) {
3759    // DMB{<c>}{<q>} {<option>} ; T1
3760    EmitT32_32(0xf3bf8f50U | option.GetType());
3761    AdvanceIT();
3762    return;
3763  } else {
3764    // DMB{<c>}{<q>} {<option>} ; A1
3765    if (cond.Is(al)) {
3766      EmitA32(0xf57ff050U | option.GetType());
3767      return;
3768    }
3769  }
3770  Delegate(kDmb, &Assembler::dmb, cond, option);
3771}
3772
3773void Assembler::dsb(Condition cond, MemoryBarrier option) {
3774  VIXL_ASSERT(AllowAssembler());
3775  CheckIT(cond);
3776  if (IsUsingT32()) {
3777    // DSB{<c>}{<q>} {<option>} ; T1
3778    EmitT32_32(0xf3bf8f40U | option.GetType());
3779    AdvanceIT();
3780    return;
3781  } else {
3782    // DSB{<c>}{<q>} {<option>} ; A1
3783    if (cond.Is(al)) {
3784      EmitA32(0xf57ff040U | option.GetType());
3785      return;
3786    }
3787  }
3788  Delegate(kDsb, &Assembler::dsb, cond, option);
3789}
3790
3791void Assembler::eor(Condition cond,
3792                    EncodingSize size,
3793                    Register rd,
3794                    Register rn,
3795                    const Operand& operand) {
3796  VIXL_ASSERT(AllowAssembler());
3797  CheckIT(cond);
3798  if (operand.IsImmediate()) {
3799    uint32_t imm = operand.GetImmediate();
3800    if (IsUsingT32()) {
3801      ImmediateT32 immediate_t32(imm);
3802      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3803      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3804        EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3805                   (immediate_t32.GetEncodingValue() & 0xff) |
3806                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3807                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3808        AdvanceIT();
3809        return;
3810      }
3811    } else {
3812      ImmediateA32 immediate_a32(imm);
3813      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3814      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3815        EmitA32(0x02200000U | (cond.GetCondition() << 28) |
3816                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3817                immediate_a32.GetEncodingValue());
3818        return;
3819      }
3820    }
3821  }
3822  if (operand.IsImmediateShiftedRegister()) {
3823    Register rm = operand.GetBaseRegister();
3824    if (operand.IsPlainRegister()) {
3825      if (IsUsingT32()) {
3826        // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3827        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3828            rm.IsLow()) {
3829          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
3830          AdvanceIT();
3831          return;
3832        }
3833      }
3834    }
3835    Shift shift = operand.GetShift();
3836    uint32_t amount = operand.GetShiftAmount();
3837    if (IsUsingT32()) {
3838      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3839      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3840        uint32_t amount_ = amount % 32;
3841        EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3842                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3843                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3844        AdvanceIT();
3845        return;
3846      }
3847    } else {
3848      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3849      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3850        uint32_t amount_ = amount % 32;
3851        EmitA32(0x00200000U | (cond.GetCondition() << 28) |
3852                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3853                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3854        return;
3855      }
3856    }
3857  }
3858  if (operand.IsRegisterShiftedRegister()) {
3859    Register rm = operand.GetBaseRegister();
3860    Shift shift = operand.GetShift();
3861    if (IsUsingA32()) {
3862      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3863      if (cond.IsNotNever()) {
3864        EmitA32(0x00200010U | (cond.GetCondition() << 28) |
3865                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3866                (shift.GetType() << 5) |
3867                (operand.GetShiftRegister().GetCode() << 8));
3868        return;
3869      }
3870    }
3871  }
3872  Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
3873}
3874
3875void Assembler::eors(Condition cond,
3876                     EncodingSize size,
3877                     Register rd,
3878                     Register rn,
3879                     const Operand& operand) {
3880  VIXL_ASSERT(AllowAssembler());
3881  CheckIT(cond);
3882  if (operand.IsImmediate()) {
3883    uint32_t imm = operand.GetImmediate();
3884    if (IsUsingT32()) {
3885      ImmediateT32 immediate_t32(imm);
3886      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3887      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc)) {
3888        EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3889                   (immediate_t32.GetEncodingValue() & 0xff) |
3890                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3891                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3892        AdvanceIT();
3893        return;
3894      }
3895    } else {
3896      ImmediateA32 immediate_a32(imm);
3897      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3898      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3899        EmitA32(0x02300000U | (cond.GetCondition() << 28) |
3900                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3901                immediate_a32.GetEncodingValue());
3902        return;
3903      }
3904    }
3905  }
3906  if (operand.IsImmediateShiftedRegister()) {
3907    Register rm = operand.GetBaseRegister();
3908    if (operand.IsPlainRegister()) {
3909      if (IsUsingT32()) {
3910        // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3911        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3912            rm.IsLow()) {
3913          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
3914          AdvanceIT();
3915          return;
3916        }
3917      }
3918    }
3919    Shift shift = operand.GetShift();
3920    uint32_t amount = operand.GetShiftAmount();
3921    if (IsUsingT32()) {
3922      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3923      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc)) {
3924        uint32_t amount_ = amount % 32;
3925        EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3926                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3927                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3928        AdvanceIT();
3929        return;
3930      }
3931    } else {
3932      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3933      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3934        uint32_t amount_ = amount % 32;
3935        EmitA32(0x00300000U | (cond.GetCondition() << 28) |
3936                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3937                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3938        return;
3939      }
3940    }
3941  }
3942  if (operand.IsRegisterShiftedRegister()) {
3943    Register rm = operand.GetBaseRegister();
3944    Shift shift = operand.GetShift();
3945    if (IsUsingA32()) {
3946      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3947      if (cond.IsNotNever()) {
3948        EmitA32(0x00300010U | (cond.GetCondition() << 28) |
3949                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3950                (shift.GetType() << 5) |
3951                (operand.GetShiftRegister().GetCode() << 8));
3952        return;
3953      }
3954    }
3955  }
3956  Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
3957}
3958
3959void Assembler::fldmdbx(Condition cond,
3960                        Register rn,
3961                        WriteBack write_back,
3962                        DRegisterList dreglist) {
3963  VIXL_ASSERT(AllowAssembler());
3964  CheckIT(cond);
3965  if (IsUsingT32()) {
3966    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
3967    if (write_back.DoesWriteBack() &&
3968        (((dreglist.GetLength() <= 16) &&
3969          (dreglist.GetLastDRegister().GetCode() < 16)) ||
3970         AllowUnpredictable())) {
3971      const DRegister& dreg = dreglist.GetFirstDRegister();
3972      unsigned len = dreglist.GetLength() * 2;
3973      EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
3974                 (len & 0xff));
3975      AdvanceIT();
3976      return;
3977    }
3978  } else {
3979    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
3980    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
3981        (((dreglist.GetLength() <= 16) &&
3982          (dreglist.GetLastDRegister().GetCode() < 16)) ||
3983         AllowUnpredictable())) {
3984      const DRegister& dreg = dreglist.GetFirstDRegister();
3985      unsigned len = dreglist.GetLength() * 2;
3986      EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
3987              dreg.Encode(22, 12) | (len & 0xff));
3988      return;
3989    }
3990  }
3991  Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
3992}
3993
3994void Assembler::fldmiax(Condition cond,
3995                        Register rn,
3996                        WriteBack write_back,
3997                        DRegisterList dreglist) {
3998  VIXL_ASSERT(AllowAssembler());
3999  CheckIT(cond);
4000  if (IsUsingT32()) {
4001    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4002    if ((((dreglist.GetLength() <= 16) &&
4003          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4004         AllowUnpredictable())) {
4005      const DRegister& dreg = dreglist.GetFirstDRegister();
4006      unsigned len = dreglist.GetLength() * 2;
4007      EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4008                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4009                 (len & 0xff));
4010      AdvanceIT();
4011      return;
4012    }
4013  } else {
4014    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4015    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4016                               (dreglist.GetLastDRegister().GetCode() < 16)) ||
4017                              AllowUnpredictable())) {
4018      const DRegister& dreg = dreglist.GetFirstDRegister();
4019      unsigned len = dreglist.GetLength() * 2;
4020      EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4021              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4022              (len & 0xff));
4023      return;
4024    }
4025  }
4026  Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4027}
4028
4029void Assembler::fstmdbx(Condition cond,
4030                        Register rn,
4031                        WriteBack write_back,
4032                        DRegisterList dreglist) {
4033  VIXL_ASSERT(AllowAssembler());
4034  CheckIT(cond);
4035  if (IsUsingT32()) {
4036    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4037    if (write_back.DoesWriteBack() &&
4038        (((dreglist.GetLength() <= 16) &&
4039          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4040         AllowUnpredictable())) {
4041      const DRegister& dreg = dreglist.GetFirstDRegister();
4042      unsigned len = dreglist.GetLength() * 2;
4043      EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4044                 (len & 0xff));
4045      AdvanceIT();
4046      return;
4047    }
4048  } else {
4049    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4050    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4051        (((dreglist.GetLength() <= 16) &&
4052          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4053         AllowUnpredictable())) {
4054      const DRegister& dreg = dreglist.GetFirstDRegister();
4055      unsigned len = dreglist.GetLength() * 2;
4056      EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4057              dreg.Encode(22, 12) | (len & 0xff));
4058      return;
4059    }
4060  }
4061  Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4062}
4063
4064void Assembler::fstmiax(Condition cond,
4065                        Register rn,
4066                        WriteBack write_back,
4067                        DRegisterList dreglist) {
4068  VIXL_ASSERT(AllowAssembler());
4069  CheckIT(cond);
4070  if (IsUsingT32()) {
4071    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4072    if ((((dreglist.GetLength() <= 16) &&
4073          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4074         AllowUnpredictable())) {
4075      const DRegister& dreg = dreglist.GetFirstDRegister();
4076      unsigned len = dreglist.GetLength() * 2;
4077      EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4078                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4079                 (len & 0xff));
4080      AdvanceIT();
4081      return;
4082    }
4083  } else {
4084    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4085    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4086                               (dreglist.GetLastDRegister().GetCode() < 16)) ||
4087                              AllowUnpredictable())) {
4088      const DRegister& dreg = dreglist.GetFirstDRegister();
4089      unsigned len = dreglist.GetLength() * 2;
4090      EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4091              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4092              (len & 0xff));
4093      return;
4094    }
4095  }
4096  Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4097}
4098
4099void Assembler::hlt(Condition cond, uint32_t imm) {
4100  VIXL_ASSERT(AllowAssembler());
4101  CheckIT(cond);
4102  if (IsUsingT32()) {
4103    // HLT{<q>} {#}<imm> ; T1
4104    if ((imm <= 63)) {
4105      EmitT32_16(0xba80 | imm);
4106      AdvanceIT();
4107      return;
4108    }
4109  } else {
4110    // HLT{<q>} {#}<imm> ; A1
4111    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4112      EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4113              ((imm & 0xfff0) << 4));
4114      return;
4115    }
4116  }
4117  Delegate(kHlt, &Assembler::hlt, cond, imm);
4118}
4119
4120void Assembler::hvc(Condition cond, uint32_t imm) {
4121  VIXL_ASSERT(AllowAssembler());
4122  CheckIT(cond);
4123  if (IsUsingT32()) {
4124    // HVC{<q>} {#}<imm16> ; T1
4125    if ((imm <= 65535)) {
4126      EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4127      AdvanceIT();
4128      return;
4129    }
4130  } else {
4131    // HVC{<q>} {#}<imm16> ; A1
4132    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4133      EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4134              ((imm & 0xfff0) << 4));
4135      return;
4136    }
4137  }
4138  Delegate(kHvc, &Assembler::hvc, cond, imm);
4139}
4140
4141void Assembler::isb(Condition cond, MemoryBarrier option) {
4142  VIXL_ASSERT(AllowAssembler());
4143  CheckIT(cond);
4144  if (IsUsingT32()) {
4145    // ISB{<c>}{<q>} {<option>} ; T1
4146    EmitT32_32(0xf3bf8f60U | option.GetType());
4147    AdvanceIT();
4148    return;
4149  } else {
4150    // ISB{<c>}{<q>} {<option>} ; A1
4151    if (cond.Is(al)) {
4152      EmitA32(0xf57ff060U | option.GetType());
4153      return;
4154    }
4155  }
4156  Delegate(kIsb, &Assembler::isb, cond, option);
4157}
4158
4159void Assembler::it(Condition cond, uint16_t mask) {
4160  VIXL_ASSERT(AllowAssembler());
4161  CheckNotIT();
4162  if (mask != 0) {
4163    if ((cond.GetCondition() & 0x1) != 0) {
4164      if ((mask & 0x1) != 0) {
4165        mask ^= 0xE;
4166      } else if ((mask & 0x2) != 0) {
4167        mask ^= 0xC;
4168      } else if ((mask & 0x4) != 0) {
4169        mask ^= 0x8;
4170      }
4171    }
4172    if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
4173    SetIT(cond, mask);
4174    return;
4175  }
4176  DelegateIt(cond, mask);
4177}
4178
4179void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
4180  VIXL_ASSERT(AllowAssembler());
4181  CheckIT(cond);
4182  if (operand.IsImmediateZero()) {
4183    Register rn = operand.GetBaseRegister();
4184    if (IsUsingT32()) {
4185      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
4186      if ((operand.GetAddrMode() == Offset) &&
4187          ((!rn.IsPC()) || AllowUnpredictable())) {
4188        EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4189        AdvanceIT();
4190        return;
4191      }
4192    } else {
4193      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
4194      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4195          ((!rn.IsPC()) || AllowUnpredictable())) {
4196        EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4197                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4198        return;
4199      }
4200    }
4201  }
4202  Delegate(kLda, &Assembler::lda, cond, rt, operand);
4203}
4204
4205void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
4206  VIXL_ASSERT(AllowAssembler());
4207  CheckIT(cond);
4208  if (operand.IsImmediateZero()) {
4209    Register rn = operand.GetBaseRegister();
4210    if (IsUsingT32()) {
4211      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4212      if ((operand.GetAddrMode() == Offset) &&
4213          ((!rn.IsPC()) || AllowUnpredictable())) {
4214        EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4215        AdvanceIT();
4216        return;
4217      }
4218    } else {
4219      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4220      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4221          ((!rn.IsPC()) || AllowUnpredictable())) {
4222        EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4223                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4224        return;
4225      }
4226    }
4227  }
4228  Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4229}
4230
4231void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
4232  VIXL_ASSERT(AllowAssembler());
4233  CheckIT(cond);
4234  if (operand.IsImmediateZero()) {
4235    Register rn = operand.GetBaseRegister();
4236    if (IsUsingT32()) {
4237      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
4238      if ((operand.GetAddrMode() == Offset) &&
4239          ((!rn.IsPC()) || AllowUnpredictable())) {
4240        EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4241        AdvanceIT();
4242        return;
4243      }
4244    } else {
4245      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
4246      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4247          ((!rn.IsPC()) || AllowUnpredictable())) {
4248        EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4249                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4250        return;
4251      }
4252    }
4253  }
4254  Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4255}
4256
4257void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
4258  VIXL_ASSERT(AllowAssembler());
4259  CheckIT(cond);
4260  if (operand.IsImmediateZero()) {
4261    Register rn = operand.GetBaseRegister();
4262    if (IsUsingT32()) {
4263      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4264      if ((operand.GetAddrMode() == Offset) &&
4265          ((!rn.IsPC()) || AllowUnpredictable())) {
4266        EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4267        AdvanceIT();
4268        return;
4269      }
4270    } else {
4271      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4272      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4273          ((!rn.IsPC()) || AllowUnpredictable())) {
4274        EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4275                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4276        return;
4277      }
4278    }
4279  }
4280  Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4281}
4282
4283void Assembler::ldaexd(Condition cond,
4284                       Register rt,
4285                       Register rt2,
4286                       const MemOperand& operand) {
4287  VIXL_ASSERT(AllowAssembler());
4288  CheckIT(cond);
4289  if (operand.IsImmediateZero()) {
4290    Register rn = operand.GetBaseRegister();
4291    if (IsUsingT32()) {
4292      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
4293      if ((operand.GetAddrMode() == Offset) &&
4294          ((!rn.IsPC()) || AllowUnpredictable())) {
4295        EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4296                   (rn.GetCode() << 16));
4297        AdvanceIT();
4298        return;
4299      }
4300    } else {
4301      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4302      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
4303          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4304          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
4305           AllowUnpredictable())) {
4306        EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4307                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4308        return;
4309      }
4310    }
4311  }
4312  Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4313}
4314
4315void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
4316  VIXL_ASSERT(AllowAssembler());
4317  CheckIT(cond);
4318  if (operand.IsImmediateZero()) {
4319    Register rn = operand.GetBaseRegister();
4320    if (IsUsingT32()) {
4321      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4322      if ((operand.GetAddrMode() == Offset) &&
4323          ((!rn.IsPC()) || AllowUnpredictable())) {
4324        EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4325        AdvanceIT();
4326        return;
4327      }
4328    } else {
4329      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4330      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4331          ((!rn.IsPC()) || AllowUnpredictable())) {
4332        EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4333                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4334        return;
4335      }
4336    }
4337  }
4338  Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4339}
4340
4341void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
4342  VIXL_ASSERT(AllowAssembler());
4343  CheckIT(cond);
4344  if (operand.IsImmediateZero()) {
4345    Register rn = operand.GetBaseRegister();
4346    if (IsUsingT32()) {
4347      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4348      if ((operand.GetAddrMode() == Offset) &&
4349          ((!rn.IsPC()) || AllowUnpredictable())) {
4350        EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4351        AdvanceIT();
4352        return;
4353      }
4354    } else {
4355      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4356      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4357          ((!rn.IsPC()) || AllowUnpredictable())) {
4358        EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4359                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4360        return;
4361      }
4362    }
4363  }
4364  Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4365}
4366
4367void Assembler::ldm(Condition cond,
4368                    EncodingSize size,
4369                    Register rn,
4370                    WriteBack write_back,
4371                    RegisterList registers) {
4372  VIXL_ASSERT(AllowAssembler());
4373  CheckIT(cond);
4374  if (IsUsingT32()) {
4375    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4376    if (!size.IsWide() && rn.IsLow() &&
4377        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4378         write_back.DoesWriteBack()) &&
4379        ((registers.GetList() & ~0xff) == 0)) {
4380      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4381                 GetRegisterListEncoding(registers, 0, 8));
4382      AdvanceIT();
4383      return;
4384    }
4385    // LDM{<c>}{<q>} SP!, <registers> ; T1
4386    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4387        ((registers.GetList() & ~0x80ff) == 0)) {
4388      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4389                 GetRegisterListEncoding(registers, 0, 8));
4390      AdvanceIT();
4391      return;
4392    }
4393    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
4394    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
4395      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4396                 (write_back.GetWriteBackUint32() << 21) |
4397                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4398                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4399                 GetRegisterListEncoding(registers, 0, 13));
4400      AdvanceIT();
4401      return;
4402    }
4403  } else {
4404    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
4405    if (cond.IsNotNever()) {
4406      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4407              (write_back.GetWriteBackUint32() << 21) |
4408              GetRegisterListEncoding(registers, 0, 16));
4409      return;
4410    }
4411  }
4412  Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4413}
4414
4415void Assembler::ldmda(Condition cond,
4416                      Register rn,
4417                      WriteBack write_back,
4418                      RegisterList registers) {
4419  VIXL_ASSERT(AllowAssembler());
4420  CheckIT(cond);
4421  if (IsUsingA32()) {
4422    // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4423    if (cond.IsNotNever()) {
4424      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4425              (write_back.GetWriteBackUint32() << 21) |
4426              GetRegisterListEncoding(registers, 0, 16));
4427      return;
4428    }
4429  }
4430  Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4431}
4432
4433void Assembler::ldmdb(Condition cond,
4434                      Register rn,
4435                      WriteBack write_back,
4436                      RegisterList registers) {
4437  VIXL_ASSERT(AllowAssembler());
4438  CheckIT(cond);
4439  if (IsUsingT32()) {
4440    // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
4441    if (((registers.GetList() & ~0xdfff) == 0)) {
4442      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4443                 (write_back.GetWriteBackUint32() << 21) |
4444                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4445                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4446                 GetRegisterListEncoding(registers, 0, 13));
4447      AdvanceIT();
4448      return;
4449    }
4450  } else {
4451    // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4452    if (cond.IsNotNever()) {
4453      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4454              (write_back.GetWriteBackUint32() << 21) |
4455              GetRegisterListEncoding(registers, 0, 16));
4456      return;
4457    }
4458  }
4459  Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4460}
4461
4462void Assembler::ldmea(Condition cond,
4463                      Register rn,
4464                      WriteBack write_back,
4465                      RegisterList registers) {
4466  VIXL_ASSERT(AllowAssembler());
4467  CheckIT(cond);
4468  if (IsUsingT32()) {
4469    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
4470    if (((registers.GetList() & ~0xdfff) == 0)) {
4471      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4472                 (write_back.GetWriteBackUint32() << 21) |
4473                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4474                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4475                 GetRegisterListEncoding(registers, 0, 13));
4476      AdvanceIT();
4477      return;
4478    }
4479  } else {
4480    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4481    if (cond.IsNotNever()) {
4482      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4483              (write_back.GetWriteBackUint32() << 21) |
4484              GetRegisterListEncoding(registers, 0, 16));
4485      return;
4486    }
4487  }
4488  Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4489}
4490
4491void Assembler::ldmed(Condition cond,
4492                      Register rn,
4493                      WriteBack write_back,
4494                      RegisterList registers) {
4495  VIXL_ASSERT(AllowAssembler());
4496  CheckIT(cond);
4497  if (IsUsingA32()) {
4498    // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
4499    if (cond.IsNotNever()) {
4500      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4501              (write_back.GetWriteBackUint32() << 21) |
4502              GetRegisterListEncoding(registers, 0, 16));
4503      return;
4504    }
4505  }
4506  Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4507}
4508
4509void Assembler::ldmfa(Condition cond,
4510                      Register rn,
4511                      WriteBack write_back,
4512                      RegisterList registers) {
4513  VIXL_ASSERT(AllowAssembler());
4514  CheckIT(cond);
4515  if (IsUsingA32()) {
4516    // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4517    if (cond.IsNotNever()) {
4518      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4519              (write_back.GetWriteBackUint32() << 21) |
4520              GetRegisterListEncoding(registers, 0, 16));
4521      return;
4522    }
4523  }
4524  Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4525}
4526
4527void Assembler::ldmfd(Condition cond,
4528                      EncodingSize size,
4529                      Register rn,
4530                      WriteBack write_back,
4531                      RegisterList registers) {
4532  VIXL_ASSERT(AllowAssembler());
4533  CheckIT(cond);
4534  if (IsUsingT32()) {
4535    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4536    if (!size.IsWide() && rn.IsLow() &&
4537        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4538         write_back.DoesWriteBack()) &&
4539        ((registers.GetList() & ~0xff) == 0)) {
4540      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4541                 GetRegisterListEncoding(registers, 0, 8));
4542      AdvanceIT();
4543      return;
4544    }
4545    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
4546    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
4547      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4548                 (write_back.GetWriteBackUint32() << 21) |
4549                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4550                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4551                 GetRegisterListEncoding(registers, 0, 13));
4552      AdvanceIT();
4553      return;
4554    }
4555  } else {
4556    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
4557    if (cond.IsNotNever()) {
4558      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4559              (write_back.GetWriteBackUint32() << 21) |
4560              GetRegisterListEncoding(registers, 0, 16));
4561      return;
4562    }
4563  }
4564  Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4565}
4566
4567void Assembler::ldmib(Condition cond,
4568                      Register rn,
4569                      WriteBack write_back,
4570                      RegisterList registers) {
4571  VIXL_ASSERT(AllowAssembler());
4572  CheckIT(cond);
4573  if (IsUsingA32()) {
4574    // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4575    if (cond.IsNotNever()) {
4576      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4577              (write_back.GetWriteBackUint32() << 21) |
4578              GetRegisterListEncoding(registers, 0, 16));
4579      return;
4580    }
4581  }
4582  Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4583}
4584
4585void Assembler::ldr(Condition cond,
4586                    EncodingSize size,
4587                    Register rt,
4588                    const MemOperand& operand) {
4589  VIXL_ASSERT(AllowAssembler());
4590  CheckIT(cond);
4591  if (operand.IsImmediate()) {
4592    Register rn = operand.GetBaseRegister();
4593    int32_t offset = operand.GetOffsetImmediate();
4594    if (IsUsingT32()) {
4595      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4596      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4597          (offset <= 124) && ((offset % 4) == 0) &&
4598          (operand.GetAddrMode() == Offset)) {
4599        int32_t offset_ = offset >> 2;
4600        EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
4601                   ((offset_ & 0x1f) << 6));
4602        AdvanceIT();
4603        return;
4604      }
4605      // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
4606      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
4607          ((offset % 4) == 0) && rn.Is(sp) &&
4608          (operand.GetAddrMode() == Offset)) {
4609        int32_t offset_ = offset >> 2;
4610        EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
4611        AdvanceIT();
4612        return;
4613      }
4614      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
4615      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
4616          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
4617        EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4618                   (offset & 0xfff));
4619        AdvanceIT();
4620        return;
4621      }
4622      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
4623      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
4624          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
4625        EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4626                   (-offset & 0xff));
4627        AdvanceIT();
4628        return;
4629      }
4630      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
4631      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4632          (operand.GetAddrMode() == PostIndex) &&
4633          ((rn.GetCode() & 0xf) != 0xf)) {
4634        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4635        uint32_t offset_ = abs(offset);
4636        EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4637                   offset_ | (sign << 9));
4638        AdvanceIT();
4639        return;
4640      }
4641      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
4642      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4643          (operand.GetAddrMode() == PreIndex) &&
4644          ((rn.GetCode() & 0xf) != 0xf)) {
4645        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4646        uint32_t offset_ = abs(offset);
4647        EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4648                   offset_ | (sign << 9));
4649        AdvanceIT();
4650        return;
4651      }
4652      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
4653      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
4654          rn.Is(pc) && (operand.GetAddrMode() == Offset)) {
4655        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4656        uint32_t offset_ = abs(offset);
4657        EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
4658        AdvanceIT();
4659        return;
4660      }
4661    } else {
4662      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
4663      if ((offset >= -4095) && (offset <= 4095) &&
4664          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4665          ((rn.GetCode() & 0xf) != 0xf)) {
4666        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4667        uint32_t offset_ = abs(offset);
4668        EmitA32(0x05100000U | (cond.GetCondition() << 28) |
4669                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4670                (sign << 23));
4671        return;
4672      }
4673      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
4674      if ((offset >= -4095) && (offset <= 4095) &&
4675          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
4676          ((rn.GetCode() & 0xf) != 0xf)) {
4677        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4678        uint32_t offset_ = abs(offset);
4679        EmitA32(0x04100000U | (cond.GetCondition() << 28) |
4680                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4681                (sign << 23));
4682        return;
4683      }
4684      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
4685      if ((offset >= -4095) && (offset <= 4095) &&
4686          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
4687          ((rn.GetCode() & 0xf) != 0xf)) {
4688        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4689        uint32_t offset_ = abs(offset);
4690        EmitA32(0x05300000U | (cond.GetCondition() << 28) |
4691                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4692                (sign << 23));
4693        return;
4694      }
4695      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
4696      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
4697          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
4698        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4699        uint32_t offset_ = abs(offset);
4700        EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
4701                (rt.GetCode() << 12) | offset_ | (sign << 23));
4702        return;
4703      }
4704    }
4705  }
4706  if (operand.IsPlainRegister()) {
4707    Register rn = operand.GetBaseRegister();
4708    Sign sign = operand.GetSign();
4709    Register rm = operand.GetOffsetRegister();
4710    if (IsUsingT32()) {
4711      // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
4712      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
4713          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
4714        EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
4715                   (rm.GetCode() << 6));
4716        AdvanceIT();
4717        return;
4718      }
4719    }
4720  }
4721  if (operand.IsShiftedRegister()) {
4722    Register rn = operand.GetBaseRegister();
4723    Sign sign = operand.GetSign();
4724    Register rm = operand.GetOffsetRegister();
4725    Shift shift = operand.GetShift();
4726    uint32_t amount = operand.GetShiftAmount();
4727    if (IsUsingT32()) {
4728      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
4729      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
4730          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
4731        EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4732                   rm.GetCode() | (amount << 4));
4733        AdvanceIT();
4734        return;
4735      }
4736    } else {
4737      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
4738      if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
4739          cond.IsNotNever()) {
4740        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4741        uint32_t shift_ = TypeEncodingValue(shift);
4742        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4743        EmitA32(0x07100000U | (cond.GetCondition() << 28) |
4744                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4745                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4746        return;
4747      }
4748      // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
4749      if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
4750          cond.IsNotNever()) {
4751        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4752        uint32_t shift_ = TypeEncodingValue(shift);
4753        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4754        EmitA32(0x06100000U | (cond.GetCondition() << 28) |
4755                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4756                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4757        return;
4758      }
4759      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
4760      if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
4761          cond.IsNotNever()) {
4762        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4763        uint32_t shift_ = TypeEncodingValue(shift);
4764        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4765        EmitA32(0x07300000U | (cond.GetCondition() << 28) |
4766                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4767                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4768        return;
4769      }
4770    }
4771  }
4772  Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
4773}
4774
4775void Assembler::ldr(Condition cond,
4776                    EncodingSize size,
4777                    Register rt,
4778                    Label* label) {
4779  VIXL_ASSERT(AllowAssembler());
4780  CheckIT(cond);
4781  Label::Offset offset =
4782      label->IsBound()
4783          ? label->GetLocation() -
4784                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
4785          : 0;
4786  if (IsUsingT32()) {
4787    // LDR{<c>}{<q>} <Rt>, <label> ; T1
4788    if (!size.IsWide() && rt.IsLow() &&
4789        ((label->IsBound() && (offset >= 0) && (offset <= 1020) &&
4790          ((offset & 0x3) == 0)) ||
4791         (!label->IsBound() && size.IsNarrow()))) {
4792      static class EmitOp : public Label::LabelEmitOperator {
4793       public:
4794        EmitOp() : Label::LabelEmitOperator(0, 1020) {}
4795        uint32_t Encode(uint32_t instr,
4796                        Label::Offset pc,
4797                        const Label* label) const {
4798          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4799          VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
4800                      ((offset & 0x3) == 0));
4801          const int32_t target = offset >> 2;
4802          return instr | (target & 0xff);
4803        }
4804      } immop;
4805      EmitT32_16(Link(0x4800 | (rt.GetCode() << 8), label, immop));
4806      AdvanceIT();
4807      return;
4808    }
4809    // LDR{<c>}{<q>} <Rt>, <label> ; T2
4810    if (!size.IsNarrow() &&
4811        ((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
4812         !label->IsBound())) {
4813      static class EmitOp : public Label::LabelEmitOperator {
4814       public:
4815        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
4816        uint32_t Encode(uint32_t instr,
4817                        Label::Offset pc,
4818                        const Label* label) const {
4819          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4820          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
4821          uint32_t U = (offset >= 0) && !label->IsMinusZero();
4822          int32_t target = abs(offset) | (U << 12);
4823          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
4824        }
4825      } immop;
4826      EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12), label, immop));
4827      AdvanceIT();
4828      return;
4829    }
4830  } else {
4831    // LDR{<c>}{<q>} <Rt>, <label> ; A1
4832    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
4833         !label->IsBound()) &&
4834        cond.IsNotNever()) {
4835      static class EmitOp : public Label::LabelEmitOperator {
4836       public:
4837        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
4838        uint32_t Encode(uint32_t instr,
4839                        Label::Offset pc,
4840                        const Label* label) const {
4841          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4842          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
4843          uint32_t U = (offset >= 0) && !label->IsMinusZero();
4844          int32_t target = abs(offset) | (U << 12);
4845          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
4846        }
4847      } immop;
4848      EmitA32(
4849          Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
4850               label,
4851               immop));
4852      return;
4853    }
4854  }
4855  Delegate(kLdr, &Assembler::ldr, cond, size, rt, label);
4856}
4857
4858void Assembler::ldrb(Condition cond,
4859                     EncodingSize size,
4860                     Register rt,
4861                     const MemOperand& operand) {
4862  VIXL_ASSERT(AllowAssembler());
4863  CheckIT(cond);
4864  if (operand.IsImmediate()) {
4865    Register rn = operand.GetBaseRegister();
4866    int32_t offset = operand.GetOffsetImmediate();
4867    if (IsUsingT32()) {
4868      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4869      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4870          (offset <= 31) && (operand.GetAddrMode() == Offset)) {
4871        EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
4872                   ((offset & 0x1f) << 6));
4873        AdvanceIT();
4874        return;
4875      }
4876      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
4877      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
4878          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
4879          !rt.Is(pc)) {
4880        EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4881                   (offset & 0xfff));
4882        AdvanceIT();
4883        return;
4884      }
4885      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
4886      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
4887          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
4888          !rt.Is(pc)) {
4889        EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4890                   (-offset & 0xff));
4891        AdvanceIT();
4892        return;
4893      }
4894      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
4895      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4896          (operand.GetAddrMode() == PostIndex) &&
4897          ((rn.GetCode() & 0xf) != 0xf)) {
4898        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4899        uint32_t offset_ = abs(offset);
4900        EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4901                   offset_ | (sign << 9));
4902        AdvanceIT();
4903        return;
4904      }
4905      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
4906      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4907          (operand.GetAddrMode() == PreIndex) &&
4908          ((rn.GetCode() & 0xf) != 0xf)) {
4909        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4910        uint32_t offset_ = abs(offset);
4911        EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4912                   offset_ | (sign << 9));
4913        AdvanceIT();
4914        return;
4915      }
4916      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
4917      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
4918          rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
4919        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4920        uint32_t offset_ = abs(offset);
4921        EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
4922        AdvanceIT();
4923        return;
4924      }
4925    } else {
4926      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
4927      if ((offset >= -4095) && (offset <= 4095) &&
4928          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4929          ((rn.GetCode() & 0xf) != 0xf)) {
4930        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4931        uint32_t offset_ = abs(offset);
4932        EmitA32(0x05500000U | (cond.GetCondition() << 28) |
4933                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4934                (sign << 23));
4935        return;
4936      }
4937      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
4938      if ((offset >= -4095) && (offset <= 4095) &&
4939          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
4940          ((rn.GetCode() & 0xf) != 0xf)) {
4941        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4942        uint32_t offset_ = abs(offset);
4943        EmitA32(0x04500000U | (cond.GetCondition() << 28) |
4944                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4945                (sign << 23));
4946        return;
4947      }
4948      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
4949      if ((offset >= -4095) && (offset <= 4095) &&
4950          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
4951          ((rn.GetCode() & 0xf) != 0xf)) {
4952        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4953        uint32_t offset_ = abs(offset);
4954        EmitA32(0x05700000U | (cond.GetCondition() << 28) |
4955                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4956                (sign << 23));
4957        return;
4958      }
4959      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
4960      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
4961          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
4962        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4963        uint32_t offset_ = abs(offset);
4964        EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
4965                (rt.GetCode() << 12) | offset_ | (sign << 23));
4966        return;
4967      }
4968    }
4969  }
4970  if (operand.IsPlainRegister()) {
4971    Register rn = operand.GetBaseRegister();
4972    Sign sign = operand.GetSign();
4973    Register rm = operand.GetOffsetRegister();
4974    if (IsUsingT32()) {
4975      // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
4976      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
4977          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
4978        EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
4979                   (rm.GetCode() << 6));
4980        AdvanceIT();
4981        return;
4982      }
4983    }
4984  }
4985  if (operand.IsShiftedRegister()) {
4986    Register rn = operand.GetBaseRegister();
4987    Sign sign = operand.GetSign();
4988    Register rm = operand.GetOffsetRegister();
4989    Shift shift = operand.GetShift();
4990    uint32_t amount = operand.GetShiftAmount();
4991    if (IsUsingT32()) {
4992      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
4993      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
4994          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
4995          !rt.Is(pc)) {
4996        EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4997                   rm.GetCode() | (amount << 4));
4998        AdvanceIT();
4999        return;
5000      }
5001    } else {
5002      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5003      if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
5004          cond.IsNotNever()) {
5005        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5006        uint32_t shift_ = TypeEncodingValue(shift);
5007        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5008        EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5009                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5010                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5011        return;
5012      }
5013      // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
5014      if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
5015          cond.IsNotNever()) {
5016        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5017        uint32_t shift_ = TypeEncodingValue(shift);
5018        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5019        EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5020                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5021                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5022        return;
5023      }
5024      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5025      if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
5026          cond.IsNotNever()) {
5027        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5028        uint32_t shift_ = TypeEncodingValue(shift);
5029        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5030        EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5031                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5032                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5033        return;
5034      }
5035    }
5036  }
5037  Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5038}
5039
5040void Assembler::ldrb(Condition cond, Register rt, Label* label) {
5041  VIXL_ASSERT(AllowAssembler());
5042  CheckIT(cond);
5043  Label::Offset offset =
5044      label->IsBound()
5045          ? label->GetLocation() -
5046                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5047          : 0;
5048  if (IsUsingT32()) {
5049    // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5050    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5051         !label->IsBound()) &&
5052        !rt.Is(pc)) {
5053      static class EmitOp : public Label::LabelEmitOperator {
5054       public:
5055        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5056        uint32_t Encode(uint32_t instr,
5057                        Label::Offset pc,
5058                        const Label* label) const {
5059          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5060          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5061          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5062          int32_t target = abs(offset) | (U << 12);
5063          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5064        }
5065      } immop;
5066      EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12), label, immop));
5067      AdvanceIT();
5068      return;
5069    }
5070  } else {
5071    // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5072    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5073         !label->IsBound()) &&
5074        cond.IsNotNever()) {
5075      static class EmitOp : public Label::LabelEmitOperator {
5076       public:
5077        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5078        uint32_t Encode(uint32_t instr,
5079                        Label::Offset pc,
5080                        const Label* label) const {
5081          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5082          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5083          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5084          int32_t target = abs(offset) | (U << 12);
5085          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5086        }
5087      } immop;
5088      EmitA32(
5089          Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5090               label,
5091               immop));
5092      return;
5093    }
5094  }
5095  Delegate(kLdrb, &Assembler::ldrb, cond, rt, label);
5096}
5097
5098void Assembler::ldrd(Condition cond,
5099                     Register rt,
5100                     Register rt2,
5101                     const MemOperand& operand) {
5102  VIXL_ASSERT(AllowAssembler());
5103  CheckIT(cond);
5104  if (operand.IsImmediate()) {
5105    Register rn = operand.GetBaseRegister();
5106    int32_t offset = operand.GetOffsetImmediate();
5107    if (IsUsingT32()) {
5108      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5109      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5110          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
5111        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5112        uint32_t offset_ = abs(offset) >> 2;
5113        EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5114                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5115        AdvanceIT();
5116        return;
5117      }
5118      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5119      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5120          (operand.GetAddrMode() == PostIndex) &&
5121          ((rn.GetCode() & 0xf) != 0xf)) {
5122        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5123        uint32_t offset_ = abs(offset) >> 2;
5124        EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5125                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5126        AdvanceIT();
5127        return;
5128      }
5129      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5130      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5131          (operand.GetAddrMode() == PreIndex) &&
5132          ((rn.GetCode() & 0xf) != 0xf)) {
5133        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5134        uint32_t offset_ = abs(offset) >> 2;
5135        EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5136                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5137        AdvanceIT();
5138        return;
5139      }
5140      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5141      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5142          (operand.GetAddrMode() == Offset)) {
5143        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5144        uint32_t offset_ = abs(offset);
5145        EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5146                   offset_ | (sign << 23));
5147        AdvanceIT();
5148        return;
5149      }
5150    } else {
5151      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5152      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5153          (offset >= -255) && (offset <= 255) &&
5154          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5155          ((rn.GetCode() & 0xf) != 0xf) &&
5156          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5157        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5158        uint32_t offset_ = abs(offset);
5159        EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5160                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5161                ((offset_ & 0xf0) << 4) | (sign << 23));
5162        return;
5163      }
5164      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5165      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5166          (offset >= -255) && (offset <= 255) &&
5167          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5168          ((rn.GetCode() & 0xf) != 0xf) &&
5169          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5170        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5171        uint32_t offset_ = abs(offset);
5172        EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5173                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5174                ((offset_ & 0xf0) << 4) | (sign << 23));
5175        return;
5176      }
5177      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5178      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5179          (offset >= -255) && (offset <= 255) &&
5180          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5181          ((rn.GetCode() & 0xf) != 0xf) &&
5182          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5183        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5184        uint32_t offset_ = abs(offset);
5185        EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5186                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5187                ((offset_ & 0xf0) << 4) | (sign << 23));
5188        return;
5189      }
5190      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5191      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5192          (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5193          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5194          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5195        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5196        uint32_t offset_ = abs(offset);
5197        EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5198                (rt.GetCode() << 12) | (offset_ & 0xf) |
5199                ((offset_ & 0xf0) << 4) | (sign << 23));
5200        return;
5201      }
5202    }
5203  }
5204  if (operand.IsPlainRegister()) {
5205    Register rn = operand.GetBaseRegister();
5206    Sign sign = operand.GetSign();
5207    Register rm = operand.GetOffsetRegister();
5208    if (IsUsingA32()) {
5209      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5210      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5211          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5212          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5213        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5214        EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5215                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5216                (sign_ << 23));
5217        return;
5218      }
5219      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5220      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5221          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5222          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5223        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5224        EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5225                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5226                (sign_ << 23));
5227        return;
5228      }
5229      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5230      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5231          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5232          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5233        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5234        EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5235                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5236                (sign_ << 23));
5237        return;
5238      }
5239    }
5240  }
5241  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5242}
5243
5244void Assembler::ldrd(Condition cond, Register rt, Register rt2, Label* label) {
5245  VIXL_ASSERT(AllowAssembler());
5246  CheckIT(cond);
5247  Label::Offset offset =
5248      label->IsBound()
5249          ? label->GetLocation() -
5250                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5251          : 0;
5252  if (IsUsingT32()) {
5253    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5254    if (((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
5255          ((offset & 0x3) == 0)) ||
5256         !label->IsBound())) {
5257      static class EmitOp : public Label::LabelEmitOperator {
5258       public:
5259        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
5260        uint32_t Encode(uint32_t instr,
5261                        Label::Offset pc,
5262                        const Label* label) const {
5263          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5264          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5265                      ((offset & 0x3) == 0));
5266          int32_t target = offset >> 2;
5267          uint32_t U = (target >= 0) && !label->IsMinusZero();
5268          target = abs(target) | (U << 8);
5269          return instr | (target & 0xff) | ((target & 0x100) << 15);
5270        }
5271      } immop;
5272      EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
5273                      label,
5274                      immop));
5275      AdvanceIT();
5276      return;
5277    }
5278  } else {
5279    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5280    if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5281        ((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5282         !label->IsBound()) &&
5283        cond.IsNotNever() &&
5284        ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5285      static class EmitOp : public Label::LabelEmitOperator {
5286       public:
5287        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
5288        uint32_t Encode(uint32_t instr,
5289                        Label::Offset pc,
5290                        const Label* label) const {
5291          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5292          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5293          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5294          int32_t target = abs(offset) | (U << 8);
5295          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5296                 ((target & 0x100) << 15);
5297        }
5298      } immop;
5299      EmitA32(
5300          Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5301               label,
5302               immop));
5303      return;
5304    }
5305  }
5306  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, label);
5307}
5308
5309void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
5310  VIXL_ASSERT(AllowAssembler());
5311  CheckIT(cond);
5312  if (operand.IsImmediate()) {
5313    Register rn = operand.GetBaseRegister();
5314    int32_t offset = operand.GetOffsetImmediate();
5315    if (IsUsingT32()) {
5316      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5317      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
5318          (operand.GetAddrMode() == Offset)) {
5319        int32_t offset_ = offset >> 2;
5320        EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5321                   (offset_ & 0xff));
5322        AdvanceIT();
5323        return;
5324      }
5325    } else {
5326      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
5327      if ((offset == 0) && (operand.GetAddrMode() == Offset) &&
5328          cond.IsNotNever()) {
5329        EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5330                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5331        return;
5332      }
5333    }
5334  }
5335  Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5336}
5337
5338void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
5339  VIXL_ASSERT(AllowAssembler());
5340  CheckIT(cond);
5341  if (operand.IsImmediateZero()) {
5342    Register rn = operand.GetBaseRegister();
5343    if (IsUsingT32()) {
5344      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
5345      if ((operand.GetAddrMode() == Offset) &&
5346          ((!rn.IsPC()) || AllowUnpredictable())) {
5347        EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5348        AdvanceIT();
5349        return;
5350      }
5351    } else {
5352      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
5353      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5354          ((!rn.IsPC()) || AllowUnpredictable())) {
5355        EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5356                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5357        return;
5358      }
5359    }
5360  }
5361  Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5362}
5363
5364void Assembler::ldrexd(Condition cond,
5365                       Register rt,
5366                       Register rt2,
5367                       const MemOperand& operand) {
5368  VIXL_ASSERT(AllowAssembler());
5369  CheckIT(cond);
5370  if (operand.IsImmediateZero()) {
5371    Register rn = operand.GetBaseRegister();
5372    if (IsUsingT32()) {
5373      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
5374      if ((operand.GetAddrMode() == Offset) &&
5375          ((!rn.IsPC()) || AllowUnpredictable())) {
5376        EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5377                   (rn.GetCode() << 16));
5378        AdvanceIT();
5379        return;
5380      }
5381    } else {
5382      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5383      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5384          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5385          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
5386           AllowUnpredictable())) {
5387        EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5388                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5389        return;
5390      }
5391    }
5392  }
5393  Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5394}
5395
5396void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
5397  VIXL_ASSERT(AllowAssembler());
5398  CheckIT(cond);
5399  if (operand.IsImmediateZero()) {
5400    Register rn = operand.GetBaseRegister();
5401    if (IsUsingT32()) {
5402      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
5403      if ((operand.GetAddrMode() == Offset) &&
5404          ((!rn.IsPC()) || AllowUnpredictable())) {
5405        EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5406        AdvanceIT();
5407        return;
5408      }
5409    } else {
5410      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
5411      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5412          ((!rn.IsPC()) || AllowUnpredictable())) {
5413        EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5414                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5415        return;
5416      }
5417    }
5418  }
5419  Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5420}
5421
5422void Assembler::ldrh(Condition cond,
5423                     EncodingSize size,
5424                     Register rt,
5425                     const MemOperand& operand) {
5426  VIXL_ASSERT(AllowAssembler());
5427  CheckIT(cond);
5428  if (operand.IsImmediate()) {
5429    Register rn = operand.GetBaseRegister();
5430    int32_t offset = operand.GetOffsetImmediate();
5431    if (IsUsingT32()) {
5432      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5433      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5434          (offset <= 62) && ((offset % 2) == 0) &&
5435          (operand.GetAddrMode() == Offset)) {
5436        int32_t offset_ = offset >> 1;
5437        EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5438                   ((offset_ & 0x1f) << 6));
5439        AdvanceIT();
5440        return;
5441      }
5442      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5443      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5444          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5445          !rt.Is(pc)) {
5446        EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5447                   (offset & 0xfff));
5448        AdvanceIT();
5449        return;
5450      }
5451      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5452      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5453          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5454          !rt.Is(pc)) {
5455        EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5456                   (-offset & 0xff));
5457        AdvanceIT();
5458        return;
5459      }
5460      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5461      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5462          (operand.GetAddrMode() == PostIndex) &&
5463          ((rn.GetCode() & 0xf) != 0xf)) {
5464        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5465        uint32_t offset_ = abs(offset);
5466        EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5467                   offset_ | (sign << 9));
5468        AdvanceIT();
5469        return;
5470      }
5471      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5472      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5473          (operand.GetAddrMode() == PreIndex) &&
5474          ((rn.GetCode() & 0xf) != 0xf)) {
5475        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5476        uint32_t offset_ = abs(offset);
5477        EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5478                   offset_ | (sign << 9));
5479        AdvanceIT();
5480        return;
5481      }
5482      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5483      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5484          rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
5485        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5486        uint32_t offset_ = abs(offset);
5487        EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5488        AdvanceIT();
5489        return;
5490      }
5491    } else {
5492      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5493      if ((offset >= -255) && (offset <= 255) &&
5494          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5495          ((rn.GetCode() & 0xf) != 0xf)) {
5496        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5497        uint32_t offset_ = abs(offset);
5498        EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
5499                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5500                ((offset_ & 0xf0) << 4) | (sign << 23));
5501        return;
5502      }
5503      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5504      if ((offset >= -255) && (offset <= 255) &&
5505          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5506          ((rn.GetCode() & 0xf) != 0xf)) {
5507        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5508        uint32_t offset_ = abs(offset);
5509        EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
5510                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5511                ((offset_ & 0xf0) << 4) | (sign << 23));
5512        return;
5513      }
5514      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5515      if ((offset >= -255) && (offset <= 255) &&
5516          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5517          ((rn.GetCode() & 0xf) != 0xf)) {
5518        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5519        uint32_t offset_ = abs(offset);
5520        EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
5521                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5522                ((offset_ & 0xf0) << 4) | (sign << 23));
5523        return;
5524      }
5525      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5526      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5527          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5528        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5529        uint32_t offset_ = abs(offset);
5530        EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
5531                (rt.GetCode() << 12) | (offset_ & 0xf) |
5532                ((offset_ & 0xf0) << 4) | (sign << 23));
5533        return;
5534      }
5535    }
5536  }
5537  if (operand.IsPlainRegister()) {
5538    Register rn = operand.GetBaseRegister();
5539    Sign sign = operand.GetSign();
5540    Register rm = operand.GetOffsetRegister();
5541    if (IsUsingT32()) {
5542      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5543      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5544          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
5545        EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
5546                   (rm.GetCode() << 6));
5547        AdvanceIT();
5548        return;
5549      }
5550    } else {
5551      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5552      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5553        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5554        EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
5555                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5556                (sign_ << 23));
5557        return;
5558      }
5559      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5560      if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
5561        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5562        EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
5563                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5564                (sign_ << 23));
5565        return;
5566      }
5567      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5568      if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
5569        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5570        EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
5571                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5572                (sign_ << 23));
5573        return;
5574      }
5575    }
5576  }
5577  if (operand.IsShiftedRegister()) {
5578    Register rn = operand.GetBaseRegister();
5579    Sign sign = operand.GetSign();
5580    Register rm = operand.GetOffsetRegister();
5581    Shift shift = operand.GetShift();
5582    uint32_t amount = operand.GetShiftAmount();
5583    if (IsUsingT32()) {
5584      // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5585      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5586          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5587          !rt.Is(pc)) {
5588        EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5589                   rm.GetCode() | (amount << 4));
5590        AdvanceIT();
5591        return;
5592      }
5593    }
5594  }
5595  Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
5596}
5597
5598void Assembler::ldrh(Condition cond, Register rt, Label* label) {
5599  VIXL_ASSERT(AllowAssembler());
5600  CheckIT(cond);
5601  Label::Offset offset =
5602      label->IsBound()
5603          ? label->GetLocation() -
5604                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5605          : 0;
5606  if (IsUsingT32()) {
5607    // LDRH{<c>}{<q>} <Rt>, <label> ; T1
5608    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5609         !label->IsBound()) &&
5610        !rt.Is(pc)) {
5611      static class EmitOp : public Label::LabelEmitOperator {
5612       public:
5613        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5614        uint32_t Encode(uint32_t instr,
5615                        Label::Offset pc,
5616                        const Label* label) const {
5617          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5618          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5619          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5620          int32_t target = abs(offset) | (U << 12);
5621          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5622        }
5623      } immop;
5624      EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12), label, immop));
5625      AdvanceIT();
5626      return;
5627    }
5628  } else {
5629    // LDRH{<c>}{<q>} <Rt>, <label> ; A1
5630    if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5631         !label->IsBound()) &&
5632        cond.IsNotNever()) {
5633      static class EmitOp : public Label::LabelEmitOperator {
5634       public:
5635        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
5636        uint32_t Encode(uint32_t instr,
5637                        Label::Offset pc,
5638                        const Label* label) const {
5639          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5640          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5641          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5642          int32_t target = abs(offset) | (U << 8);
5643          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5644                 ((target & 0x100) << 15);
5645        }
5646      } immop;
5647      EmitA32(
5648          Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5649               label,
5650               immop));
5651      return;
5652    }
5653  }
5654  Delegate(kLdrh, &Assembler::ldrh, cond, rt, label);
5655}
5656
5657void Assembler::ldrsb(Condition cond,
5658                      EncodingSize size,
5659                      Register rt,
5660                      const MemOperand& operand) {
5661  VIXL_ASSERT(AllowAssembler());
5662  CheckIT(cond);
5663  if (operand.IsImmediate()) {
5664    Register rn = operand.GetBaseRegister();
5665    int32_t offset = operand.GetOffsetImmediate();
5666    if (IsUsingT32()) {
5667      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5668      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5669          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5670          !rt.Is(pc)) {
5671        EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5672                   (offset & 0xfff));
5673        AdvanceIT();
5674        return;
5675      }
5676      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
5677      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5678          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5679          !rt.Is(pc)) {
5680        EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5681                   (-offset & 0xff));
5682        AdvanceIT();
5683        return;
5684      }
5685      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
5686      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5687          (operand.GetAddrMode() == PostIndex) &&
5688          ((rn.GetCode() & 0xf) != 0xf)) {
5689        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5690        uint32_t offset_ = abs(offset);
5691        EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5692                   offset_ | (sign << 9));
5693        AdvanceIT();
5694        return;
5695      }
5696      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
5697      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5698          (operand.GetAddrMode() == PreIndex) &&
5699          ((rn.GetCode() & 0xf) != 0xf)) {
5700        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5701        uint32_t offset_ = abs(offset);
5702        EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5703                   offset_ | (sign << 9));
5704        AdvanceIT();
5705        return;
5706      }
5707      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5708      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5709          rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
5710        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5711        uint32_t offset_ = abs(offset);
5712        EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5713        AdvanceIT();
5714        return;
5715      }
5716    } else {
5717      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
5718      if ((offset >= -255) && (offset <= 255) &&
5719          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5720          ((rn.GetCode() & 0xf) != 0xf)) {
5721        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5722        uint32_t offset_ = abs(offset);
5723        EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
5724                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5725                ((offset_ & 0xf0) << 4) | (sign << 23));
5726        return;
5727      }
5728      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
5729      if ((offset >= -255) && (offset <= 255) &&
5730          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5731          ((rn.GetCode() & 0xf) != 0xf)) {
5732        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5733        uint32_t offset_ = abs(offset);
5734        EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
5735                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5736                ((offset_ & 0xf0) << 4) | (sign << 23));
5737        return;
5738      }
5739      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
5740      if ((offset >= -255) && (offset <= 255) &&
5741          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5742          ((rn.GetCode() & 0xf) != 0xf)) {
5743        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5744        uint32_t offset_ = abs(offset);
5745        EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
5746                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5747                ((offset_ & 0xf0) << 4) | (sign << 23));
5748        return;
5749      }
5750      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5751      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5752          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5753        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5754        uint32_t offset_ = abs(offset);
5755        EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
5756                (rt.GetCode() << 12) | (offset_ & 0xf) |
5757                ((offset_ & 0xf0) << 4) | (sign << 23));
5758        return;
5759      }
5760    }
5761  }
5762  if (operand.IsPlainRegister()) {
5763    Register rn = operand.GetBaseRegister();
5764    Sign sign = operand.GetSign();
5765    Register rm = operand.GetOffsetRegister();
5766    if (IsUsingT32()) {
5767      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5768      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5769          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
5770        EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
5771                   (rm.GetCode() << 6));
5772        AdvanceIT();
5773        return;
5774      }
5775    } else {
5776      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5777      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5778        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5779        EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
5780                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5781                (sign_ << 23));
5782        return;
5783      }
5784      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5785      if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
5786        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5787        EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
5788                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5789                (sign_ << 23));
5790        return;
5791      }
5792      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5793      if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
5794        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5795        EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
5796                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5797                (sign_ << 23));
5798        return;
5799      }
5800    }
5801  }
5802  if (operand.IsShiftedRegister()) {
5803    Register rn = operand.GetBaseRegister();
5804    Sign sign = operand.GetSign();
5805    Register rm = operand.GetOffsetRegister();
5806    Shift shift = operand.GetShift();
5807    uint32_t amount = operand.GetShiftAmount();
5808    if (IsUsingT32()) {
5809      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5810      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5811          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5812          !rt.Is(pc)) {
5813        EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5814                   rm.GetCode() | (amount << 4));
5815        AdvanceIT();
5816        return;
5817      }
5818    }
5819  }
5820  Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
5821}
5822
5823void Assembler::ldrsb(Condition cond, Register rt, Label* label) {
5824  VIXL_ASSERT(AllowAssembler());
5825  CheckIT(cond);
5826  Label::Offset offset =
5827      label->IsBound()
5828          ? label->GetLocation() -
5829                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5830          : 0;
5831  if (IsUsingT32()) {
5832    // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
5833    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5834         !label->IsBound()) &&
5835        !rt.Is(pc)) {
5836      static class EmitOp : public Label::LabelEmitOperator {
5837       public:
5838        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5839        uint32_t Encode(uint32_t instr,
5840                        Label::Offset pc,
5841                        const Label* label) const {
5842          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5843          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5844          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5845          int32_t target = abs(offset) | (U << 12);
5846          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5847        }
5848      } immop;
5849      EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12), label, immop));
5850      AdvanceIT();
5851      return;
5852    }
5853  } else {
5854    // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
5855    if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5856         !label->IsBound()) &&
5857        cond.IsNotNever()) {
5858      static class EmitOp : public Label::LabelEmitOperator {
5859       public:
5860        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
5861        uint32_t Encode(uint32_t instr,
5862                        Label::Offset pc,
5863                        const Label* label) const {
5864          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5865          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5866          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5867          int32_t target = abs(offset) | (U << 8);
5868          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5869                 ((target & 0x100) << 15);
5870        }
5871      } immop;
5872      EmitA32(
5873          Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5874               label,
5875               immop));
5876      return;
5877    }
5878  }
5879  Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, label);
5880}
5881
5882void Assembler::ldrsh(Condition cond,
5883                      EncodingSize size,
5884                      Register rt,
5885                      const MemOperand& operand) {
5886  VIXL_ASSERT(AllowAssembler());
5887  CheckIT(cond);
5888  if (operand.IsImmediate()) {
5889    Register rn = operand.GetBaseRegister();
5890    int32_t offset = operand.GetOffsetImmediate();
5891    if (IsUsingT32()) {
5892      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5893      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5894          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5895          !rt.Is(pc)) {
5896        EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5897                   (offset & 0xfff));
5898        AdvanceIT();
5899        return;
5900      }
5901      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
5902      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5903          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5904          !rt.Is(pc)) {
5905        EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5906                   (-offset & 0xff));
5907        AdvanceIT();
5908        return;
5909      }
5910      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
5911      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5912          (operand.GetAddrMode() == PostIndex) &&
5913          ((rn.GetCode() & 0xf) != 0xf)) {
5914        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5915        uint32_t offset_ = abs(offset);
5916        EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5917                   offset_ | (sign << 9));
5918        AdvanceIT();
5919        return;
5920      }
5921      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
5922      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5923          (operand.GetAddrMode() == PreIndex) &&
5924          ((rn.GetCode() & 0xf) != 0xf)) {
5925        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5926        uint32_t offset_ = abs(offset);
5927        EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5928                   offset_ | (sign << 9));
5929        AdvanceIT();
5930        return;
5931      }
5932      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5933      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5934          rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
5935        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5936        uint32_t offset_ = abs(offset);
5937        EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5938        AdvanceIT();
5939        return;
5940      }
5941    } else {
5942      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
5943      if ((offset >= -255) && (offset <= 255) &&
5944          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5945          ((rn.GetCode() & 0xf) != 0xf)) {
5946        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5947        uint32_t offset_ = abs(offset);
5948        EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
5949                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5950                ((offset_ & 0xf0) << 4) | (sign << 23));
5951        return;
5952      }
5953      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
5954      if ((offset >= -255) && (offset <= 255) &&
5955          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5956          ((rn.GetCode() & 0xf) != 0xf)) {
5957        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5958        uint32_t offset_ = abs(offset);
5959        EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
5960                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5961                ((offset_ & 0xf0) << 4) | (sign << 23));
5962        return;
5963      }
5964      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
5965      if ((offset >= -255) && (offset <= 255) &&
5966          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5967          ((rn.GetCode() & 0xf) != 0xf)) {
5968        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5969        uint32_t offset_ = abs(offset);
5970        EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
5971                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5972                ((offset_ & 0xf0) << 4) | (sign << 23));
5973        return;
5974      }
5975      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5976      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5977          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5978        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5979        uint32_t offset_ = abs(offset);
5980        EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
5981                (rt.GetCode() << 12) | (offset_ & 0xf) |
5982                ((offset_ & 0xf0) << 4) | (sign << 23));
5983        return;
5984      }
5985    }
5986  }
5987  if (operand.IsPlainRegister()) {
5988    Register rn = operand.GetBaseRegister();
5989    Sign sign = operand.GetSign();
5990    Register rm = operand.GetOffsetRegister();
5991    if (IsUsingT32()) {
5992      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5993      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5994          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
5995        EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
5996                   (rm.GetCode() << 6));
5997        AdvanceIT();
5998        return;
5999      }
6000    } else {
6001      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6002      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
6003        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6004        EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6005                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6006                (sign_ << 23));
6007        return;
6008      }
6009      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6010      if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
6011        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6012        EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6013                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6014                (sign_ << 23));
6015        return;
6016      }
6017      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6018      if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
6019        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6020        EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6021                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6022                (sign_ << 23));
6023        return;
6024      }
6025    }
6026  }
6027  if (operand.IsShiftedRegister()) {
6028    Register rn = operand.GetBaseRegister();
6029    Sign sign = operand.GetSign();
6030    Register rm = operand.GetOffsetRegister();
6031    Shift shift = operand.GetShift();
6032    uint32_t amount = operand.GetShiftAmount();
6033    if (IsUsingT32()) {
6034      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6035      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6036          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
6037          !rt.Is(pc)) {
6038        EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6039                   rm.GetCode() | (amount << 4));
6040        AdvanceIT();
6041        return;
6042      }
6043    }
6044  }
6045  Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6046}
6047
6048void Assembler::ldrsh(Condition cond, Register rt, Label* label) {
6049  VIXL_ASSERT(AllowAssembler());
6050  CheckIT(cond);
6051  Label::Offset offset =
6052      label->IsBound()
6053          ? label->GetLocation() -
6054                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6055          : 0;
6056  if (IsUsingT32()) {
6057    // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6058    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6059         !label->IsBound()) &&
6060        !rt.Is(pc)) {
6061      static class EmitOp : public Label::LabelEmitOperator {
6062       public:
6063        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
6064        uint32_t Encode(uint32_t instr,
6065                        Label::Offset pc,
6066                        const Label* label) const {
6067          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
6068          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
6069          uint32_t U = (offset >= 0) && !label->IsMinusZero();
6070          int32_t target = abs(offset) | (U << 12);
6071          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6072        }
6073      } immop;
6074      EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12), label, immop));
6075      AdvanceIT();
6076      return;
6077    }
6078  } else {
6079    // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6080    if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
6081         !label->IsBound()) &&
6082        cond.IsNotNever()) {
6083      static class EmitOp : public Label::LabelEmitOperator {
6084       public:
6085        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
6086        uint32_t Encode(uint32_t instr,
6087                        Label::Offset pc,
6088                        const Label* label) const {
6089          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
6090          VIXL_ASSERT((offset >= -255) && (offset <= 255));
6091          uint32_t U = (offset >= 0) && !label->IsMinusZero();
6092          int32_t target = abs(offset) | (U << 8);
6093          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6094                 ((target & 0x100) << 15);
6095        }
6096      } immop;
6097      EmitA32(
6098          Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6099               label,
6100               immop));
6101      return;
6102    }
6103  }
6104  Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, label);
6105}
6106
6107void Assembler::lsl(Condition cond,
6108                    EncodingSize size,
6109                    Register rd,
6110                    Register rm,
6111                    const Operand& operand) {
6112  VIXL_ASSERT(AllowAssembler());
6113  CheckIT(cond);
6114  if (operand.IsImmediate()) {
6115    uint32_t imm = operand.GetImmediate();
6116    if (IsUsingT32()) {
6117      // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6118      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6119          (imm >= 1) && (imm <= 31)) {
6120        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6121        AdvanceIT();
6122        return;
6123      }
6124      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6125      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
6126        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6127                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6128        AdvanceIT();
6129        return;
6130      }
6131    } else {
6132      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6133      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6134        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6135                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6136        return;
6137      }
6138    }
6139  }
6140  if (operand.IsPlainRegister()) {
6141    Register rs = operand.GetBaseRegister();
6142    if (IsUsingT32()) {
6143      // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6144      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6145          rs.IsLow()) {
6146        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6147        AdvanceIT();
6148        return;
6149      }
6150      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6151      if (!size.IsNarrow()) {
6152        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6153                   rs.GetCode());
6154        AdvanceIT();
6155        return;
6156      }
6157    } else {
6158      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6159      if (cond.IsNotNever()) {
6160        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6161                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6162        return;
6163      }
6164    }
6165  }
6166  Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6167}
6168
6169void Assembler::lsls(Condition cond,
6170                     EncodingSize size,
6171                     Register rd,
6172                     Register rm,
6173                     const Operand& operand) {
6174  VIXL_ASSERT(AllowAssembler());
6175  CheckIT(cond);
6176  if (operand.IsImmediate()) {
6177    uint32_t imm = operand.GetImmediate();
6178    if (IsUsingT32()) {
6179      // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6180      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6181          (imm >= 1) && (imm <= 31)) {
6182        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6183        AdvanceIT();
6184        return;
6185      }
6186      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6187      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
6188        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6189                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6190        AdvanceIT();
6191        return;
6192      }
6193    } else {
6194      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6195      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6196        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6197                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6198        return;
6199      }
6200    }
6201  }
6202  if (operand.IsPlainRegister()) {
6203    Register rs = operand.GetBaseRegister();
6204    if (IsUsingT32()) {
6205      // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6206      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6207          rs.IsLow()) {
6208        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6209        AdvanceIT();
6210        return;
6211      }
6212      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6213      if (!size.IsNarrow()) {
6214        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6215                   rs.GetCode());
6216        AdvanceIT();
6217        return;
6218      }
6219    } else {
6220      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6221      if (cond.IsNotNever()) {
6222        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6223                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6224        return;
6225      }
6226    }
6227  }
6228  Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6229}
6230
6231void Assembler::lsr(Condition cond,
6232                    EncodingSize size,
6233                    Register rd,
6234                    Register rm,
6235                    const Operand& operand) {
6236  VIXL_ASSERT(AllowAssembler());
6237  CheckIT(cond);
6238  if (operand.IsImmediate()) {
6239    uint32_t imm = operand.GetImmediate();
6240    if (IsUsingT32()) {
6241      // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6242      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6243          (imm >= 1) && (imm <= 32)) {
6244        uint32_t amount_ = imm % 32;
6245        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6246                   (amount_ << 6));
6247        AdvanceIT();
6248        return;
6249      }
6250      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6251      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
6252        uint32_t amount_ = imm % 32;
6253        EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6254                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6255        AdvanceIT();
6256        return;
6257      }
6258    } else {
6259      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6260      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6261        uint32_t amount_ = imm % 32;
6262        EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6263                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6264        return;
6265      }
6266    }
6267  }
6268  if (operand.IsPlainRegister()) {
6269    Register rs = operand.GetBaseRegister();
6270    if (IsUsingT32()) {
6271      // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6272      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6273          rs.IsLow()) {
6274        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6275        AdvanceIT();
6276        return;
6277      }
6278      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6279      if (!size.IsNarrow()) {
6280        EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6281                   rs.GetCode());
6282        AdvanceIT();
6283        return;
6284      }
6285    } else {
6286      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6287      if (cond.IsNotNever()) {
6288        EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6289                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6290        return;
6291      }
6292    }
6293  }
6294  Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6295}
6296
6297void Assembler::lsrs(Condition cond,
6298                     EncodingSize size,
6299                     Register rd,
6300                     Register rm,
6301                     const Operand& operand) {
6302  VIXL_ASSERT(AllowAssembler());
6303  CheckIT(cond);
6304  if (operand.IsImmediate()) {
6305    uint32_t imm = operand.GetImmediate();
6306    if (IsUsingT32()) {
6307      // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6308      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6309          (imm >= 1) && (imm <= 32)) {
6310        uint32_t amount_ = imm % 32;
6311        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6312                   (amount_ << 6));
6313        AdvanceIT();
6314        return;
6315      }
6316      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6317      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
6318        uint32_t amount_ = imm % 32;
6319        EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6320                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6321        AdvanceIT();
6322        return;
6323      }
6324    } else {
6325      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6326      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6327        uint32_t amount_ = imm % 32;
6328        EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6329                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6330        return;
6331      }
6332    }
6333  }
6334  if (operand.IsPlainRegister()) {
6335    Register rs = operand.GetBaseRegister();
6336    if (IsUsingT32()) {
6337      // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6338      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6339          rs.IsLow()) {
6340        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6341        AdvanceIT();
6342        return;
6343      }
6344      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6345      if (!size.IsNarrow()) {
6346        EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6347                   rs.GetCode());
6348        AdvanceIT();
6349        return;
6350      }
6351    } else {
6352      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6353      if (cond.IsNotNever()) {
6354        EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6355                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6356        return;
6357      }
6358    }
6359  }
6360  Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6361}
6362
6363void Assembler::mla(
6364    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6365  VIXL_ASSERT(AllowAssembler());
6366  CheckIT(cond);
6367  if (IsUsingT32()) {
6368    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6369    if (!ra.Is(pc)) {
6370      EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6371                 rm.GetCode() | (ra.GetCode() << 12));
6372      AdvanceIT();
6373      return;
6374    }
6375  } else {
6376    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6377    if (cond.IsNotNever()) {
6378      EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6379              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6380      return;
6381    }
6382  }
6383  Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
6384}
6385
6386void Assembler::mlas(
6387    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6388  VIXL_ASSERT(AllowAssembler());
6389  CheckIT(cond);
6390  if (IsUsingA32()) {
6391    // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6392    if (cond.IsNotNever()) {
6393      EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6394              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6395      return;
6396    }
6397  }
6398  Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
6399}
6400
6401void Assembler::mls(
6402    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6403  VIXL_ASSERT(AllowAssembler());
6404  CheckIT(cond);
6405  if (IsUsingT32()) {
6406    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6407    EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6408               rm.GetCode() | (ra.GetCode() << 12));
6409    AdvanceIT();
6410    return;
6411  } else {
6412    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6413    if (cond.IsNotNever()) {
6414      EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6415              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6416      return;
6417    }
6418  }
6419  Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
6420}
6421
6422void Assembler::mov(Condition cond,
6423                    EncodingSize size,
6424                    Register rd,
6425                    const Operand& operand) {
6426  VIXL_ASSERT(AllowAssembler());
6427  CheckIT(cond);
6428  if (operand.IsImmediateShiftedRegister()) {
6429    Register rm = operand.GetBaseRegister();
6430    if (operand.IsPlainRegister()) {
6431      if (IsUsingT32()) {
6432        // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
6433        if (!size.IsWide()) {
6434          EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
6435                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
6436          AdvanceIT();
6437          return;
6438        }
6439      }
6440    }
6441    Shift shift = operand.GetShift();
6442    uint32_t amount = operand.GetShiftAmount();
6443    if (IsUsingT32()) {
6444      // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6445      if (InITBlock() && !size.IsWide() && rd.IsLow() &&
6446          shift.IsValidAmount(amount) && rm.IsLow() &&
6447          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
6448        uint32_t amount_ = amount % 32;
6449        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
6450                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
6451        AdvanceIT();
6452        return;
6453      }
6454      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
6455      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6456        uint32_t amount_ = amount % 32;
6457        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6458                   (operand.GetTypeEncodingValue() << 4) |
6459                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6460        AdvanceIT();
6461        return;
6462      }
6463    } else {
6464      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6465      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6466        uint32_t amount_ = amount % 32;
6467        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6468                (rd.GetCode() << 12) | rm.GetCode() |
6469                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6470        return;
6471      }
6472    }
6473  }
6474  if (operand.IsRegisterShiftedRegister()) {
6475    Register rm = operand.GetBaseRegister();
6476    Shift shift = operand.GetShift();
6477    if (IsUsingT32()) {
6478      // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
6479      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6480          shift.IsASR() && operand.GetShiftRegister().IsLow()) {
6481        EmitT32_16(0x4100 | rd.GetCode() |
6482                   (operand.GetShiftRegister().GetCode() << 3));
6483        AdvanceIT();
6484        return;
6485      }
6486      // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
6487      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6488          shift.IsLSL() && operand.GetShiftRegister().IsLow()) {
6489        EmitT32_16(0x4080 | rd.GetCode() |
6490                   (operand.GetShiftRegister().GetCode() << 3));
6491        AdvanceIT();
6492        return;
6493      }
6494      // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
6495      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6496          shift.IsLSR() && operand.GetShiftRegister().IsLow()) {
6497        EmitT32_16(0x40c0 | rd.GetCode() |
6498                   (operand.GetShiftRegister().GetCode() << 3));
6499        AdvanceIT();
6500        return;
6501      }
6502      // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
6503      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6504          shift.IsROR() && operand.GetShiftRegister().IsLow()) {
6505        EmitT32_16(0x41c0 | rd.GetCode() |
6506                   (operand.GetShiftRegister().GetCode() << 3));
6507        AdvanceIT();
6508        return;
6509      }
6510      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
6511      if (!size.IsNarrow()) {
6512        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6513                   (shift.GetType() << 21) |
6514                   operand.GetShiftRegister().GetCode());
6515        AdvanceIT();
6516        return;
6517      }
6518    } else {
6519      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6520      if (cond.IsNotNever()) {
6521        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6522                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6523                (operand.GetShiftRegister().GetCode() << 8));
6524        return;
6525      }
6526    }
6527  }
6528  if (operand.IsImmediate()) {
6529    uint32_t imm = operand.GetImmediate();
6530    if (IsUsingT32()) {
6531      ImmediateT32 immediate_t32(imm);
6532      // MOV<c>{<q>} <Rd>, #<imm8> ; T1
6533      if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
6534        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
6535        AdvanceIT();
6536        return;
6537      }
6538      // MOV{<c>}{<q>} <Rd>, #<const> ; T2
6539      if (!size.IsNarrow() && immediate_t32.IsValid()) {
6540        EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
6541                   (immediate_t32.GetEncodingValue() & 0xff) |
6542                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6543                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6544        AdvanceIT();
6545        return;
6546      }
6547      // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
6548      if (!size.IsNarrow() && (imm <= 65535)) {
6549        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
6550                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6551                   ((imm & 0xf000) << 4));
6552        AdvanceIT();
6553        return;
6554      }
6555    } else {
6556      ImmediateA32 immediate_a32(imm);
6557      // MOV{<c>}{<q>} <Rd>, #<const> ; A1
6558      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6559        EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
6560                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6561        return;
6562      }
6563      // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
6564      if ((imm <= 65535) && cond.IsNotNever()) {
6565        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
6566                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6567        return;
6568      }
6569    }
6570  }
6571  Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
6572}
6573
6574void Assembler::movs(Condition cond,
6575                     EncodingSize size,
6576                     Register rd,
6577                     const Operand& operand) {
6578  VIXL_ASSERT(AllowAssembler());
6579  CheckIT(cond);
6580  if (operand.IsImmediateShiftedRegister()) {
6581    Register rm = operand.GetBaseRegister();
6582    Shift shift = operand.GetShift();
6583    uint32_t amount = operand.GetShiftAmount();
6584    if (IsUsingT32()) {
6585      // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6586      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
6587          shift.IsValidAmount(amount) && rm.IsLow() &&
6588          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
6589        uint32_t amount_ = amount % 32;
6590        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
6591                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
6592        AdvanceIT();
6593        return;
6594      }
6595      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
6596      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6597        uint32_t amount_ = amount % 32;
6598        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6599                   (operand.GetTypeEncodingValue() << 4) |
6600                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6601        AdvanceIT();
6602        return;
6603      }
6604    } else {
6605      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6606      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6607        uint32_t amount_ = amount % 32;
6608        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6609                (rd.GetCode() << 12) | rm.GetCode() |
6610                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6611        return;
6612      }
6613    }
6614  }
6615  if (operand.IsRegisterShiftedRegister()) {
6616    Register rm = operand.GetBaseRegister();
6617    Shift shift = operand.GetShift();
6618    if (IsUsingT32()) {
6619      // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
6620      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6621          shift.IsASR() && operand.GetShiftRegister().IsLow()) {
6622        EmitT32_16(0x4100 | rd.GetCode() |
6623                   (operand.GetShiftRegister().GetCode() << 3));
6624        AdvanceIT();
6625        return;
6626      }
6627      // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
6628      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6629          shift.IsLSL() && operand.GetShiftRegister().IsLow()) {
6630        EmitT32_16(0x4080 | rd.GetCode() |
6631                   (operand.GetShiftRegister().GetCode() << 3));
6632        AdvanceIT();
6633        return;
6634      }
6635      // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
6636      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6637          shift.IsLSR() && operand.GetShiftRegister().IsLow()) {
6638        EmitT32_16(0x40c0 | rd.GetCode() |
6639                   (operand.GetShiftRegister().GetCode() << 3));
6640        AdvanceIT();
6641        return;
6642      }
6643      // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
6644      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6645          shift.IsROR() && operand.GetShiftRegister().IsLow()) {
6646        EmitT32_16(0x41c0 | rd.GetCode() |
6647                   (operand.GetShiftRegister().GetCode() << 3));
6648        AdvanceIT();
6649        return;
6650      }
6651      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
6652      if (!size.IsNarrow()) {
6653        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6654                   (shift.GetType() << 21) |
6655                   operand.GetShiftRegister().GetCode());
6656        AdvanceIT();
6657        return;
6658      }
6659    } else {
6660      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6661      if (cond.IsNotNever()) {
6662        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6663                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6664                (operand.GetShiftRegister().GetCode() << 8));
6665        return;
6666      }
6667    }
6668  }
6669  if (operand.IsImmediate()) {
6670    uint32_t imm = operand.GetImmediate();
6671    if (IsUsingT32()) {
6672      ImmediateT32 immediate_t32(imm);
6673      // MOVS{<q>} <Rd>, #<imm8> ; T1
6674      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
6675        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
6676        AdvanceIT();
6677        return;
6678      }
6679      // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
6680      if (!size.IsNarrow() && immediate_t32.IsValid()) {
6681        EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
6682                   (immediate_t32.GetEncodingValue() & 0xff) |
6683                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6684                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6685        AdvanceIT();
6686        return;
6687      }
6688    } else {
6689      ImmediateA32 immediate_a32(imm);
6690      // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
6691      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6692        EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
6693                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6694        return;
6695      }
6696    }
6697  }
6698  Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
6699}
6700
6701void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
6702  VIXL_ASSERT(AllowAssembler());
6703  CheckIT(cond);
6704  if (operand.IsImmediate()) {
6705    uint32_t imm = operand.GetImmediate();
6706    if (IsUsingT32()) {
6707      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
6708      if ((imm <= 65535)) {
6709        EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
6710                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6711                   ((imm & 0xf000) << 4));
6712        AdvanceIT();
6713        return;
6714      }
6715    } else {
6716      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
6717      if ((imm <= 65535) && cond.IsNotNever()) {
6718        EmitA32(0x03400000U | (cond.GetCondition() << 28) |
6719                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6720        return;
6721      }
6722    }
6723  }
6724  Delegate(kMovt, &Assembler::movt, cond, rd, operand);
6725}
6726
6727void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
6728  VIXL_ASSERT(AllowAssembler());
6729  CheckIT(cond);
6730  if (operand.IsImmediate()) {
6731    uint32_t imm = operand.GetImmediate();
6732    if (IsUsingT32()) {
6733      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
6734      if ((imm <= 65535)) {
6735        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
6736                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6737                   ((imm & 0xf000) << 4));
6738        AdvanceIT();
6739        return;
6740      }
6741    } else {
6742      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
6743      if ((imm <= 65535) && cond.IsNotNever()) {
6744        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
6745                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6746        return;
6747      }
6748    }
6749  }
6750  Delegate(kMovw, &Assembler::movw, cond, rd, operand);
6751}
6752
6753void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
6754  VIXL_ASSERT(AllowAssembler());
6755  CheckIT(cond);
6756  if (IsUsingT32()) {
6757    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
6758    EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
6759    AdvanceIT();
6760    return;
6761  } else {
6762    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
6763    if (cond.IsNotNever()) {
6764      EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
6765              (spec_reg.GetReg() << 22));
6766      return;
6767    }
6768  }
6769  Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
6770}
6771
6772void Assembler::msr(Condition cond,
6773                    MaskedSpecialRegister spec_reg,
6774                    const Operand& operand) {
6775  VIXL_ASSERT(AllowAssembler());
6776  CheckIT(cond);
6777  if (operand.IsImmediate()) {
6778    uint32_t imm = operand.GetImmediate();
6779    if (IsUsingA32()) {
6780      ImmediateA32 immediate_a32(imm);
6781      // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
6782      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6783        EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
6784                ((spec_reg.GetReg() & 0xf) << 16) |
6785                ((spec_reg.GetReg() & 0x10) << 18) |
6786                immediate_a32.GetEncodingValue());
6787        return;
6788      }
6789    }
6790  }
6791  if (operand.IsPlainRegister()) {
6792    Register rn = operand.GetBaseRegister();
6793    if (IsUsingT32()) {
6794      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
6795      EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
6796                 ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
6797      AdvanceIT();
6798      return;
6799    } else {
6800      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
6801      if (cond.IsNotNever()) {
6802        EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
6803                ((spec_reg.GetReg() & 0xf) << 16) |
6804                ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
6805        return;
6806      }
6807    }
6808  }
6809  Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
6810}
6811
6812void Assembler::mul(
6813    Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
6814  VIXL_ASSERT(AllowAssembler());
6815  CheckIT(cond);
6816  if (IsUsingT32()) {
6817    // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
6818    if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
6819        rm.IsLow()) {
6820      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
6821      AdvanceIT();
6822      return;
6823    }
6824    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
6825    if (!size.IsNarrow()) {
6826      EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6827                 rm.GetCode());
6828      AdvanceIT();
6829      return;
6830    }
6831  } else {
6832    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
6833    if (cond.IsNotNever()) {
6834      EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6835              rn.GetCode() | (rm.GetCode() << 8));
6836      return;
6837    }
6838  }
6839  Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
6840}
6841
6842void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
6843  VIXL_ASSERT(AllowAssembler());
6844  CheckIT(cond);
6845  if (IsUsingT32()) {
6846    // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
6847    if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
6848      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
6849      AdvanceIT();
6850      return;
6851    }
6852  } else {
6853    // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
6854    if (cond.IsNotNever()) {
6855      EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6856              rn.GetCode() | (rm.GetCode() << 8));
6857      return;
6858    }
6859  }
6860  Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
6861}
6862
6863void Assembler::mvn(Condition cond,
6864                    EncodingSize size,
6865                    Register rd,
6866                    const Operand& operand) {
6867  VIXL_ASSERT(AllowAssembler());
6868  CheckIT(cond);
6869  if (operand.IsImmediate()) {
6870    uint32_t imm = operand.GetImmediate();
6871    if (IsUsingT32()) {
6872      ImmediateT32 immediate_t32(imm);
6873      // MVN{<c>}{<q>} <Rd>, #<const> ; T1
6874      if (!size.IsNarrow() && immediate_t32.IsValid()) {
6875        EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
6876                   (immediate_t32.GetEncodingValue() & 0xff) |
6877                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6878                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6879        AdvanceIT();
6880        return;
6881      }
6882    } else {
6883      ImmediateA32 immediate_a32(imm);
6884      // MVN{<c>}{<q>} <Rd>, #<const> ; A1
6885      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6886        EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
6887                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6888        return;
6889      }
6890    }
6891  }
6892  if (operand.IsImmediateShiftedRegister()) {
6893    Register rm = operand.GetBaseRegister();
6894    if (operand.IsPlainRegister()) {
6895      if (IsUsingT32()) {
6896        // MVN<c>{<q>} <Rd>, <Rm> ; T1
6897        if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
6898          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
6899          AdvanceIT();
6900          return;
6901        }
6902      }
6903    }
6904    Shift shift = operand.GetShift();
6905    uint32_t amount = operand.GetShiftAmount();
6906    if (IsUsingT32()) {
6907      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6908      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6909        uint32_t amount_ = amount % 32;
6910        EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6911                   (operand.GetTypeEncodingValue() << 4) |
6912                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6913        AdvanceIT();
6914        return;
6915      }
6916    } else {
6917      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6918      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6919        uint32_t amount_ = amount % 32;
6920        EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
6921                (rd.GetCode() << 12) | rm.GetCode() |
6922                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6923        return;
6924      }
6925    }
6926  }
6927  if (operand.IsRegisterShiftedRegister()) {
6928    Register rm = operand.GetBaseRegister();
6929    Shift shift = operand.GetShift();
6930    if (IsUsingA32()) {
6931      // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6932      if (cond.IsNotNever()) {
6933        EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
6934                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6935                (operand.GetShiftRegister().GetCode() << 8));
6936        return;
6937      }
6938    }
6939  }
6940  Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
6941}
6942
6943void Assembler::mvns(Condition cond,
6944                     EncodingSize size,
6945                     Register rd,
6946                     const Operand& operand) {
6947  VIXL_ASSERT(AllowAssembler());
6948  CheckIT(cond);
6949  if (operand.IsImmediate()) {
6950    uint32_t imm = operand.GetImmediate();
6951    if (IsUsingT32()) {
6952      ImmediateT32 immediate_t32(imm);
6953      // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
6954      if (!size.IsNarrow() && immediate_t32.IsValid()) {
6955        EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
6956                   (immediate_t32.GetEncodingValue() & 0xff) |
6957                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6958                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6959        AdvanceIT();
6960        return;
6961      }
6962    } else {
6963      ImmediateA32 immediate_a32(imm);
6964      // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
6965      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6966        EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
6967                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6968        return;
6969      }
6970    }
6971  }
6972  if (operand.IsImmediateShiftedRegister()) {
6973    Register rm = operand.GetBaseRegister();
6974    if (operand.IsPlainRegister()) {
6975      if (IsUsingT32()) {
6976        // MVNS{<q>} <Rd>, <Rm> ; T1
6977        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
6978          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
6979          AdvanceIT();
6980          return;
6981        }
6982      }
6983    }
6984    Shift shift = operand.GetShift();
6985    uint32_t amount = operand.GetShiftAmount();
6986    if (IsUsingT32()) {
6987      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6988      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6989        uint32_t amount_ = amount % 32;
6990        EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6991                   (operand.GetTypeEncodingValue() << 4) |
6992                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6993        AdvanceIT();
6994        return;
6995      }
6996    } else {
6997      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6998      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6999        uint32_t amount_ = amount % 32;
7000        EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7001                (rd.GetCode() << 12) | rm.GetCode() |
7002                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7003        return;
7004      }
7005    }
7006  }
7007  if (operand.IsRegisterShiftedRegister()) {
7008    Register rm = operand.GetBaseRegister();
7009    Shift shift = operand.GetShift();
7010    if (IsUsingA32()) {
7011      // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7012      if (cond.IsNotNever()) {
7013        EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7014                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7015                (operand.GetShiftRegister().GetCode() << 8));
7016        return;
7017      }
7018    }
7019  }
7020  Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7021}
7022
7023void Assembler::nop(Condition cond, EncodingSize size) {
7024  VIXL_ASSERT(AllowAssembler());
7025  CheckIT(cond);
7026  if (IsUsingT32()) {
7027    // NOP{<c>}{<q>} ; T1
7028    if (!size.IsWide()) {
7029      EmitT32_16(0xbf00);
7030      AdvanceIT();
7031      return;
7032    }
7033    // NOP{<c>}.W ; T2
7034    if (!size.IsNarrow()) {
7035      EmitT32_32(0xf3af8000U);
7036      AdvanceIT();
7037      return;
7038    }
7039  } else {
7040    // NOP{<c>}{<q>} ; A1
7041    if (cond.IsNotNever()) {
7042      EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7043      return;
7044    }
7045  }
7046  Delegate(kNop, &Assembler::nop, cond, size);
7047}
7048
7049void Assembler::orn(Condition cond,
7050                    Register rd,
7051                    Register rn,
7052                    const Operand& operand) {
7053  VIXL_ASSERT(AllowAssembler());
7054  CheckIT(cond);
7055  if (operand.IsImmediate()) {
7056    uint32_t imm = operand.GetImmediate();
7057    if (IsUsingT32()) {
7058      ImmediateT32 immediate_t32(imm);
7059      // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7060      if (immediate_t32.IsValid() && !rn.Is(pc)) {
7061        EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7062                   (immediate_t32.GetEncodingValue() & 0xff) |
7063                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7064                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7065        AdvanceIT();
7066        return;
7067      }
7068    }
7069  }
7070  if (operand.IsImmediateShiftedRegister()) {
7071    Register rm = operand.GetBaseRegister();
7072    Shift shift = operand.GetShift();
7073    uint32_t amount = operand.GetShiftAmount();
7074    if (IsUsingT32()) {
7075      // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7076      if (shift.IsValidAmount(amount) && !rn.Is(pc)) {
7077        uint32_t amount_ = amount % 32;
7078        EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7079                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7080                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7081        AdvanceIT();
7082        return;
7083      }
7084    }
7085  }
7086  Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7087}
7088
7089void Assembler::orns(Condition cond,
7090                     Register rd,
7091                     Register rn,
7092                     const Operand& operand) {
7093  VIXL_ASSERT(AllowAssembler());
7094  CheckIT(cond);
7095  if (operand.IsImmediate()) {
7096    uint32_t imm = operand.GetImmediate();
7097    if (IsUsingT32()) {
7098      ImmediateT32 immediate_t32(imm);
7099      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7100      if (immediate_t32.IsValid() && !rn.Is(pc)) {
7101        EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7102                   (immediate_t32.GetEncodingValue() & 0xff) |
7103                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7104                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7105        AdvanceIT();
7106        return;
7107      }
7108    }
7109  }
7110  if (operand.IsImmediateShiftedRegister()) {
7111    Register rm = operand.GetBaseRegister();
7112    Shift shift = operand.GetShift();
7113    uint32_t amount = operand.GetShiftAmount();
7114    if (IsUsingT32()) {
7115      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7116      if (shift.IsValidAmount(amount) && !rn.Is(pc)) {
7117        uint32_t amount_ = amount % 32;
7118        EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7119                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7120                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7121        AdvanceIT();
7122        return;
7123      }
7124    }
7125  }
7126  Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7127}
7128
7129void Assembler::orr(Condition cond,
7130                    EncodingSize size,
7131                    Register rd,
7132                    Register rn,
7133                    const Operand& operand) {
7134  VIXL_ASSERT(AllowAssembler());
7135  CheckIT(cond);
7136  if (operand.IsImmediate()) {
7137    uint32_t imm = operand.GetImmediate();
7138    if (IsUsingT32()) {
7139      ImmediateT32 immediate_t32(imm);
7140      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7141      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc)) {
7142        EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7143                   (immediate_t32.GetEncodingValue() & 0xff) |
7144                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7145                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7146        AdvanceIT();
7147        return;
7148      }
7149    } else {
7150      ImmediateA32 immediate_a32(imm);
7151      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7152      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7153        EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7154                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7155                immediate_a32.GetEncodingValue());
7156        return;
7157      }
7158    }
7159  }
7160  if (operand.IsImmediateShiftedRegister()) {
7161    Register rm = operand.GetBaseRegister();
7162    if (operand.IsPlainRegister()) {
7163      if (IsUsingT32()) {
7164        // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7165        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7166            rm.IsLow()) {
7167          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7168          AdvanceIT();
7169          return;
7170        }
7171      }
7172    }
7173    Shift shift = operand.GetShift();
7174    uint32_t amount = operand.GetShiftAmount();
7175    if (IsUsingT32()) {
7176      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7177      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc)) {
7178        uint32_t amount_ = amount % 32;
7179        EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7180                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7181                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7182        AdvanceIT();
7183        return;
7184      }
7185    } else {
7186      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7187      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7188        uint32_t amount_ = amount % 32;
7189        EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7190                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7191                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7192        return;
7193      }
7194    }
7195  }
7196  if (operand.IsRegisterShiftedRegister()) {
7197    Register rm = operand.GetBaseRegister();
7198    Shift shift = operand.GetShift();
7199    if (IsUsingA32()) {
7200      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7201      if (cond.IsNotNever()) {
7202        EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7203                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7204                (shift.GetType() << 5) |
7205                (operand.GetShiftRegister().GetCode() << 8));
7206        return;
7207      }
7208    }
7209  }
7210  Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7211}
7212
7213void Assembler::orrs(Condition cond,
7214                     EncodingSize size,
7215                     Register rd,
7216                     Register rn,
7217                     const Operand& operand) {
7218  VIXL_ASSERT(AllowAssembler());
7219  CheckIT(cond);
7220  if (operand.IsImmediate()) {
7221    uint32_t imm = operand.GetImmediate();
7222    if (IsUsingT32()) {
7223      ImmediateT32 immediate_t32(imm);
7224      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7225      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc)) {
7226        EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7227                   (immediate_t32.GetEncodingValue() & 0xff) |
7228                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7229                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7230        AdvanceIT();
7231        return;
7232      }
7233    } else {
7234      ImmediateA32 immediate_a32(imm);
7235      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7236      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7237        EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7238                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7239                immediate_a32.GetEncodingValue());
7240        return;
7241      }
7242    }
7243  }
7244  if (operand.IsImmediateShiftedRegister()) {
7245    Register rm = operand.GetBaseRegister();
7246    if (operand.IsPlainRegister()) {
7247      if (IsUsingT32()) {
7248        // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7249        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7250            rm.IsLow()) {
7251          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7252          AdvanceIT();
7253          return;
7254        }
7255      }
7256    }
7257    Shift shift = operand.GetShift();
7258    uint32_t amount = operand.GetShiftAmount();
7259    if (IsUsingT32()) {
7260      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7261      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc)) {
7262        uint32_t amount_ = amount % 32;
7263        EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7264                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7265                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7266        AdvanceIT();
7267        return;
7268      }
7269    } else {
7270      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7271      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7272        uint32_t amount_ = amount % 32;
7273        EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7274                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7275                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7276        return;
7277      }
7278    }
7279  }
7280  if (operand.IsRegisterShiftedRegister()) {
7281    Register rm = operand.GetBaseRegister();
7282    Shift shift = operand.GetShift();
7283    if (IsUsingA32()) {
7284      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7285      if (cond.IsNotNever()) {
7286        EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7287                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7288                (shift.GetType() << 5) |
7289                (operand.GetShiftRegister().GetCode() << 8));
7290        return;
7291      }
7292    }
7293  }
7294  Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7295}
7296
7297void Assembler::pkhbt(Condition cond,
7298                      Register rd,
7299                      Register rn,
7300                      const Operand& operand) {
7301  VIXL_ASSERT(AllowAssembler());
7302  CheckIT(cond);
7303  if (operand.IsImmediateShiftedRegister()) {
7304    Register rm = operand.GetBaseRegister();
7305    Shift shift = operand.GetShift();
7306    uint32_t amount = operand.GetShiftAmount();
7307    if (IsUsingT32()) {
7308      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
7309      if (shift.IsLSL() && shift.IsValidAmount(amount)) {
7310        EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7311                   rm.GetCode() | ((amount & 0x3) << 6) |
7312                   ((amount & 0x1c) << 10));
7313        AdvanceIT();
7314        return;
7315      }
7316    } else {
7317      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
7318      if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever()) {
7319        EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7320                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7321                (amount << 7));
7322        return;
7323      }
7324    }
7325  }
7326  Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7327}
7328
7329void Assembler::pkhtb(Condition cond,
7330                      Register rd,
7331                      Register rn,
7332                      const Operand& operand) {
7333  VIXL_ASSERT(AllowAssembler());
7334  CheckIT(cond);
7335  if (operand.IsImmediateShiftedRegister()) {
7336    Register rm = operand.GetBaseRegister();
7337    Shift shift = operand.GetShift();
7338    uint32_t amount = operand.GetShiftAmount();
7339    if (IsUsingT32()) {
7340      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
7341      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount)) {
7342        uint32_t amount_ = amount % 32;
7343        EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7344                   rm.GetCode() | ((amount_ & 0x3) << 6) |
7345                   ((amount_ & 0x1c) << 10));
7346        AdvanceIT();
7347        return;
7348      }
7349    } else {
7350      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
7351      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7352          cond.IsNotNever()) {
7353        uint32_t amount_ = amount % 32;
7354        EmitA32(0x06800050U | (cond.GetCondition() << 28) |
7355                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7356                (amount_ << 7));
7357        return;
7358      }
7359    }
7360  }
7361  Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
7362}
7363
7364void Assembler::pld(Condition cond, Label* label) {
7365  VIXL_ASSERT(AllowAssembler());
7366  CheckIT(cond);
7367  Label::Offset offset =
7368      label->IsBound()
7369          ? label->GetLocation() -
7370                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
7371          : 0;
7372  if (IsUsingT32()) {
7373    // PLD{<c>}{<q>} <label> ; T1
7374    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7375         !label->IsBound())) {
7376      static class EmitOp : public Label::LabelEmitOperator {
7377       public:
7378        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7379        uint32_t Encode(uint32_t instr,
7380                        Label::Offset pc,
7381                        const Label* label) const {
7382          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7383          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7384          uint32_t U = (offset >= 0) && !label->IsMinusZero();
7385          int32_t target = abs(offset) | (U << 12);
7386          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7387        }
7388      } immop;
7389      EmitT32_32(Link(0xf81ff000U, label, immop));
7390      AdvanceIT();
7391      return;
7392    }
7393  } else {
7394    // PLD{<c>}{<q>} <label> ; A1
7395    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7396         !label->IsBound())) {
7397      if (cond.Is(al)) {
7398        static class EmitOp : public Label::LabelEmitOperator {
7399         public:
7400          EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7401          uint32_t Encode(uint32_t instr,
7402                          Label::Offset pc,
7403                          const Label* label) const {
7404            Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7405            VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7406            uint32_t U = (offset >= 0) && !label->IsMinusZero();
7407            int32_t target = abs(offset) | (U << 12);
7408            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7409          }
7410        } immop;
7411        EmitA32(Link(0xf55ff000U, label, immop));
7412        return;
7413      }
7414    }
7415  }
7416  Delegate(kPld, &Assembler::pld, cond, label);
7417}
7418
7419void Assembler::pld(Condition cond, const MemOperand& operand) {
7420  VIXL_ASSERT(AllowAssembler());
7421  CheckIT(cond);
7422  if (operand.IsImmediate()) {
7423    Register rn = operand.GetBaseRegister();
7424    int32_t offset = operand.GetOffsetImmediate();
7425    if (IsUsingT32()) {
7426      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
7427      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7428        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7429        uint32_t offset_ = abs(offset);
7430        EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
7431        AdvanceIT();
7432        return;
7433      }
7434    } else {
7435      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
7436      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7437        if (cond.Is(al)) {
7438          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7439          uint32_t offset_ = abs(offset);
7440          EmitA32(0xf55ff000U | offset_ | (sign << 23));
7441          return;
7442        }
7443      }
7444    }
7445  }
7446  if (operand.IsImmediate()) {
7447    Register rn = operand.GetBaseRegister();
7448    int32_t offset = operand.GetOffsetImmediate();
7449    if (IsUsingT32()) {
7450      // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7451      if ((offset >= 0) && (offset <= 4095) && ((rn.GetCode() & 0xf) != 0xf)) {
7452        EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7453        AdvanceIT();
7454        return;
7455      }
7456      // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7457      if ((-offset >= 0) && (-offset <= 255) && ((rn.GetCode() & 0xf) != 0xf)) {
7458        EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7459        AdvanceIT();
7460        return;
7461      }
7462    } else {
7463      // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
7464      if ((offset >= -4095) && (offset <= 4095) &&
7465          ((rn.GetCode() & 0xf) != 0xf)) {
7466        if (cond.Is(al)) {
7467          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7468          uint32_t offset_ = abs(offset);
7469          EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7470          return;
7471        }
7472      }
7473    }
7474  }
7475  if (operand.IsShiftedRegister()) {
7476    Register rn = operand.GetBaseRegister();
7477    Sign sign = operand.GetSign();
7478    Register rm = operand.GetOffsetRegister();
7479    Shift shift = operand.GetShift();
7480    uint32_t amount = operand.GetShiftAmount();
7481    if (IsUsingT32()) {
7482      // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7483      if (sign.IsPlus() && shift.IsLSL() && (operand.GetAddrMode() == Offset) &&
7484          ((rn.GetCode() & 0xf) != 0xf)) {
7485        EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
7486                   (amount << 4));
7487        AdvanceIT();
7488        return;
7489      }
7490    } else {
7491      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7492      if (!shift.IsRRX() && shift.IsValidAmount(amount) &&
7493          (operand.GetAddrMode() == Offset)) {
7494        if (cond.Is(al)) {
7495          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7496          uint32_t amount_ = amount % 32;
7497          EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
7498                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7499          return;
7500        }
7501      }
7502      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7503      if (shift.IsRRX() && (operand.GetAddrMode() == Offset)) {
7504        if (cond.Is(al)) {
7505          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7506          EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
7507                  (sign_ << 23));
7508          return;
7509        }
7510      }
7511    }
7512  }
7513  Delegate(kPld, &Assembler::pld, cond, operand);
7514}
7515
7516void Assembler::pldw(Condition cond, const MemOperand& operand) {
7517  VIXL_ASSERT(AllowAssembler());
7518  CheckIT(cond);
7519  if (operand.IsImmediate()) {
7520    Register rn = operand.GetBaseRegister();
7521    int32_t offset = operand.GetOffsetImmediate();
7522    if (IsUsingT32()) {
7523      // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7524      if ((offset >= 0) && (offset <= 4095) && ((rn.GetCode() & 0xf) != 0xf)) {
7525        EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7526        AdvanceIT();
7527        return;
7528      }
7529      // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7530      if ((-offset >= 0) && (-offset <= 255) && ((rn.GetCode() & 0xf) != 0xf)) {
7531        EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7532        AdvanceIT();
7533        return;
7534      }
7535    } else {
7536      // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
7537      if ((offset >= -4095) && (offset <= 4095) &&
7538          ((rn.GetCode() & 0xf) != 0xf)) {
7539        if (cond.Is(al)) {
7540          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7541          uint32_t offset_ = abs(offset);
7542          EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7543          return;
7544        }
7545      }
7546    }
7547  }
7548  if (operand.IsShiftedRegister()) {
7549    Register rn = operand.GetBaseRegister();
7550    Sign sign = operand.GetSign();
7551    Register rm = operand.GetOffsetRegister();
7552    Shift shift = operand.GetShift();
7553    uint32_t amount = operand.GetShiftAmount();
7554    if (IsUsingT32()) {
7555      // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7556      if (sign.IsPlus() && shift.IsLSL() && (operand.GetAddrMode() == Offset) &&
7557          ((rn.GetCode() & 0xf) != 0xf)) {
7558        EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
7559                   (amount << 4));
7560        AdvanceIT();
7561        return;
7562      }
7563    } else {
7564      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7565      if (!shift.IsRRX() && shift.IsValidAmount(amount) &&
7566          (operand.GetAddrMode() == Offset)) {
7567        if (cond.Is(al)) {
7568          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7569          uint32_t amount_ = amount % 32;
7570          EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
7571                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7572          return;
7573        }
7574      }
7575      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7576      if (shift.IsRRX() && (operand.GetAddrMode() == Offset)) {
7577        if (cond.Is(al)) {
7578          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7579          EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
7580                  (sign_ << 23));
7581          return;
7582        }
7583      }
7584    }
7585  }
7586  Delegate(kPldw, &Assembler::pldw, cond, operand);
7587}
7588
7589void Assembler::pli(Condition cond, const MemOperand& operand) {
7590  VIXL_ASSERT(AllowAssembler());
7591  CheckIT(cond);
7592  if (operand.IsImmediate()) {
7593    Register rn = operand.GetBaseRegister();
7594    int32_t offset = operand.GetOffsetImmediate();
7595    if (IsUsingT32()) {
7596      // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7597      if ((offset >= 0) && (offset <= 4095) && ((rn.GetCode() & 0xf) != 0xf)) {
7598        EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7599        AdvanceIT();
7600        return;
7601      }
7602      // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7603      if ((-offset >= 0) && (-offset <= 255) && ((rn.GetCode() & 0xf) != 0xf)) {
7604        EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7605        AdvanceIT();
7606        return;
7607      }
7608    } else {
7609      // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
7610      if ((offset >= -4095) && (offset <= 4095) &&
7611          ((rn.GetCode() & 0xf) != 0xf)) {
7612        if (cond.Is(al)) {
7613          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7614          uint32_t offset_ = abs(offset);
7615          EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7616          return;
7617        }
7618      }
7619    }
7620  }
7621  if (operand.IsImmediate()) {
7622    Register rn = operand.GetBaseRegister();
7623    int32_t offset = operand.GetOffsetImmediate();
7624    if (IsUsingT32()) {
7625      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
7626      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7627        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7628        uint32_t offset_ = abs(offset);
7629        EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
7630        AdvanceIT();
7631        return;
7632      }
7633    } else {
7634      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
7635      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7636        if (cond.Is(al)) {
7637          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7638          uint32_t offset_ = abs(offset);
7639          EmitA32(0xf45ff000U | offset_ | (sign << 23));
7640          return;
7641        }
7642      }
7643    }
7644  }
7645  if (operand.IsShiftedRegister()) {
7646    Register rn = operand.GetBaseRegister();
7647    Sign sign = operand.GetSign();
7648    Register rm = operand.GetOffsetRegister();
7649    Shift shift = operand.GetShift();
7650    uint32_t amount = operand.GetShiftAmount();
7651    if (IsUsingT32()) {
7652      // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7653      if (sign.IsPlus() && shift.IsLSL() && (operand.GetAddrMode() == Offset) &&
7654          ((rn.GetCode() & 0xf) != 0xf)) {
7655        EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
7656                   (amount << 4));
7657        AdvanceIT();
7658        return;
7659      }
7660    } else {
7661      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7662      if (shift.IsRRX() && (operand.GetAddrMode() == Offset)) {
7663        if (cond.Is(al)) {
7664          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7665          EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
7666                  (sign_ << 23));
7667          return;
7668        }
7669      }
7670      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7671      if (!shift.IsRRX() && shift.IsValidAmount(amount) &&
7672          (operand.GetAddrMode() == Offset)) {
7673        if (cond.Is(al)) {
7674          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7675          uint32_t amount_ = amount % 32;
7676          EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
7677                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7678          return;
7679        }
7680      }
7681    }
7682  }
7683  Delegate(kPli, &Assembler::pli, cond, operand);
7684}
7685
7686void Assembler::pli(Condition cond, Label* label) {
7687  VIXL_ASSERT(AllowAssembler());
7688  CheckIT(cond);
7689  Label::Offset offset =
7690      label->IsBound()
7691          ? label->GetLocation() -
7692                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
7693          : 0;
7694  if (IsUsingT32()) {
7695    // PLI{<c>}{<q>} <label> ; T3
7696    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7697         !label->IsBound())) {
7698      static class EmitOp : public Label::LabelEmitOperator {
7699       public:
7700        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7701        uint32_t Encode(uint32_t instr,
7702                        Label::Offset pc,
7703                        const Label* label) const {
7704          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7705          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7706          uint32_t U = (offset >= 0) && !label->IsMinusZero();
7707          int32_t target = abs(offset) | (U << 12);
7708          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7709        }
7710      } immop;
7711      EmitT32_32(Link(0xf91ff000U, label, immop));
7712      AdvanceIT();
7713      return;
7714    }
7715  } else {
7716    // PLI{<c>}{<q>} <label> ; A1
7717    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7718         !label->IsBound())) {
7719      if (cond.Is(al)) {
7720        static class EmitOp : public Label::LabelEmitOperator {
7721         public:
7722          EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7723          uint32_t Encode(uint32_t instr,
7724                          Label::Offset pc,
7725                          const Label* label) const {
7726            Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7727            VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7728            uint32_t U = (offset >= 0) && !label->IsMinusZero();
7729            int32_t target = abs(offset) | (U << 12);
7730            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7731          }
7732        } immop;
7733        EmitA32(Link(0xf45ff000U, label, immop));
7734        return;
7735      }
7736    }
7737  }
7738  Delegate(kPli, &Assembler::pli, cond, label);
7739}
7740
7741void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
7742  VIXL_ASSERT(AllowAssembler());
7743  CheckIT(cond);
7744  if (IsUsingT32()) {
7745    // POP{<c>}{<q>} <registers> ; T1
7746    if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
7747      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
7748                 GetRegisterListEncoding(registers, 0, 8));
7749      AdvanceIT();
7750      return;
7751    }
7752    // POP{<c>}{<q>} <registers> ; T2
7753    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
7754      EmitT32_32(0xe8bd0000U |
7755                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
7756                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
7757                 GetRegisterListEncoding(registers, 0, 13));
7758      AdvanceIT();
7759      return;
7760    }
7761  } else {
7762    // POP{<c>}{<q>} <registers> ; A1
7763    if (cond.IsNotNever()) {
7764      EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
7765              GetRegisterListEncoding(registers, 0, 16));
7766      return;
7767    }
7768  }
7769  Delegate(kPop, &Assembler::pop, cond, size, registers);
7770}
7771
7772void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
7773  VIXL_ASSERT(AllowAssembler());
7774  CheckIT(cond);
7775  if (IsUsingT32()) {
7776    // POP{<c>}{<q>} <single_register_list> ; T4
7777    if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) {
7778      EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
7779      AdvanceIT();
7780      return;
7781    }
7782  } else {
7783    // POP{<c>}{<q>} <single_register_list> ; A1
7784    if (cond.IsNotNever()) {
7785      EmitA32(0x049d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
7786      return;
7787    }
7788  }
7789  Delegate(kPop, &Assembler::pop, cond, size, rt);
7790}
7791
7792void Assembler::push(Condition cond,
7793                     EncodingSize size,
7794                     RegisterList registers) {
7795  VIXL_ASSERT(AllowAssembler());
7796  CheckIT(cond);
7797  if (IsUsingT32()) {
7798    // PUSH{<c>}{<q>} <registers> ; T1
7799    if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
7800      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
7801                 GetRegisterListEncoding(registers, 0, 8));
7802      AdvanceIT();
7803      return;
7804    }
7805    // PUSH{<c>}{<q>} <registers> ; T1
7806    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
7807      EmitT32_32(0xe92d0000U |
7808                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
7809                 GetRegisterListEncoding(registers, 0, 13));
7810      AdvanceIT();
7811      return;
7812    }
7813  } else {
7814    // PUSH{<c>}{<q>} <registers> ; A1
7815    if (cond.IsNotNever()) {
7816      EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
7817              GetRegisterListEncoding(registers, 0, 16));
7818      return;
7819    }
7820  }
7821  Delegate(kPush, &Assembler::push, cond, size, registers);
7822}
7823
7824void Assembler::push(Condition cond, EncodingSize size, Register rt) {
7825  VIXL_ASSERT(AllowAssembler());
7826  CheckIT(cond);
7827  if (IsUsingT32()) {
7828    // PUSH{<c>}{<q>} <single_register_list> ; T4
7829    if (!size.IsNarrow()) {
7830      EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
7831      AdvanceIT();
7832      return;
7833    }
7834  } else {
7835    // PUSH{<c>}{<q>} <single_register_list> ; A1
7836    if (cond.IsNotNever() && ((!rt.IsPC()) || AllowUnpredictable())) {
7837      EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
7838      return;
7839    }
7840  }
7841  Delegate(kPush, &Assembler::push, cond, size, rt);
7842}
7843
7844void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
7845  VIXL_ASSERT(AllowAssembler());
7846  CheckIT(cond);
7847  if (IsUsingT32()) {
7848    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7849    EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
7850               (rn.GetCode() << 16));
7851    AdvanceIT();
7852    return;
7853  } else {
7854    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7855    if (cond.IsNotNever()) {
7856      EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7857              rm.GetCode() | (rn.GetCode() << 16));
7858      return;
7859    }
7860  }
7861  Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
7862}
7863
7864void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
7865  VIXL_ASSERT(AllowAssembler());
7866  CheckIT(cond);
7867  if (IsUsingT32()) {
7868    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7869    EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7870               rm.GetCode());
7871    AdvanceIT();
7872    return;
7873  } else {
7874    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7875    if (cond.IsNotNever()) {
7876      EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7877              (rn.GetCode() << 16) | rm.GetCode());
7878      return;
7879    }
7880  }
7881  Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
7882}
7883
7884void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
7885  VIXL_ASSERT(AllowAssembler());
7886  CheckIT(cond);
7887  if (IsUsingT32()) {
7888    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7889    EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7890               rm.GetCode());
7891    AdvanceIT();
7892    return;
7893  } else {
7894    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7895    if (cond.IsNotNever()) {
7896      EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7897              (rn.GetCode() << 16) | rm.GetCode());
7898      return;
7899    }
7900  }
7901  Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
7902}
7903
7904void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
7905  VIXL_ASSERT(AllowAssembler());
7906  CheckIT(cond);
7907  if (IsUsingT32()) {
7908    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7909    EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7910               rm.GetCode());
7911    AdvanceIT();
7912    return;
7913  } else {
7914    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7915    if (cond.IsNotNever()) {
7916      EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7917              (rn.GetCode() << 16) | rm.GetCode());
7918      return;
7919    }
7920  }
7921  Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
7922}
7923
7924void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
7925  VIXL_ASSERT(AllowAssembler());
7926  CheckIT(cond);
7927  if (IsUsingT32()) {
7928    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7929    EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
7930               (rn.GetCode() << 16));
7931    AdvanceIT();
7932    return;
7933  } else {
7934    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7935    if (cond.IsNotNever()) {
7936      EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7937              rm.GetCode() | (rn.GetCode() << 16));
7938      return;
7939    }
7940  }
7941  Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
7942}
7943
7944void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
7945  VIXL_ASSERT(AllowAssembler());
7946  CheckIT(cond);
7947  if (IsUsingT32()) {
7948    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7949    EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
7950               (rn.GetCode() << 16));
7951    AdvanceIT();
7952    return;
7953  } else {
7954    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7955    if (cond.IsNotNever()) {
7956      EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7957              rm.GetCode() | (rn.GetCode() << 16));
7958      return;
7959    }
7960  }
7961  Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
7962}
7963
7964void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
7965  VIXL_ASSERT(AllowAssembler());
7966  CheckIT(cond);
7967  if (IsUsingT32()) {
7968    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7969    EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7970               rm.GetCode());
7971    AdvanceIT();
7972    return;
7973  } else {
7974    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7975    if (cond.IsNotNever()) {
7976      EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7977              (rn.GetCode() << 16) | rm.GetCode());
7978      return;
7979    }
7980  }
7981  Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
7982}
7983
7984void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
7985  VIXL_ASSERT(AllowAssembler());
7986  CheckIT(cond);
7987  if (IsUsingT32()) {
7988    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7989    EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
7990               (rn.GetCode() << 16));
7991    AdvanceIT();
7992    return;
7993  } else {
7994    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7995    if (cond.IsNotNever()) {
7996      EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7997              rm.GetCode() | (rn.GetCode() << 16));
7998      return;
7999    }
8000  }
8001  Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8002}
8003
8004void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
8005  VIXL_ASSERT(AllowAssembler());
8006  CheckIT(cond);
8007  if (IsUsingT32()) {
8008    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8009    EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8010               rm.GetCode());
8011    AdvanceIT();
8012    return;
8013  } else {
8014    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8015    if (cond.IsNotNever()) {
8016      EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8017              (rn.GetCode() << 16) | rm.GetCode());
8018      return;
8019    }
8020  }
8021  Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8022}
8023
8024void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
8025  VIXL_ASSERT(AllowAssembler());
8026  CheckIT(cond);
8027  if (IsUsingT32()) {
8028    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8029    EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8030               rm.GetCode());
8031    AdvanceIT();
8032    return;
8033  } else {
8034    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8035    if (cond.IsNotNever()) {
8036      EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8037              (rn.GetCode() << 16) | rm.GetCode());
8038      return;
8039    }
8040  }
8041  Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8042}
8043
8044void Assembler::rbit(Condition cond, Register rd, Register rm) {
8045  VIXL_ASSERT(AllowAssembler());
8046  CheckIT(cond);
8047  if (IsUsingT32()) {
8048    // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
8049    EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8050               (rm.GetCode() << 16));
8051    AdvanceIT();
8052    return;
8053  } else {
8054    // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
8055    if (cond.IsNotNever()) {
8056      EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8057              rm.GetCode());
8058      return;
8059    }
8060  }
8061  Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8062}
8063
8064void Assembler::rev(Condition cond,
8065                    EncodingSize size,
8066                    Register rd,
8067                    Register rm) {
8068  VIXL_ASSERT(AllowAssembler());
8069  CheckIT(cond);
8070  if (IsUsingT32()) {
8071    // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8072    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8073      EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8074      AdvanceIT();
8075      return;
8076    }
8077    // REV{<c>}{<q>} <Rd>, <Rm> ; T2
8078    if (!size.IsNarrow()) {
8079      EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8080                 (rm.GetCode() << 16));
8081      AdvanceIT();
8082      return;
8083    }
8084  } else {
8085    // REV{<c>}{<q>} <Rd>, <Rm> ; A1
8086    if (cond.IsNotNever()) {
8087      EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8088              rm.GetCode());
8089      return;
8090    }
8091  }
8092  Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8093}
8094
8095void Assembler::rev16(Condition cond,
8096                      EncodingSize size,
8097                      Register rd,
8098                      Register rm) {
8099  VIXL_ASSERT(AllowAssembler());
8100  CheckIT(cond);
8101  if (IsUsingT32()) {
8102    // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8103    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8104      EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8105      AdvanceIT();
8106      return;
8107    }
8108    // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
8109    if (!size.IsNarrow()) {
8110      EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8111                 (rm.GetCode() << 16));
8112      AdvanceIT();
8113      return;
8114    }
8115  } else {
8116    // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
8117    if (cond.IsNotNever()) {
8118      EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8119              rm.GetCode());
8120      return;
8121    }
8122  }
8123  Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8124}
8125
8126void Assembler::revsh(Condition cond,
8127                      EncodingSize size,
8128                      Register rd,
8129                      Register rm) {
8130  VIXL_ASSERT(AllowAssembler());
8131  CheckIT(cond);
8132  if (IsUsingT32()) {
8133    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8134    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8135      EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8136      AdvanceIT();
8137      return;
8138    }
8139    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
8140    if (!size.IsNarrow()) {
8141      EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8142                 (rm.GetCode() << 16));
8143      AdvanceIT();
8144      return;
8145    }
8146  } else {
8147    // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
8148    if (cond.IsNotNever()) {
8149      EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8150              rm.GetCode());
8151      return;
8152    }
8153  }
8154  Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8155}
8156
8157void Assembler::ror(Condition cond,
8158                    EncodingSize size,
8159                    Register rd,
8160                    Register rm,
8161                    const Operand& operand) {
8162  VIXL_ASSERT(AllowAssembler());
8163  CheckIT(cond);
8164  if (operand.IsImmediate()) {
8165    uint32_t imm = operand.GetImmediate();
8166    if (IsUsingT32()) {
8167      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8168      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
8169        EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8170                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8171        AdvanceIT();
8172        return;
8173      }
8174    } else {
8175      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8176      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8177        EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8178                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8179        return;
8180      }
8181    }
8182  }
8183  if (operand.IsPlainRegister()) {
8184    Register rs = operand.GetBaseRegister();
8185    if (IsUsingT32()) {
8186      // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8187      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8188          rs.IsLow()) {
8189        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8190        AdvanceIT();
8191        return;
8192      }
8193      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8194      if (!size.IsNarrow()) {
8195        EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8196                   rs.GetCode());
8197        AdvanceIT();
8198        return;
8199      }
8200    } else {
8201      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8202      if (cond.IsNotNever()) {
8203        EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
8204                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8205        return;
8206      }
8207    }
8208  }
8209  Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
8210}
8211
8212void Assembler::rors(Condition cond,
8213                     EncodingSize size,
8214                     Register rd,
8215                     Register rm,
8216                     const Operand& operand) {
8217  VIXL_ASSERT(AllowAssembler());
8218  CheckIT(cond);
8219  if (operand.IsImmediate()) {
8220    uint32_t imm = operand.GetImmediate();
8221    if (IsUsingT32()) {
8222      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8223      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
8224        EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8225                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8226        AdvanceIT();
8227        return;
8228      }
8229    } else {
8230      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8231      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8232        EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
8233                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8234        return;
8235      }
8236    }
8237  }
8238  if (operand.IsPlainRegister()) {
8239    Register rs = operand.GetBaseRegister();
8240    if (IsUsingT32()) {
8241      // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8242      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8243          rs.IsLow()) {
8244        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8245        AdvanceIT();
8246        return;
8247      }
8248      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8249      if (!size.IsNarrow()) {
8250        EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8251                   rs.GetCode());
8252        AdvanceIT();
8253        return;
8254      }
8255    } else {
8256      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8257      if (cond.IsNotNever()) {
8258        EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
8259                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8260        return;
8261      }
8262    }
8263  }
8264  Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
8265}
8266
8267void Assembler::rrx(Condition cond, Register rd, Register rm) {
8268  VIXL_ASSERT(AllowAssembler());
8269  CheckIT(cond);
8270  if (IsUsingT32()) {
8271    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
8272    EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
8273    AdvanceIT();
8274    return;
8275  } else {
8276    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
8277    if (cond.IsNotNever()) {
8278      EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8279              rm.GetCode());
8280      return;
8281    }
8282  }
8283  Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
8284}
8285
8286void Assembler::rrxs(Condition cond, Register rd, Register rm) {
8287  VIXL_ASSERT(AllowAssembler());
8288  CheckIT(cond);
8289  if (IsUsingT32()) {
8290    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
8291    EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
8292    AdvanceIT();
8293    return;
8294  } else {
8295    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
8296    if (cond.IsNotNever()) {
8297      EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8298              rm.GetCode());
8299      return;
8300    }
8301  }
8302  Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
8303}
8304
8305void Assembler::rsb(Condition cond,
8306                    EncodingSize size,
8307                    Register rd,
8308                    Register rn,
8309                    const Operand& operand) {
8310  VIXL_ASSERT(AllowAssembler());
8311  CheckIT(cond);
8312  if (operand.IsImmediate()) {
8313    uint32_t imm = operand.GetImmediate();
8314    if (IsUsingT32()) {
8315      ImmediateT32 immediate_t32(imm);
8316      // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
8317      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
8318          (imm == 0)) {
8319        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
8320        AdvanceIT();
8321        return;
8322      }
8323      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
8324      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8325        EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8326                   (immediate_t32.GetEncodingValue() & 0xff) |
8327                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8328                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8329        AdvanceIT();
8330        return;
8331      }
8332    } else {
8333      ImmediateA32 immediate_a32(imm);
8334      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8335      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8336        EmitA32(0x02600000U | (cond.GetCondition() << 28) |
8337                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8338                immediate_a32.GetEncodingValue());
8339        return;
8340      }
8341    }
8342  }
8343  if (operand.IsImmediateShiftedRegister()) {
8344    Register rm = operand.GetBaseRegister();
8345    Shift shift = operand.GetShift();
8346    uint32_t amount = operand.GetShiftAmount();
8347    if (IsUsingT32()) {
8348      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
8349      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8350        uint32_t amount_ = amount % 32;
8351        EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8352                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8353                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8354        AdvanceIT();
8355        return;
8356      }
8357    } else {
8358      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8359      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8360        uint32_t amount_ = amount % 32;
8361        EmitA32(0x00600000U | (cond.GetCondition() << 28) |
8362                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8363                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8364        return;
8365      }
8366    }
8367  }
8368  if (operand.IsRegisterShiftedRegister()) {
8369    Register rm = operand.GetBaseRegister();
8370    Shift shift = operand.GetShift();
8371    if (IsUsingA32()) {
8372      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8373      if (cond.IsNotNever()) {
8374        EmitA32(0x00600010U | (cond.GetCondition() << 28) |
8375                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8376                (shift.GetType() << 5) |
8377                (operand.GetShiftRegister().GetCode() << 8));
8378        return;
8379      }
8380    }
8381  }
8382  Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
8383}
8384
8385void Assembler::rsbs(Condition cond,
8386                     EncodingSize size,
8387                     Register rd,
8388                     Register rn,
8389                     const Operand& operand) {
8390  VIXL_ASSERT(AllowAssembler());
8391  CheckIT(cond);
8392  if (operand.IsImmediate()) {
8393    uint32_t imm = operand.GetImmediate();
8394    if (IsUsingT32()) {
8395      ImmediateT32 immediate_t32(imm);
8396      // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
8397      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
8398          (imm == 0)) {
8399        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
8400        AdvanceIT();
8401        return;
8402      }
8403      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
8404      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8405        EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8406                   (immediate_t32.GetEncodingValue() & 0xff) |
8407                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8408                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8409        AdvanceIT();
8410        return;
8411      }
8412    } else {
8413      ImmediateA32 immediate_a32(imm);
8414      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8415      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8416        EmitA32(0x02700000U | (cond.GetCondition() << 28) |
8417                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8418                immediate_a32.GetEncodingValue());
8419        return;
8420      }
8421    }
8422  }
8423  if (operand.IsImmediateShiftedRegister()) {
8424    Register rm = operand.GetBaseRegister();
8425    Shift shift = operand.GetShift();
8426    uint32_t amount = operand.GetShiftAmount();
8427    if (IsUsingT32()) {
8428      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
8429      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8430        uint32_t amount_ = amount % 32;
8431        EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8432                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8433                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8434        AdvanceIT();
8435        return;
8436      }
8437    } else {
8438      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8439      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8440        uint32_t amount_ = amount % 32;
8441        EmitA32(0x00700000U | (cond.GetCondition() << 28) |
8442                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8443                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8444        return;
8445      }
8446    }
8447  }
8448  if (operand.IsRegisterShiftedRegister()) {
8449    Register rm = operand.GetBaseRegister();
8450    Shift shift = operand.GetShift();
8451    if (IsUsingA32()) {
8452      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8453      if (cond.IsNotNever()) {
8454        EmitA32(0x00700010U | (cond.GetCondition() << 28) |
8455                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8456                (shift.GetType() << 5) |
8457                (operand.GetShiftRegister().GetCode() << 8));
8458        return;
8459      }
8460    }
8461  }
8462  Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
8463}
8464
8465void Assembler::rsc(Condition cond,
8466                    Register rd,
8467                    Register rn,
8468                    const Operand& operand) {
8469  VIXL_ASSERT(AllowAssembler());
8470  CheckIT(cond);
8471  if (operand.IsImmediate()) {
8472    uint32_t imm = operand.GetImmediate();
8473    if (IsUsingA32()) {
8474      ImmediateA32 immediate_a32(imm);
8475      // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8476      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8477        EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
8478                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8479                immediate_a32.GetEncodingValue());
8480        return;
8481      }
8482    }
8483  }
8484  if (operand.IsImmediateShiftedRegister()) {
8485    Register rm = operand.GetBaseRegister();
8486    Shift shift = operand.GetShift();
8487    uint32_t amount = operand.GetShiftAmount();
8488    if (IsUsingA32()) {
8489      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8490      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8491        uint32_t amount_ = amount % 32;
8492        EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
8493                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8494                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8495        return;
8496      }
8497    }
8498  }
8499  if (operand.IsRegisterShiftedRegister()) {
8500    Register rm = operand.GetBaseRegister();
8501    Shift shift = operand.GetShift();
8502    if (IsUsingA32()) {
8503      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8504      if (cond.IsNotNever()) {
8505        EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
8506                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8507                (shift.GetType() << 5) |
8508                (operand.GetShiftRegister().GetCode() << 8));
8509        return;
8510      }
8511    }
8512  }
8513  Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
8514}
8515
8516void Assembler::rscs(Condition cond,
8517                     Register rd,
8518                     Register rn,
8519                     const Operand& operand) {
8520  VIXL_ASSERT(AllowAssembler());
8521  CheckIT(cond);
8522  if (operand.IsImmediate()) {
8523    uint32_t imm = operand.GetImmediate();
8524    if (IsUsingA32()) {
8525      ImmediateA32 immediate_a32(imm);
8526      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8527      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8528        EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
8529                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8530                immediate_a32.GetEncodingValue());
8531        return;
8532      }
8533    }
8534  }
8535  if (operand.IsImmediateShiftedRegister()) {
8536    Register rm = operand.GetBaseRegister();
8537    Shift shift = operand.GetShift();
8538    uint32_t amount = operand.GetShiftAmount();
8539    if (IsUsingA32()) {
8540      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8541      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8542        uint32_t amount_ = amount % 32;
8543        EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
8544                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8545                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8546        return;
8547      }
8548    }
8549  }
8550  if (operand.IsRegisterShiftedRegister()) {
8551    Register rm = operand.GetBaseRegister();
8552    Shift shift = operand.GetShift();
8553    if (IsUsingA32()) {
8554      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8555      if (cond.IsNotNever()) {
8556        EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
8557                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8558                (shift.GetType() << 5) |
8559                (operand.GetShiftRegister().GetCode() << 8));
8560        return;
8561      }
8562    }
8563  }
8564  Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
8565}
8566
8567void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
8568  VIXL_ASSERT(AllowAssembler());
8569  CheckIT(cond);
8570  if (IsUsingT32()) {
8571    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8572    EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8573               rm.GetCode());
8574    AdvanceIT();
8575    return;
8576  } else {
8577    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8578    if (cond.IsNotNever()) {
8579      EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8580              (rn.GetCode() << 16) | rm.GetCode());
8581      return;
8582    }
8583  }
8584  Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
8585}
8586
8587void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
8588  VIXL_ASSERT(AllowAssembler());
8589  CheckIT(cond);
8590  if (IsUsingT32()) {
8591    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8592    EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8593               rm.GetCode());
8594    AdvanceIT();
8595    return;
8596  } else {
8597    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8598    if (cond.IsNotNever()) {
8599      EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8600              (rn.GetCode() << 16) | rm.GetCode());
8601      return;
8602    }
8603  }
8604  Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
8605}
8606
8607void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
8608  VIXL_ASSERT(AllowAssembler());
8609  CheckIT(cond);
8610  if (IsUsingT32()) {
8611    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8612    EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8613               rm.GetCode());
8614    AdvanceIT();
8615    return;
8616  } else {
8617    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8618    if (cond.IsNotNever()) {
8619      EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8620              (rn.GetCode() << 16) | rm.GetCode());
8621      return;
8622    }
8623  }
8624  Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
8625}
8626
8627void Assembler::sbc(Condition cond,
8628                    EncodingSize size,
8629                    Register rd,
8630                    Register rn,
8631                    const Operand& operand) {
8632  VIXL_ASSERT(AllowAssembler());
8633  CheckIT(cond);
8634  if (operand.IsImmediate()) {
8635    uint32_t imm = operand.GetImmediate();
8636    if (IsUsingT32()) {
8637      ImmediateT32 immediate_t32(imm);
8638      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
8639      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8640        EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8641                   (immediate_t32.GetEncodingValue() & 0xff) |
8642                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8643                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8644        AdvanceIT();
8645        return;
8646      }
8647    } else {
8648      ImmediateA32 immediate_a32(imm);
8649      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8650      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8651        EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
8652                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8653                immediate_a32.GetEncodingValue());
8654        return;
8655      }
8656    }
8657  }
8658  if (operand.IsImmediateShiftedRegister()) {
8659    Register rm = operand.GetBaseRegister();
8660    if (operand.IsPlainRegister()) {
8661      if (IsUsingT32()) {
8662        // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
8663        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
8664            rm.IsLow()) {
8665          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
8666          AdvanceIT();
8667          return;
8668        }
8669      }
8670    }
8671    Shift shift = operand.GetShift();
8672    uint32_t amount = operand.GetShiftAmount();
8673    if (IsUsingT32()) {
8674      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
8675      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8676        uint32_t amount_ = amount % 32;
8677        EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8678                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8679                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8680        AdvanceIT();
8681        return;
8682      }
8683    } else {
8684      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8685      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8686        uint32_t amount_ = amount % 32;
8687        EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
8688                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8689                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8690        return;
8691      }
8692    }
8693  }
8694  if (operand.IsRegisterShiftedRegister()) {
8695    Register rm = operand.GetBaseRegister();
8696    Shift shift = operand.GetShift();
8697    if (IsUsingA32()) {
8698      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8699      if (cond.IsNotNever()) {
8700        EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
8701                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8702                (shift.GetType() << 5) |
8703                (operand.GetShiftRegister().GetCode() << 8));
8704        return;
8705      }
8706    }
8707  }
8708  Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
8709}
8710
8711void Assembler::sbcs(Condition cond,
8712                     EncodingSize size,
8713                     Register rd,
8714                     Register rn,
8715                     const Operand& operand) {
8716  VIXL_ASSERT(AllowAssembler());
8717  CheckIT(cond);
8718  if (operand.IsImmediate()) {
8719    uint32_t imm = operand.GetImmediate();
8720    if (IsUsingT32()) {
8721      ImmediateT32 immediate_t32(imm);
8722      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
8723      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8724        EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8725                   (immediate_t32.GetEncodingValue() & 0xff) |
8726                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8727                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8728        AdvanceIT();
8729        return;
8730      }
8731    } else {
8732      ImmediateA32 immediate_a32(imm);
8733      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8734      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8735        EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
8736                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8737                immediate_a32.GetEncodingValue());
8738        return;
8739      }
8740    }
8741  }
8742  if (operand.IsImmediateShiftedRegister()) {
8743    Register rm = operand.GetBaseRegister();
8744    if (operand.IsPlainRegister()) {
8745      if (IsUsingT32()) {
8746        // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
8747        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
8748            rm.IsLow()) {
8749          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
8750          AdvanceIT();
8751          return;
8752        }
8753      }
8754    }
8755    Shift shift = operand.GetShift();
8756    uint32_t amount = operand.GetShiftAmount();
8757    if (IsUsingT32()) {
8758      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
8759      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8760        uint32_t amount_ = amount % 32;
8761        EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8762                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8763                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8764        AdvanceIT();
8765        return;
8766      }
8767    } else {
8768      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8769      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8770        uint32_t amount_ = amount % 32;
8771        EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
8772                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8773                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8774        return;
8775      }
8776    }
8777  }
8778  if (operand.IsRegisterShiftedRegister()) {
8779    Register rm = operand.GetBaseRegister();
8780    Shift shift = operand.GetShift();
8781    if (IsUsingA32()) {
8782      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8783      if (cond.IsNotNever()) {
8784        EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
8785                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8786                (shift.GetType() << 5) |
8787                (operand.GetShiftRegister().GetCode() << 8));
8788        return;
8789      }
8790    }
8791  }
8792  Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
8793}
8794
8795void Assembler::sbfx(Condition cond,
8796                     Register rd,
8797                     Register rn,
8798                     uint32_t lsb,
8799                     const Operand& operand) {
8800  VIXL_ASSERT(AllowAssembler());
8801  CheckIT(cond);
8802  if (operand.IsImmediate()) {
8803    uint32_t width = operand.GetImmediate();
8804    if (IsUsingT32()) {
8805      // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
8806      if ((lsb <= 31) &&
8807          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
8808        uint32_t widthm1 = width - 1;
8809        EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8810                   ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
8811        AdvanceIT();
8812        return;
8813      }
8814    } else {
8815      // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
8816      if ((lsb <= 31) && cond.IsNotNever() &&
8817          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
8818        uint32_t widthm1 = width - 1;
8819        EmitA32(0x07a00050U | (cond.GetCondition() << 28) |
8820                (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) |
8821                (widthm1 << 16));
8822        return;
8823      }
8824    }
8825  }
8826  Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, operand);
8827}
8828
8829void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
8830  VIXL_ASSERT(AllowAssembler());
8831  CheckIT(cond);
8832  if (IsUsingT32()) {
8833    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8834    EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8835               rm.GetCode());
8836    AdvanceIT();
8837    return;
8838  } else {
8839    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8840    if (cond.IsNotNever()) {
8841      EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
8842              rn.GetCode() | (rm.GetCode() << 8));
8843      return;
8844    }
8845  }
8846  Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
8847}
8848
8849void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
8850  VIXL_ASSERT(AllowAssembler());
8851  CheckIT(cond);
8852  if (IsUsingT32()) {
8853    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8854    EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8855               rm.GetCode());
8856    AdvanceIT();
8857    return;
8858  } else {
8859    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8860    if (cond.IsNotNever()) {
8861      EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8862              (rn.GetCode() << 16) | rm.GetCode());
8863      return;
8864    }
8865  }
8866  Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
8867}
8868
8869void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
8870  VIXL_ASSERT(AllowAssembler());
8871  CheckIT(cond);
8872  if (IsUsingT32()) {
8873    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8874    EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8875               rm.GetCode());
8876    AdvanceIT();
8877    return;
8878  } else {
8879    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8880    if (cond.IsNotNever()) {
8881      EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8882              (rn.GetCode() << 16) | rm.GetCode());
8883      return;
8884    }
8885  }
8886  Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
8887}
8888
8889void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
8890  VIXL_ASSERT(AllowAssembler());
8891  CheckIT(cond);
8892  if (IsUsingT32()) {
8893    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8894    EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8895               rm.GetCode());
8896    AdvanceIT();
8897    return;
8898  } else {
8899    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8900    if (cond.IsNotNever()) {
8901      EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8902              (rn.GetCode() << 16) | rm.GetCode());
8903      return;
8904    }
8905  }
8906  Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
8907}
8908
8909void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
8910  VIXL_ASSERT(AllowAssembler());
8911  CheckIT(cond);
8912  if (IsUsingT32()) {
8913    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8914    EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8915               rm.GetCode());
8916    AdvanceIT();
8917    return;
8918  } else {
8919    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8920    if (cond.IsNotNever()) {
8921      EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8922              (rn.GetCode() << 16) | rm.GetCode());
8923      return;
8924    }
8925  }
8926  Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
8927}
8928
8929void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
8930  VIXL_ASSERT(AllowAssembler());
8931  CheckIT(cond);
8932  if (IsUsingT32()) {
8933    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8934    EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8935               rm.GetCode());
8936    AdvanceIT();
8937    return;
8938  } else {
8939    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8940    if (cond.IsNotNever()) {
8941      EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8942              (rn.GetCode() << 16) | rm.GetCode());
8943      return;
8944    }
8945  }
8946  Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
8947}
8948
8949void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
8950  VIXL_ASSERT(AllowAssembler());
8951  CheckIT(cond);
8952  if (IsUsingT32()) {
8953    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8954    EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8955               rm.GetCode());
8956    AdvanceIT();
8957    return;
8958  } else {
8959    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8960    if (cond.IsNotNever()) {
8961      EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8962              (rn.GetCode() << 16) | rm.GetCode());
8963      return;
8964    }
8965  }
8966  Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
8967}
8968
8969void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
8970  VIXL_ASSERT(AllowAssembler());
8971  CheckIT(cond);
8972  if (IsUsingT32()) {
8973    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8974    EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8975               rm.GetCode());
8976    AdvanceIT();
8977    return;
8978  } else {
8979    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8980    if (cond.IsNotNever()) {
8981      EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8982              (rn.GetCode() << 16) | rm.GetCode());
8983      return;
8984    }
8985  }
8986  Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
8987}
8988
8989void Assembler::smlabb(
8990    Condition cond, Register rd, Register rn, Register rm, Register ra) {
8991  VIXL_ASSERT(AllowAssembler());
8992  CheckIT(cond);
8993  if (IsUsingT32()) {
8994    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
8995    if (!ra.Is(pc)) {
8996      EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8997                 rm.GetCode() | (ra.GetCode() << 12));
8998      AdvanceIT();
8999      return;
9000    }
9001  } else {
9002    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9003    if (cond.IsNotNever()) {
9004      EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9005              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9006      return;
9007    }
9008  }
9009  Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9010}
9011
9012void Assembler::smlabt(
9013    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9014  VIXL_ASSERT(AllowAssembler());
9015  CheckIT(cond);
9016  if (IsUsingT32()) {
9017    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9018    if (!ra.Is(pc)) {
9019      EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9020                 rm.GetCode() | (ra.GetCode() << 12));
9021      AdvanceIT();
9022      return;
9023    }
9024  } else {
9025    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9026    if (cond.IsNotNever()) {
9027      EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9028              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9029      return;
9030    }
9031  }
9032  Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9033}
9034
9035void Assembler::smlad(
9036    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9037  VIXL_ASSERT(AllowAssembler());
9038  CheckIT(cond);
9039  if (IsUsingT32()) {
9040    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9041    if (!ra.Is(pc)) {
9042      EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9043                 rm.GetCode() | (ra.GetCode() << 12));
9044      AdvanceIT();
9045      return;
9046    }
9047  } else {
9048    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9049    if (cond.IsNotNever() && !ra.Is(pc)) {
9050      EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9051              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9052      return;
9053    }
9054  }
9055  Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9056}
9057
9058void Assembler::smladx(
9059    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9060  VIXL_ASSERT(AllowAssembler());
9061  CheckIT(cond);
9062  if (IsUsingT32()) {
9063    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9064    if (!ra.Is(pc)) {
9065      EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9066                 rm.GetCode() | (ra.GetCode() << 12));
9067      AdvanceIT();
9068      return;
9069    }
9070  } else {
9071    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9072    if (cond.IsNotNever() && !ra.Is(pc)) {
9073      EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9074              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9075      return;
9076    }
9077  }
9078  Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9079}
9080
9081void Assembler::smlal(
9082    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9083  VIXL_ASSERT(AllowAssembler());
9084  CheckIT(cond);
9085  if (IsUsingT32()) {
9086    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9087    EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9088               (rn.GetCode() << 16) | rm.GetCode());
9089    AdvanceIT();
9090    return;
9091  } else {
9092    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9093    if (cond.IsNotNever()) {
9094      EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9095              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9096              (rm.GetCode() << 8));
9097      return;
9098    }
9099  }
9100  Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9101}
9102
9103void Assembler::smlalbb(
9104    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9105  VIXL_ASSERT(AllowAssembler());
9106  CheckIT(cond);
9107  if (IsUsingT32()) {
9108    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9109    EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9110               (rn.GetCode() << 16) | rm.GetCode());
9111    AdvanceIT();
9112    return;
9113  } else {
9114    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9115    if (cond.IsNotNever()) {
9116      EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9117              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9118              (rm.GetCode() << 8));
9119      return;
9120    }
9121  }
9122  Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9123}
9124
9125void Assembler::smlalbt(
9126    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9127  VIXL_ASSERT(AllowAssembler());
9128  CheckIT(cond);
9129  if (IsUsingT32()) {
9130    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9131    EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9132               (rn.GetCode() << 16) | rm.GetCode());
9133    AdvanceIT();
9134    return;
9135  } else {
9136    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9137    if (cond.IsNotNever()) {
9138      EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
9139              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9140              (rm.GetCode() << 8));
9141      return;
9142    }
9143  }
9144  Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
9145}
9146
9147void Assembler::smlald(
9148    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9149  VIXL_ASSERT(AllowAssembler());
9150  CheckIT(cond);
9151  if (IsUsingT32()) {
9152    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9153    EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9154               (rn.GetCode() << 16) | rm.GetCode());
9155    AdvanceIT();
9156    return;
9157  } else {
9158    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9159    if (cond.IsNotNever()) {
9160      EmitA32(0x07400010U | (cond.GetCondition() << 28) |
9161              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9162              (rm.GetCode() << 8));
9163      return;
9164    }
9165  }
9166  Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
9167}
9168
9169void Assembler::smlaldx(
9170    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9171  VIXL_ASSERT(AllowAssembler());
9172  CheckIT(cond);
9173  if (IsUsingT32()) {
9174    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9175    EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9176               (rn.GetCode() << 16) | rm.GetCode());
9177    AdvanceIT();
9178    return;
9179  } else {
9180    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9181    if (cond.IsNotNever()) {
9182      EmitA32(0x07400030U | (cond.GetCondition() << 28) |
9183              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9184              (rm.GetCode() << 8));
9185      return;
9186    }
9187  }
9188  Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
9189}
9190
9191void Assembler::smlals(
9192    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9193  VIXL_ASSERT(AllowAssembler());
9194  CheckIT(cond);
9195  if (IsUsingA32()) {
9196    // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9197    if (cond.IsNotNever()) {
9198      EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
9199              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9200              (rm.GetCode() << 8));
9201      return;
9202    }
9203  }
9204  Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
9205}
9206
9207void Assembler::smlaltb(
9208    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9209  VIXL_ASSERT(AllowAssembler());
9210  CheckIT(cond);
9211  if (IsUsingT32()) {
9212    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9213    EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9214               (rn.GetCode() << 16) | rm.GetCode());
9215    AdvanceIT();
9216    return;
9217  } else {
9218    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9219    if (cond.IsNotNever()) {
9220      EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
9221              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9222              (rm.GetCode() << 8));
9223      return;
9224    }
9225  }
9226  Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
9227}
9228
9229void Assembler::smlaltt(
9230    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9231  VIXL_ASSERT(AllowAssembler());
9232  CheckIT(cond);
9233  if (IsUsingT32()) {
9234    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9235    EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9236               (rn.GetCode() << 16) | rm.GetCode());
9237    AdvanceIT();
9238    return;
9239  } else {
9240    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9241    if (cond.IsNotNever()) {
9242      EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
9243              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9244              (rm.GetCode() << 8));
9245      return;
9246    }
9247  }
9248  Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
9249}
9250
9251void Assembler::smlatb(
9252    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9253  VIXL_ASSERT(AllowAssembler());
9254  CheckIT(cond);
9255  if (IsUsingT32()) {
9256    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9257    if (!ra.Is(pc)) {
9258      EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9259                 rm.GetCode() | (ra.GetCode() << 12));
9260      AdvanceIT();
9261      return;
9262    }
9263  } else {
9264    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9265    if (cond.IsNotNever()) {
9266      EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9267              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9268      return;
9269    }
9270  }
9271  Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
9272}
9273
9274void Assembler::smlatt(
9275    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9276  VIXL_ASSERT(AllowAssembler());
9277  CheckIT(cond);
9278  if (IsUsingT32()) {
9279    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9280    if (!ra.Is(pc)) {
9281      EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9282                 rm.GetCode() | (ra.GetCode() << 12));
9283      AdvanceIT();
9284      return;
9285    }
9286  } else {
9287    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9288    if (cond.IsNotNever()) {
9289      EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9290              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9291      return;
9292    }
9293  }
9294  Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
9295}
9296
9297void Assembler::smlawb(
9298    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9299  VIXL_ASSERT(AllowAssembler());
9300  CheckIT(cond);
9301  if (IsUsingT32()) {
9302    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9303    if (!ra.Is(pc)) {
9304      EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9305                 rm.GetCode() | (ra.GetCode() << 12));
9306      AdvanceIT();
9307      return;
9308    }
9309  } else {
9310    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9311    if (cond.IsNotNever()) {
9312      EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9313              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9314      return;
9315    }
9316  }
9317  Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
9318}
9319
9320void Assembler::smlawt(
9321    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9322  VIXL_ASSERT(AllowAssembler());
9323  CheckIT(cond);
9324  if (IsUsingT32()) {
9325    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9326    if (!ra.Is(pc)) {
9327      EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9328                 rm.GetCode() | (ra.GetCode() << 12));
9329      AdvanceIT();
9330      return;
9331    }
9332  } else {
9333    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9334    if (cond.IsNotNever()) {
9335      EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9336              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9337      return;
9338    }
9339  }
9340  Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
9341}
9342
9343void Assembler::smlsd(
9344    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9345  VIXL_ASSERT(AllowAssembler());
9346  CheckIT(cond);
9347  if (IsUsingT32()) {
9348    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9349    if (!ra.Is(pc)) {
9350      EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9351                 rm.GetCode() | (ra.GetCode() << 12));
9352      AdvanceIT();
9353      return;
9354    }
9355  } else {
9356    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9357    if (cond.IsNotNever() && !ra.Is(pc)) {
9358      EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9359              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9360      return;
9361    }
9362  }
9363  Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
9364}
9365
9366void Assembler::smlsdx(
9367    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9368  VIXL_ASSERT(AllowAssembler());
9369  CheckIT(cond);
9370  if (IsUsingT32()) {
9371    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9372    if (!ra.Is(pc)) {
9373      EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9374                 rm.GetCode() | (ra.GetCode() << 12));
9375      AdvanceIT();
9376      return;
9377    }
9378  } else {
9379    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9380    if (cond.IsNotNever() && !ra.Is(pc)) {
9381      EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9382              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9383      return;
9384    }
9385  }
9386  Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
9387}
9388
9389void Assembler::smlsld(
9390    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9391  VIXL_ASSERT(AllowAssembler());
9392  CheckIT(cond);
9393  if (IsUsingT32()) {
9394    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9395    EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9396               (rn.GetCode() << 16) | rm.GetCode());
9397    AdvanceIT();
9398    return;
9399  } else {
9400    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9401    if (cond.IsNotNever()) {
9402      EmitA32(0x07400050U | (cond.GetCondition() << 28) |
9403              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9404              (rm.GetCode() << 8));
9405      return;
9406    }
9407  }
9408  Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
9409}
9410
9411void Assembler::smlsldx(
9412    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9413  VIXL_ASSERT(AllowAssembler());
9414  CheckIT(cond);
9415  if (IsUsingT32()) {
9416    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9417    EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9418               (rn.GetCode() << 16) | rm.GetCode());
9419    AdvanceIT();
9420    return;
9421  } else {
9422    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9423    if (cond.IsNotNever()) {
9424      EmitA32(0x07400070U | (cond.GetCondition() << 28) |
9425              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9426              (rm.GetCode() << 8));
9427      return;
9428    }
9429  }
9430  Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
9431}
9432
9433void Assembler::smmla(
9434    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9435  VIXL_ASSERT(AllowAssembler());
9436  CheckIT(cond);
9437  if (IsUsingT32()) {
9438    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9439    if (!ra.Is(pc)) {
9440      EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9441                 rm.GetCode() | (ra.GetCode() << 12));
9442      AdvanceIT();
9443      return;
9444    }
9445  } else {
9446    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9447    if (cond.IsNotNever() && !ra.Is(pc)) {
9448      EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9449              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9450      return;
9451    }
9452  }
9453  Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
9454}
9455
9456void Assembler::smmlar(
9457    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9458  VIXL_ASSERT(AllowAssembler());
9459  CheckIT(cond);
9460  if (IsUsingT32()) {
9461    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9462    if (!ra.Is(pc)) {
9463      EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9464                 rm.GetCode() | (ra.GetCode() << 12));
9465      AdvanceIT();
9466      return;
9467    }
9468  } else {
9469    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9470    if (cond.IsNotNever() && !ra.Is(pc)) {
9471      EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9472              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9473      return;
9474    }
9475  }
9476  Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
9477}
9478
9479void Assembler::smmls(
9480    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9481  VIXL_ASSERT(AllowAssembler());
9482  CheckIT(cond);
9483  if (IsUsingT32()) {
9484    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9485    EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9486               rm.GetCode() | (ra.GetCode() << 12));
9487    AdvanceIT();
9488    return;
9489  } else {
9490    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9491    if (cond.IsNotNever()) {
9492      EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9493              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9494      return;
9495    }
9496  }
9497  Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
9498}
9499
9500void Assembler::smmlsr(
9501    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9502  VIXL_ASSERT(AllowAssembler());
9503  CheckIT(cond);
9504  if (IsUsingT32()) {
9505    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9506    EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9507               rm.GetCode() | (ra.GetCode() << 12));
9508    AdvanceIT();
9509    return;
9510  } else {
9511    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9512    if (cond.IsNotNever()) {
9513      EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9514              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9515      return;
9516    }
9517  }
9518  Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
9519}
9520
9521void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
9522  VIXL_ASSERT(AllowAssembler());
9523  CheckIT(cond);
9524  if (IsUsingT32()) {
9525    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9526    EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9527               rm.GetCode());
9528    AdvanceIT();
9529    return;
9530  } else {
9531    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9532    if (cond.IsNotNever()) {
9533      EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9534              rn.GetCode() | (rm.GetCode() << 8));
9535      return;
9536    }
9537  }
9538  Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
9539}
9540
9541void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
9542  VIXL_ASSERT(AllowAssembler());
9543  CheckIT(cond);
9544  if (IsUsingT32()) {
9545    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9546    EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9547               rm.GetCode());
9548    AdvanceIT();
9549    return;
9550  } else {
9551    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9552    if (cond.IsNotNever()) {
9553      EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9554              rn.GetCode() | (rm.GetCode() << 8));
9555      return;
9556    }
9557  }
9558  Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
9559}
9560
9561void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
9562  VIXL_ASSERT(AllowAssembler());
9563  CheckIT(cond);
9564  if (IsUsingT32()) {
9565    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9566    EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9567               rm.GetCode());
9568    AdvanceIT();
9569    return;
9570  } else {
9571    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9572    if (cond.IsNotNever()) {
9573      EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9574              rn.GetCode() | (rm.GetCode() << 8));
9575      return;
9576    }
9577  }
9578  Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
9579}
9580
9581void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
9582  VIXL_ASSERT(AllowAssembler());
9583  CheckIT(cond);
9584  if (IsUsingT32()) {
9585    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9586    EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9587               rm.GetCode());
9588    AdvanceIT();
9589    return;
9590  } else {
9591    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9592    if (cond.IsNotNever()) {
9593      EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9594              rn.GetCode() | (rm.GetCode() << 8));
9595      return;
9596    }
9597  }
9598  Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
9599}
9600
9601void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
9602  VIXL_ASSERT(AllowAssembler());
9603  CheckIT(cond);
9604  if (IsUsingT32()) {
9605    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9606    EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9607               rm.GetCode());
9608    AdvanceIT();
9609    return;
9610  } else {
9611    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9612    if (cond.IsNotNever()) {
9613      EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9614              rn.GetCode() | (rm.GetCode() << 8));
9615      return;
9616    }
9617  }
9618  Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
9619}
9620
9621void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
9622  VIXL_ASSERT(AllowAssembler());
9623  CheckIT(cond);
9624  if (IsUsingT32()) {
9625    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9626    EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9627               rm.GetCode());
9628    AdvanceIT();
9629    return;
9630  } else {
9631    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9632    if (cond.IsNotNever()) {
9633      EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9634              rn.GetCode() | (rm.GetCode() << 8));
9635      return;
9636    }
9637  }
9638  Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
9639}
9640
9641void Assembler::smull(
9642    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9643  VIXL_ASSERT(AllowAssembler());
9644  CheckIT(cond);
9645  if (IsUsingT32()) {
9646    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9647    EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9648               (rn.GetCode() << 16) | rm.GetCode());
9649    AdvanceIT();
9650    return;
9651  } else {
9652    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9653    if (cond.IsNotNever()) {
9654      EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
9655              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9656              (rm.GetCode() << 8));
9657      return;
9658    }
9659  }
9660  Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
9661}
9662
9663void Assembler::smulls(
9664    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9665  VIXL_ASSERT(AllowAssembler());
9666  CheckIT(cond);
9667  if (IsUsingA32()) {
9668    // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9669    if (cond.IsNotNever()) {
9670      EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
9671              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9672              (rm.GetCode() << 8));
9673      return;
9674    }
9675  }
9676  Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
9677}
9678
9679void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
9680  VIXL_ASSERT(AllowAssembler());
9681  CheckIT(cond);
9682  if (IsUsingT32()) {
9683    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9684    EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9685               rm.GetCode());
9686    AdvanceIT();
9687    return;
9688  } else {
9689    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9690    if (cond.IsNotNever()) {
9691      EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9692              rn.GetCode() | (rm.GetCode() << 8));
9693      return;
9694    }
9695  }
9696  Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
9697}
9698
9699void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
9700  VIXL_ASSERT(AllowAssembler());
9701  CheckIT(cond);
9702  if (IsUsingT32()) {
9703    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9704    EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9705               rm.GetCode());
9706    AdvanceIT();
9707    return;
9708  } else {
9709    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9710    if (cond.IsNotNever()) {
9711      EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9712              rn.GetCode() | (rm.GetCode() << 8));
9713      return;
9714    }
9715  }
9716  Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
9717}
9718
9719void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
9720  VIXL_ASSERT(AllowAssembler());
9721  CheckIT(cond);
9722  if (IsUsingT32()) {
9723    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9724    EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9725               rm.GetCode());
9726    AdvanceIT();
9727    return;
9728  } else {
9729    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9730    if (cond.IsNotNever()) {
9731      EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9732              rn.GetCode() | (rm.GetCode() << 8));
9733      return;
9734    }
9735  }
9736  Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
9737}
9738
9739void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
9740  VIXL_ASSERT(AllowAssembler());
9741  CheckIT(cond);
9742  if (IsUsingT32()) {
9743    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9744    EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9745               rm.GetCode());
9746    AdvanceIT();
9747    return;
9748  } else {
9749    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9750    if (cond.IsNotNever()) {
9751      EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9752              rn.GetCode() | (rm.GetCode() << 8));
9753      return;
9754    }
9755  }
9756  Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
9757}
9758
9759void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
9760  VIXL_ASSERT(AllowAssembler());
9761  CheckIT(cond);
9762  if (IsUsingT32()) {
9763    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9764    EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9765               rm.GetCode());
9766    AdvanceIT();
9767    return;
9768  } else {
9769    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9770    if (cond.IsNotNever()) {
9771      EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9772              rn.GetCode() | (rm.GetCode() << 8));
9773      return;
9774    }
9775  }
9776  Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
9777}
9778
9779void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
9780  VIXL_ASSERT(AllowAssembler());
9781  CheckIT(cond);
9782  if (IsUsingT32()) {
9783    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9784    EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9785               rm.GetCode());
9786    AdvanceIT();
9787    return;
9788  } else {
9789    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9790    if (cond.IsNotNever()) {
9791      EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9792              rn.GetCode() | (rm.GetCode() << 8));
9793      return;
9794    }
9795  }
9796  Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
9797}
9798
9799void Assembler::ssat(Condition cond,
9800                     Register rd,
9801                     uint32_t imm,
9802                     const Operand& operand) {
9803  VIXL_ASSERT(AllowAssembler());
9804  CheckIT(cond);
9805  if (operand.IsImmediateShiftedRegister()) {
9806    Register rn = operand.GetBaseRegister();
9807    Shift shift = operand.GetShift();
9808    uint32_t amount = operand.GetShiftAmount();
9809    if (IsUsingT32()) {
9810      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
9811      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
9812          (amount <= 31)) {
9813        uint32_t imm_ = imm - 1;
9814        EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
9815                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
9816                   ((amount & 0x1c) << 10));
9817        AdvanceIT();
9818        return;
9819      }
9820      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
9821      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31)) {
9822        uint32_t imm_ = imm - 1;
9823        EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
9824                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
9825                   ((amount & 0x1c) << 10));
9826        AdvanceIT();
9827        return;
9828      }
9829    } else {
9830      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
9831      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
9832          (amount <= 32) && cond.IsNotNever()) {
9833        uint32_t imm_ = imm - 1;
9834        uint32_t amount_ = amount % 32;
9835        EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
9836                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
9837                (amount_ << 7));
9838        return;
9839      }
9840      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
9841      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
9842          cond.IsNotNever()) {
9843        uint32_t imm_ = imm - 1;
9844        EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
9845                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
9846                (amount << 7));
9847        return;
9848      }
9849    }
9850  }
9851  Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
9852}
9853
9854void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
9855  VIXL_ASSERT(AllowAssembler());
9856  CheckIT(cond);
9857  if (IsUsingT32()) {
9858    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
9859    if ((imm >= 1) && (imm <= 16)) {
9860      uint32_t imm_ = imm - 1;
9861      EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
9862                 (rn.GetCode() << 16));
9863      AdvanceIT();
9864      return;
9865    }
9866  } else {
9867    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
9868    if ((imm >= 1) && (imm <= 16) && cond.IsNotNever()) {
9869      uint32_t imm_ = imm - 1;
9870      EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9871              (imm_ << 16) | rn.GetCode());
9872      return;
9873    }
9874  }
9875  Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
9876}
9877
9878void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
9879  VIXL_ASSERT(AllowAssembler());
9880  CheckIT(cond);
9881  if (IsUsingT32()) {
9882    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9883    EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9884               rm.GetCode());
9885    AdvanceIT();
9886    return;
9887  } else {
9888    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9889    if (cond.IsNotNever()) {
9890      EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9891              (rn.GetCode() << 16) | rm.GetCode());
9892      return;
9893    }
9894  }
9895  Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
9896}
9897
9898void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
9899  VIXL_ASSERT(AllowAssembler());
9900  CheckIT(cond);
9901  if (IsUsingT32()) {
9902    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9903    EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9904               rm.GetCode());
9905    AdvanceIT();
9906    return;
9907  } else {
9908    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9909    if (cond.IsNotNever()) {
9910      EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9911              (rn.GetCode() << 16) | rm.GetCode());
9912      return;
9913    }
9914  }
9915  Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
9916}
9917
9918void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
9919  VIXL_ASSERT(AllowAssembler());
9920  CheckIT(cond);
9921  if (IsUsingT32()) {
9922    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9923    EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9924               rm.GetCode());
9925    AdvanceIT();
9926    return;
9927  } else {
9928    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9929    if (cond.IsNotNever()) {
9930      EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9931              (rn.GetCode() << 16) | rm.GetCode());
9932      return;
9933    }
9934  }
9935  Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
9936}
9937
9938void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
9939  VIXL_ASSERT(AllowAssembler());
9940  CheckIT(cond);
9941  if (operand.IsImmediateZero()) {
9942    Register rn = operand.GetBaseRegister();
9943    if (IsUsingT32()) {
9944      // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
9945      if ((operand.GetAddrMode() == Offset) &&
9946          ((!rn.IsPC()) || AllowUnpredictable())) {
9947        EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
9948        AdvanceIT();
9949        return;
9950      }
9951    } else {
9952      // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
9953      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
9954          ((!rn.IsPC()) || AllowUnpredictable())) {
9955        EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
9956                (rn.GetCode() << 16));
9957        return;
9958      }
9959    }
9960  }
9961  Delegate(kStl, &Assembler::stl, cond, rt, operand);
9962}
9963
9964void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
9965  VIXL_ASSERT(AllowAssembler());
9966  CheckIT(cond);
9967  if (operand.IsImmediateZero()) {
9968    Register rn = operand.GetBaseRegister();
9969    if (IsUsingT32()) {
9970      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
9971      if ((operand.GetAddrMode() == Offset) &&
9972          ((!rn.IsPC()) || AllowUnpredictable())) {
9973        EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
9974        AdvanceIT();
9975        return;
9976      }
9977    } else {
9978      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
9979      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
9980          ((!rn.IsPC()) || AllowUnpredictable())) {
9981        EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
9982                (rn.GetCode() << 16));
9983        return;
9984      }
9985    }
9986  }
9987  Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
9988}
9989
9990void Assembler::stlex(Condition cond,
9991                      Register rd,
9992                      Register rt,
9993                      const MemOperand& operand) {
9994  VIXL_ASSERT(AllowAssembler());
9995  CheckIT(cond);
9996  if (operand.IsImmediateZero()) {
9997    Register rn = operand.GetBaseRegister();
9998    if (IsUsingT32()) {
9999      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10000      if ((operand.GetAddrMode() == Offset) &&
10001          ((!rn.IsPC()) || AllowUnpredictable())) {
10002        EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
10003                   (rn.GetCode() << 16));
10004        AdvanceIT();
10005        return;
10006      }
10007    } else {
10008      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10009      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10010          ((!rn.IsPC()) || AllowUnpredictable())) {
10011        EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
10012                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10013        return;
10014      }
10015    }
10016  }
10017  Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
10018}
10019
10020void Assembler::stlexb(Condition cond,
10021                       Register rd,
10022                       Register rt,
10023                       const MemOperand& operand) {
10024  VIXL_ASSERT(AllowAssembler());
10025  CheckIT(cond);
10026  if (operand.IsImmediateZero()) {
10027    Register rn = operand.GetBaseRegister();
10028    if (IsUsingT32()) {
10029      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10030      if ((operand.GetAddrMode() == Offset) &&
10031          ((!rn.IsPC()) || AllowUnpredictable())) {
10032        EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
10033                   (rn.GetCode() << 16));
10034        AdvanceIT();
10035        return;
10036      }
10037    } else {
10038      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10039      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10040          ((!rn.IsPC()) || AllowUnpredictable())) {
10041        EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
10042                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10043        return;
10044      }
10045    }
10046  }
10047  Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
10048}
10049
10050void Assembler::stlexd(Condition cond,
10051                       Register rd,
10052                       Register rt,
10053                       Register rt2,
10054                       const MemOperand& operand) {
10055  VIXL_ASSERT(AllowAssembler());
10056  CheckIT(cond);
10057  if (operand.IsImmediateZero()) {
10058    Register rn = operand.GetBaseRegister();
10059    if (IsUsingT32()) {
10060      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
10061      if ((operand.GetAddrMode() == Offset) &&
10062          ((!rn.IsPC()) || AllowUnpredictable())) {
10063        EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
10064                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
10065        AdvanceIT();
10066        return;
10067      }
10068    } else {
10069      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
10070      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10071          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10072          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
10073           AllowUnpredictable())) {
10074        EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
10075                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10076        return;
10077      }
10078    }
10079  }
10080  Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
10081}
10082
10083void Assembler::stlexh(Condition cond,
10084                       Register rd,
10085                       Register rt,
10086                       const MemOperand& operand) {
10087  VIXL_ASSERT(AllowAssembler());
10088  CheckIT(cond);
10089  if (operand.IsImmediateZero()) {
10090    Register rn = operand.GetBaseRegister();
10091    if (IsUsingT32()) {
10092      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10093      if ((operand.GetAddrMode() == Offset) &&
10094          ((!rn.IsPC()) || AllowUnpredictable())) {
10095        EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
10096                   (rn.GetCode() << 16));
10097        AdvanceIT();
10098        return;
10099      }
10100    } else {
10101      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10102      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10103          ((!rn.IsPC()) || AllowUnpredictable())) {
10104        EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
10105                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10106        return;
10107      }
10108    }
10109  }
10110  Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
10111}
10112
10113void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
10114  VIXL_ASSERT(AllowAssembler());
10115  CheckIT(cond);
10116  if (operand.IsImmediateZero()) {
10117    Register rn = operand.GetBaseRegister();
10118    if (IsUsingT32()) {
10119      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
10120      if ((operand.GetAddrMode() == Offset) &&
10121          ((!rn.IsPC()) || AllowUnpredictable())) {
10122        EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10123        AdvanceIT();
10124        return;
10125      }
10126    } else {
10127      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
10128      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10129          ((!rn.IsPC()) || AllowUnpredictable())) {
10130        EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10131                (rn.GetCode() << 16));
10132        return;
10133      }
10134    }
10135  }
10136  Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
10137}
10138
10139void Assembler::stm(Condition cond,
10140                    EncodingSize size,
10141                    Register rn,
10142                    WriteBack write_back,
10143                    RegisterList registers) {
10144  VIXL_ASSERT(AllowAssembler());
10145  CheckIT(cond);
10146  if (IsUsingT32()) {
10147    // STM{<c>}{<q>} <Rn>!, <registers> ; T1
10148    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
10149        ((registers.GetList() & ~0xff) == 0)) {
10150      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
10151                 GetRegisterListEncoding(registers, 0, 8));
10152      AdvanceIT();
10153      return;
10154    }
10155    // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
10156    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10157      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10158                 (write_back.GetWriteBackUint32() << 21) |
10159                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10160                 GetRegisterListEncoding(registers, 0, 13));
10161      AdvanceIT();
10162      return;
10163    }
10164  } else {
10165    // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
10166    if (cond.IsNotNever()) {
10167      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10168              (write_back.GetWriteBackUint32() << 21) |
10169              GetRegisterListEncoding(registers, 0, 16));
10170      return;
10171    }
10172  }
10173  Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
10174}
10175
10176void Assembler::stmda(Condition cond,
10177                      Register rn,
10178                      WriteBack write_back,
10179                      RegisterList registers) {
10180  VIXL_ASSERT(AllowAssembler());
10181  CheckIT(cond);
10182  if (IsUsingA32()) {
10183    // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10184    if (cond.IsNotNever()) {
10185      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10186              (write_back.GetWriteBackUint32() << 21) |
10187              GetRegisterListEncoding(registers, 0, 16));
10188      return;
10189    }
10190  }
10191  Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
10192}
10193
10194void Assembler::stmdb(Condition cond,
10195                      EncodingSize size,
10196                      Register rn,
10197                      WriteBack write_back,
10198                      RegisterList registers) {
10199  VIXL_ASSERT(AllowAssembler());
10200  CheckIT(cond);
10201  if (IsUsingT32()) {
10202    // STMDB{<c>}{<q>} SP!, <registers> ; T1
10203    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
10204        ((registers.GetList() & ~0x40ff) == 0)) {
10205      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
10206                 GetRegisterListEncoding(registers, 0, 8));
10207      AdvanceIT();
10208      return;
10209    }
10210    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
10211    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10212      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
10213                 (write_back.GetWriteBackUint32() << 21) |
10214                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10215                 GetRegisterListEncoding(registers, 0, 13));
10216      AdvanceIT();
10217      return;
10218    }
10219  } else {
10220    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
10221    if (cond.IsNotNever()) {
10222      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10223              (write_back.GetWriteBackUint32() << 21) |
10224              GetRegisterListEncoding(registers, 0, 16));
10225      return;
10226    }
10227  }
10228  Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
10229}
10230
10231void Assembler::stmea(Condition cond,
10232                      EncodingSize size,
10233                      Register rn,
10234                      WriteBack write_back,
10235                      RegisterList registers) {
10236  VIXL_ASSERT(AllowAssembler());
10237  CheckIT(cond);
10238  if (IsUsingT32()) {
10239    // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
10240    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
10241        ((registers.GetList() & ~0xff) == 0)) {
10242      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
10243                 GetRegisterListEncoding(registers, 0, 8));
10244      AdvanceIT();
10245      return;
10246    }
10247    // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
10248    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10249      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10250                 (write_back.GetWriteBackUint32() << 21) |
10251                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10252                 GetRegisterListEncoding(registers, 0, 13));
10253      AdvanceIT();
10254      return;
10255    }
10256    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
10257    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10258      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10259                 (write_back.GetWriteBackUint32() << 21) |
10260                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10261                 GetRegisterListEncoding(registers, 0, 13));
10262      AdvanceIT();
10263      return;
10264    }
10265  } else {
10266    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10267    if (cond.IsNotNever()) {
10268      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10269              (write_back.GetWriteBackUint32() << 21) |
10270              GetRegisterListEncoding(registers, 0, 16));
10271      return;
10272    }
10273  }
10274  Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
10275}
10276
10277void Assembler::stmed(Condition cond,
10278                      Register rn,
10279                      WriteBack write_back,
10280                      RegisterList registers) {
10281  VIXL_ASSERT(AllowAssembler());
10282  CheckIT(cond);
10283  if (IsUsingA32()) {
10284    // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
10285    if (cond.IsNotNever()) {
10286      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10287              (write_back.GetWriteBackUint32() << 21) |
10288              GetRegisterListEncoding(registers, 0, 16));
10289      return;
10290    }
10291  }
10292  Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
10293}
10294
10295void Assembler::stmfa(Condition cond,
10296                      Register rn,
10297                      WriteBack write_back,
10298                      RegisterList registers) {
10299  VIXL_ASSERT(AllowAssembler());
10300  CheckIT(cond);
10301  if (IsUsingA32()) {
10302    // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10303    if (cond.IsNotNever()) {
10304      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10305              (write_back.GetWriteBackUint32() << 21) |
10306              GetRegisterListEncoding(registers, 0, 16));
10307      return;
10308    }
10309  }
10310  Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
10311}
10312
10313void Assembler::stmfd(Condition cond,
10314                      Register rn,
10315                      WriteBack write_back,
10316                      RegisterList registers) {
10317  VIXL_ASSERT(AllowAssembler());
10318  CheckIT(cond);
10319  if (IsUsingT32()) {
10320    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
10321    if (((registers.GetList() & ~0x5fff) == 0)) {
10322      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
10323                 (write_back.GetWriteBackUint32() << 21) |
10324                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10325                 GetRegisterListEncoding(registers, 0, 13));
10326      AdvanceIT();
10327      return;
10328    }
10329  } else {
10330    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
10331    if (cond.IsNotNever()) {
10332      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10333              (write_back.GetWriteBackUint32() << 21) |
10334              GetRegisterListEncoding(registers, 0, 16));
10335      return;
10336    }
10337  }
10338  Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
10339}
10340
10341void Assembler::stmib(Condition cond,
10342                      Register rn,
10343                      WriteBack write_back,
10344                      RegisterList registers) {
10345  VIXL_ASSERT(AllowAssembler());
10346  CheckIT(cond);
10347  if (IsUsingA32()) {
10348    // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
10349    if (cond.IsNotNever()) {
10350      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10351              (write_back.GetWriteBackUint32() << 21) |
10352              GetRegisterListEncoding(registers, 0, 16));
10353      return;
10354    }
10355  }
10356  Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
10357}
10358
10359void Assembler::str(Condition cond,
10360                    EncodingSize size,
10361                    Register rt,
10362                    const MemOperand& operand) {
10363  VIXL_ASSERT(AllowAssembler());
10364  CheckIT(cond);
10365  if (operand.IsImmediate()) {
10366    Register rn = operand.GetBaseRegister();
10367    int32_t offset = operand.GetOffsetImmediate();
10368    if (IsUsingT32()) {
10369      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10370      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10371          (offset <= 124) && ((offset % 4) == 0) &&
10372          (operand.GetAddrMode() == Offset)) {
10373        int32_t offset_ = offset >> 2;
10374        EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
10375                   ((offset_ & 0x1f) << 6));
10376        AdvanceIT();
10377        return;
10378      }
10379      // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
10380      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
10381          ((offset % 4) == 0) && rn.Is(sp) &&
10382          (operand.GetAddrMode() == Offset)) {
10383        int32_t offset_ = offset >> 2;
10384        EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
10385        AdvanceIT();
10386        return;
10387      }
10388      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
10389      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10390          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10391        EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10392                   (offset & 0xfff));
10393        AdvanceIT();
10394        return;
10395      }
10396      // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
10397      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10398          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10399        EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10400                   (-offset & 0xff));
10401        AdvanceIT();
10402        return;
10403      }
10404      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
10405      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10406          (operand.GetAddrMode() == PostIndex) &&
10407          ((rn.GetCode() & 0xf) != 0xf)) {
10408        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10409        uint32_t offset_ = abs(offset);
10410        EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10411                   offset_ | (sign << 9));
10412        AdvanceIT();
10413        return;
10414      }
10415      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
10416      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10417          (operand.GetAddrMode() == PreIndex) &&
10418          ((rn.GetCode() & 0xf) != 0xf)) {
10419        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10420        uint32_t offset_ = abs(offset);
10421        EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10422                   offset_ | (sign << 9));
10423        AdvanceIT();
10424        return;
10425      }
10426    } else {
10427      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10428      if ((offset >= -4095) && (offset <= 4095) &&
10429          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
10430        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10431        uint32_t offset_ = abs(offset);
10432        EmitA32(0x05000000U | (cond.GetCondition() << 28) |
10433                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10434                (sign << 23));
10435        return;
10436      }
10437      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10438      if ((offset >= -4095) && (offset <= 4095) &&
10439          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
10440        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10441        uint32_t offset_ = abs(offset);
10442        EmitA32(0x04000000U | (cond.GetCondition() << 28) |
10443                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10444                (sign << 23));
10445        return;
10446      }
10447      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10448      if ((offset >= -4095) && (offset <= 4095) &&
10449          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
10450        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10451        uint32_t offset_ = abs(offset);
10452        EmitA32(0x05200000U | (cond.GetCondition() << 28) |
10453                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10454                (sign << 23));
10455        return;
10456      }
10457    }
10458  }
10459  if (operand.IsPlainRegister()) {
10460    Register rn = operand.GetBaseRegister();
10461    Sign sign = operand.GetSign();
10462    Register rm = operand.GetOffsetRegister();
10463    if (IsUsingT32()) {
10464      // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
10465      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
10466          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
10467        EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
10468                   (rm.GetCode() << 6));
10469        AdvanceIT();
10470        return;
10471      }
10472    }
10473  }
10474  if (operand.IsShiftedRegister()) {
10475    Register rn = operand.GetBaseRegister();
10476    Sign sign = operand.GetSign();
10477    Register rm = operand.GetOffsetRegister();
10478    Shift shift = operand.GetShift();
10479    uint32_t amount = operand.GetShiftAmount();
10480    if (IsUsingT32()) {
10481      // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
10482      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
10483          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10484        EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10485                   rm.GetCode() | (amount << 4));
10486        AdvanceIT();
10487        return;
10488      }
10489    } else {
10490      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
10491      if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
10492          cond.IsNotNever()) {
10493        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10494        uint32_t shift_ = TypeEncodingValue(shift);
10495        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10496        EmitA32(0x07000000U | (cond.GetCondition() << 28) |
10497                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10498                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10499        return;
10500      }
10501      // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
10502      if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
10503          cond.IsNotNever()) {
10504        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10505        uint32_t shift_ = TypeEncodingValue(shift);
10506        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10507        EmitA32(0x06000000U | (cond.GetCondition() << 28) |
10508                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10509                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10510        return;
10511      }
10512      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
10513      if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
10514          cond.IsNotNever()) {
10515        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10516        uint32_t shift_ = TypeEncodingValue(shift);
10517        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10518        EmitA32(0x07200000U | (cond.GetCondition() << 28) |
10519                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10520                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10521        return;
10522      }
10523    }
10524  }
10525  Delegate(kStr, &Assembler::str, cond, size, rt, operand);
10526}
10527
10528void Assembler::strb(Condition cond,
10529                     EncodingSize size,
10530                     Register rt,
10531                     const MemOperand& operand) {
10532  VIXL_ASSERT(AllowAssembler());
10533  CheckIT(cond);
10534  if (operand.IsImmediate()) {
10535    Register rn = operand.GetBaseRegister();
10536    int32_t offset = operand.GetOffsetImmediate();
10537    if (IsUsingT32()) {
10538      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10539      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10540          (offset <= 31) && (operand.GetAddrMode() == Offset)) {
10541        EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
10542                   ((offset & 0x1f) << 6));
10543        AdvanceIT();
10544        return;
10545      }
10546      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
10547      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10548          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10549        EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10550                   (offset & 0xfff));
10551        AdvanceIT();
10552        return;
10553      }
10554      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
10555      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10556          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10557        EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10558                   (-offset & 0xff));
10559        AdvanceIT();
10560        return;
10561      }
10562      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
10563      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10564          (operand.GetAddrMode() == PostIndex) &&
10565          ((rn.GetCode() & 0xf) != 0xf)) {
10566        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10567        uint32_t offset_ = abs(offset);
10568        EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10569                   offset_ | (sign << 9));
10570        AdvanceIT();
10571        return;
10572      }
10573      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
10574      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10575          (operand.GetAddrMode() == PreIndex) &&
10576          ((rn.GetCode() & 0xf) != 0xf)) {
10577        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10578        uint32_t offset_ = abs(offset);
10579        EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10580                   offset_ | (sign << 9));
10581        AdvanceIT();
10582        return;
10583      }
10584    } else {
10585      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10586      if ((offset >= -4095) && (offset <= 4095) &&
10587          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
10588        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10589        uint32_t offset_ = abs(offset);
10590        EmitA32(0x05400000U | (cond.GetCondition() << 28) |
10591                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10592                (sign << 23));
10593        return;
10594      }
10595      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10596      if ((offset >= -4095) && (offset <= 4095) &&
10597          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
10598        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10599        uint32_t offset_ = abs(offset);
10600        EmitA32(0x04400000U | (cond.GetCondition() << 28) |
10601                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10602                (sign << 23));
10603        return;
10604      }
10605      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10606      if ((offset >= -4095) && (offset <= 4095) &&
10607          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
10608        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10609        uint32_t offset_ = abs(offset);
10610        EmitA32(0x05600000U | (cond.GetCondition() << 28) |
10611                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10612                (sign << 23));
10613        return;
10614      }
10615    }
10616  }
10617  if (operand.IsPlainRegister()) {
10618    Register rn = operand.GetBaseRegister();
10619    Sign sign = operand.GetSign();
10620    Register rm = operand.GetOffsetRegister();
10621    if (IsUsingT32()) {
10622      // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
10623      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
10624          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
10625        EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
10626                   (rm.GetCode() << 6));
10627        AdvanceIT();
10628        return;
10629      }
10630    }
10631  }
10632  if (operand.IsShiftedRegister()) {
10633    Register rn = operand.GetBaseRegister();
10634    Sign sign = operand.GetSign();
10635    Register rm = operand.GetOffsetRegister();
10636    Shift shift = operand.GetShift();
10637    uint32_t amount = operand.GetShiftAmount();
10638    if (IsUsingT32()) {
10639      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
10640      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
10641          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10642        EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10643                   rm.GetCode() | (amount << 4));
10644        AdvanceIT();
10645        return;
10646      }
10647    } else {
10648      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
10649      if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
10650          cond.IsNotNever()) {
10651        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10652        uint32_t shift_ = TypeEncodingValue(shift);
10653        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10654        EmitA32(0x07400000U | (cond.GetCondition() << 28) |
10655                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10656                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10657        return;
10658      }
10659      // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
10660      if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
10661          cond.IsNotNever()) {
10662        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10663        uint32_t shift_ = TypeEncodingValue(shift);
10664        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10665        EmitA32(0x06400000U | (cond.GetCondition() << 28) |
10666                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10667                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10668        return;
10669      }
10670      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
10671      if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
10672          cond.IsNotNever()) {
10673        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10674        uint32_t shift_ = TypeEncodingValue(shift);
10675        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10676        EmitA32(0x07600000U | (cond.GetCondition() << 28) |
10677                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10678                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10679        return;
10680      }
10681    }
10682  }
10683  Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
10684}
10685
10686void Assembler::strd(Condition cond,
10687                     Register rt,
10688                     Register rt2,
10689                     const MemOperand& operand) {
10690  VIXL_ASSERT(AllowAssembler());
10691  CheckIT(cond);
10692  if (operand.IsImmediate()) {
10693    Register rn = operand.GetBaseRegister();
10694    int32_t offset = operand.GetOffsetImmediate();
10695    if (IsUsingT32()) {
10696      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
10697      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10698          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10699        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10700        uint32_t offset_ = abs(offset) >> 2;
10701        EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10702                   (rn.GetCode() << 16) | offset_ | (sign << 23));
10703        AdvanceIT();
10704        return;
10705      }
10706      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
10707      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10708          (operand.GetAddrMode() == PostIndex) &&
10709          ((rn.GetCode() & 0xf) != 0xf)) {
10710        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10711        uint32_t offset_ = abs(offset) >> 2;
10712        EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10713                   (rn.GetCode() << 16) | offset_ | (sign << 23));
10714        AdvanceIT();
10715        return;
10716      }
10717      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
10718      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10719          (operand.GetAddrMode() == PreIndex) &&
10720          ((rn.GetCode() & 0xf) != 0xf)) {
10721        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10722        uint32_t offset_ = abs(offset) >> 2;
10723        EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10724                   (rn.GetCode() << 16) | offset_ | (sign << 23));
10725        AdvanceIT();
10726        return;
10727      }
10728    } else {
10729      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
10730      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10731          (offset >= -255) && (offset <= 255) &&
10732          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10733          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10734        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10735        uint32_t offset_ = abs(offset);
10736        EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
10737                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10738                ((offset_ & 0xf0) << 4) | (sign << 23));
10739        return;
10740      }
10741      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
10742      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10743          (offset >= -255) && (offset <= 255) &&
10744          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
10745          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10746        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10747        uint32_t offset_ = abs(offset);
10748        EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
10749                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10750                ((offset_ & 0xf0) << 4) | (sign << 23));
10751        return;
10752      }
10753      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
10754      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10755          (offset >= -255) && (offset <= 255) &&
10756          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
10757          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10758        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10759        uint32_t offset_ = abs(offset);
10760        EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
10761                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10762                ((offset_ & 0xf0) << 4) | (sign << 23));
10763        return;
10764      }
10765    }
10766  }
10767  if (operand.IsPlainRegister()) {
10768    Register rn = operand.GetBaseRegister();
10769    Sign sign = operand.GetSign();
10770    Register rm = operand.GetOffsetRegister();
10771    if (IsUsingA32()) {
10772      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
10773      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10774          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10775          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10776        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10777        EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
10778                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10779                (sign_ << 23));
10780        return;
10781      }
10782      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
10783      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10784          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
10785          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10786        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10787        EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
10788                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10789                (sign_ << 23));
10790        return;
10791      }
10792      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
10793      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10794          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
10795          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10796        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10797        EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
10798                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10799                (sign_ << 23));
10800        return;
10801      }
10802    }
10803  }
10804  Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
10805}
10806
10807void Assembler::strex(Condition cond,
10808                      Register rd,
10809                      Register rt,
10810                      const MemOperand& operand) {
10811  VIXL_ASSERT(AllowAssembler());
10812  CheckIT(cond);
10813  if (operand.IsImmediate()) {
10814    Register rn = operand.GetBaseRegister();
10815    int32_t offset = operand.GetOffsetImmediate();
10816    if (IsUsingT32()) {
10817      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
10818      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
10819          (operand.GetAddrMode() == Offset)) {
10820        int32_t offset_ = offset >> 2;
10821        EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
10822                   (rn.GetCode() << 16) | (offset_ & 0xff));
10823        AdvanceIT();
10824        return;
10825      }
10826    } else {
10827      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
10828      if ((offset == 0) && (operand.GetAddrMode() == Offset) &&
10829          cond.IsNotNever()) {
10830        EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
10831                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10832        return;
10833      }
10834    }
10835  }
10836  Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
10837}
10838
10839void Assembler::strexb(Condition cond,
10840                       Register rd,
10841                       Register rt,
10842                       const MemOperand& operand) {
10843  VIXL_ASSERT(AllowAssembler());
10844  CheckIT(cond);
10845  if (operand.IsImmediateZero()) {
10846    Register rn = operand.GetBaseRegister();
10847    if (IsUsingT32()) {
10848      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10849      if ((operand.GetAddrMode() == Offset) &&
10850          ((!rn.IsPC()) || AllowUnpredictable())) {
10851        EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
10852                   (rn.GetCode() << 16));
10853        AdvanceIT();
10854        return;
10855      }
10856    } else {
10857      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10858      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10859          ((!rn.IsPC()) || AllowUnpredictable())) {
10860        EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
10861                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10862        return;
10863      }
10864    }
10865  }
10866  Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
10867}
10868
10869void Assembler::strexd(Condition cond,
10870                       Register rd,
10871                       Register rt,
10872                       Register rt2,
10873                       const MemOperand& operand) {
10874  VIXL_ASSERT(AllowAssembler());
10875  CheckIT(cond);
10876  if (operand.IsImmediateZero()) {
10877    Register rn = operand.GetBaseRegister();
10878    if (IsUsingT32()) {
10879      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
10880      if ((operand.GetAddrMode() == Offset) &&
10881          ((!rn.IsPC()) || AllowUnpredictable())) {
10882        EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
10883                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
10884        AdvanceIT();
10885        return;
10886      }
10887    } else {
10888      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
10889      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10890          (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10891          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
10892           AllowUnpredictable())) {
10893        EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
10894                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10895        return;
10896      }
10897    }
10898  }
10899  Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
10900}
10901
10902void Assembler::strexh(Condition cond,
10903                       Register rd,
10904                       Register rt,
10905                       const MemOperand& operand) {
10906  VIXL_ASSERT(AllowAssembler());
10907  CheckIT(cond);
10908  if (operand.IsImmediateZero()) {
10909    Register rn = operand.GetBaseRegister();
10910    if (IsUsingT32()) {
10911      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10912      if ((operand.GetAddrMode() == Offset) &&
10913          ((!rn.IsPC()) || AllowUnpredictable())) {
10914        EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
10915                   (rn.GetCode() << 16));
10916        AdvanceIT();
10917        return;
10918      }
10919    } else {
10920      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10921      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10922          ((!rn.IsPC()) || AllowUnpredictable())) {
10923        EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
10924                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10925        return;
10926      }
10927    }
10928  }
10929  Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
10930}
10931
10932void Assembler::strh(Condition cond,
10933                     EncodingSize size,
10934                     Register rt,
10935                     const MemOperand& operand) {
10936  VIXL_ASSERT(AllowAssembler());
10937  CheckIT(cond);
10938  if (operand.IsImmediate()) {
10939    Register rn = operand.GetBaseRegister();
10940    int32_t offset = operand.GetOffsetImmediate();
10941    if (IsUsingT32()) {
10942      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10943      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10944          (offset <= 62) && ((offset % 2) == 0) &&
10945          (operand.GetAddrMode() == Offset)) {
10946        int32_t offset_ = offset >> 1;
10947        EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
10948                   ((offset_ & 0x1f) << 6));
10949        AdvanceIT();
10950        return;
10951      }
10952      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
10953      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10954          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10955        EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10956                   (offset & 0xfff));
10957        AdvanceIT();
10958        return;
10959      }
10960      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
10961      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10962          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10963        EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10964                   (-offset & 0xff));
10965        AdvanceIT();
10966        return;
10967      }
10968      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
10969      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10970          (operand.GetAddrMode() == PostIndex) &&
10971          ((rn.GetCode() & 0xf) != 0xf)) {
10972        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10973        uint32_t offset_ = abs(offset);
10974        EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10975                   offset_ | (sign << 9));
10976        AdvanceIT();
10977        return;
10978      }
10979      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
10980      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10981          (operand.GetAddrMode() == PreIndex) &&
10982          ((rn.GetCode() & 0xf) != 0xf)) {
10983        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10984        uint32_t offset_ = abs(offset);
10985        EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10986                   offset_ | (sign << 9));
10987        AdvanceIT();
10988        return;
10989      }
10990    } else {
10991      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10992      if ((offset >= -255) && (offset <= 255) &&
10993          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
10994        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10995        uint32_t offset_ = abs(offset);
10996        EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
10997                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10998                ((offset_ & 0xf0) << 4) | (sign << 23));
10999        return;
11000      }
11001      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11002      if ((offset >= -255) && (offset <= 255) &&
11003          (operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
11004        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11005        uint32_t offset_ = abs(offset);
11006        EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
11007                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11008                ((offset_ & 0xf0) << 4) | (sign << 23));
11009        return;
11010      }
11011      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11012      if ((offset >= -255) && (offset <= 255) &&
11013          (operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
11014        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11015        uint32_t offset_ = abs(offset);
11016        EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
11017                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11018                ((offset_ & 0xf0) << 4) | (sign << 23));
11019        return;
11020      }
11021    }
11022  }
11023  if (operand.IsPlainRegister()) {
11024    Register rn = operand.GetBaseRegister();
11025    Sign sign = operand.GetSign();
11026    Register rm = operand.GetOffsetRegister();
11027    if (IsUsingT32()) {
11028      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11029      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11030          sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
11031        EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
11032                   (rm.GetCode() << 6));
11033        AdvanceIT();
11034        return;
11035      }
11036    } else {
11037      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
11038      if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
11039        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11040        EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
11041                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11042                (sign_ << 23));
11043        return;
11044      }
11045      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
11046      if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
11047        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11048        EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
11049                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11050                (sign_ << 23));
11051        return;
11052      }
11053      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
11054      if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
11055        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11056        EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
11057                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11058                (sign_ << 23));
11059        return;
11060      }
11061    }
11062  }
11063  if (operand.IsShiftedRegister()) {
11064    Register rn = operand.GetBaseRegister();
11065    Sign sign = operand.GetSign();
11066    Register rm = operand.GetOffsetRegister();
11067    Shift shift = operand.GetShift();
11068    uint32_t amount = operand.GetShiftAmount();
11069    if (IsUsingT32()) {
11070      // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11071      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11072          (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
11073        EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11074                   rm.GetCode() | (amount << 4));
11075        AdvanceIT();
11076        return;
11077      }
11078    }
11079  }
11080  Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
11081}
11082
11083void Assembler::sub(Condition cond,
11084                    EncodingSize size,
11085                    Register rd,
11086                    Register rn,
11087                    const Operand& operand) {
11088  VIXL_ASSERT(AllowAssembler());
11089  CheckIT(cond);
11090  if (operand.IsImmediate()) {
11091    uint32_t imm = operand.GetImmediate();
11092    if (IsUsingT32()) {
11093      ImmediateT32 immediate_t32(imm);
11094      // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
11095      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11096          (imm <= 7)) {
11097        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
11098        AdvanceIT();
11099        return;
11100      }
11101      // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
11102      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
11103          (imm <= 255)) {
11104        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11105        AdvanceIT();
11106        return;
11107      }
11108      // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
11109      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
11110          ((imm % 4) == 0)) {
11111        uint32_t imm_ = imm >> 2;
11112        EmitT32_16(0xb080 | imm_);
11113        AdvanceIT();
11114        return;
11115      }
11116      // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
11117      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) {
11118        EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11119                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11120        AdvanceIT();
11121        return;
11122      }
11123      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
11124      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp)) {
11125        EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11126                   (immediate_t32.GetEncodingValue() & 0xff) |
11127                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11128                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11129        AdvanceIT();
11130        return;
11131      }
11132      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
11133      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
11134        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11135                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11136        AdvanceIT();
11137        return;
11138      }
11139      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
11140      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid()) {
11141        EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
11142                   (immediate_t32.GetEncodingValue() & 0xff) |
11143                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11144                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11145        AdvanceIT();
11146        return;
11147      }
11148      // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
11149      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095)) {
11150        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11151                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11152        AdvanceIT();
11153        return;
11154      }
11155    } else {
11156      ImmediateA32 immediate_a32(imm);
11157      // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
11158      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
11159        EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
11160                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11161        return;
11162      }
11163      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
11164      if (immediate_a32.IsValid() && cond.IsNotNever() &&
11165          ((rn.GetCode() & 0xd) != 0xd)) {
11166        EmitA32(0x02400000U | (cond.GetCondition() << 28) |
11167                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
11168                immediate_a32.GetEncodingValue());
11169        return;
11170      }
11171      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
11172      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
11173        EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
11174                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11175        return;
11176      }
11177    }
11178  }
11179  if (operand.IsImmediateShiftedRegister()) {
11180    Register rm = operand.GetBaseRegister();
11181    if (operand.IsPlainRegister()) {
11182      if (IsUsingT32()) {
11183        // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
11184        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11185            rm.IsLow()) {
11186          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
11187                     (rm.GetCode() << 6));
11188          AdvanceIT();
11189          return;
11190        }
11191        // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
11192        if (rn.Is(sp)) {
11193          EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
11194          AdvanceIT();
11195          return;
11196        }
11197      }
11198    }
11199    Shift shift = operand.GetShift();
11200    uint32_t amount = operand.GetShiftAmount();
11201    if (IsUsingT32()) {
11202      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
11203      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp)) {
11204        uint32_t amount_ = amount % 32;
11205        EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11206                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
11207                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11208        AdvanceIT();
11209        return;
11210      }
11211      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
11212      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount)) {
11213        uint32_t amount_ = amount % 32;
11214        EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
11215                   (operand.GetTypeEncodingValue() << 4) |
11216                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11217        AdvanceIT();
11218        return;
11219      }
11220    } else {
11221      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
11222      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
11223        uint32_t amount_ = amount % 32;
11224        EmitA32(0x00400000U | (cond.GetCondition() << 28) |
11225                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11226                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11227        return;
11228      }
11229      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
11230      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
11231        uint32_t amount_ = amount % 32;
11232        EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
11233                (rd.GetCode() << 12) | rm.GetCode() |
11234                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11235        return;
11236      }
11237    }
11238  }
11239  if (operand.IsRegisterShiftedRegister()) {
11240    Register rm = operand.GetBaseRegister();
11241    Shift shift = operand.GetShift();
11242    if (IsUsingA32()) {
11243      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
11244      if (cond.IsNotNever()) {
11245        EmitA32(0x00400010U | (cond.GetCondition() << 28) |
11246                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11247                (shift.GetType() << 5) |
11248                (operand.GetShiftRegister().GetCode() << 8));
11249        return;
11250      }
11251    }
11252  }
11253  Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
11254}
11255
11256void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
11257  VIXL_ASSERT(AllowAssembler());
11258  CheckIT(cond);
11259  if (operand.IsImmediate()) {
11260    uint32_t imm = operand.GetImmediate();
11261    if (IsUsingT32()) {
11262      // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
11263      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
11264        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11265        AdvanceIT();
11266        return;
11267      }
11268    }
11269  }
11270  Delegate(kSub, &Assembler::sub, cond, rd, operand);
11271}
11272
11273void Assembler::subs(Condition cond,
11274                     EncodingSize size,
11275                     Register rd,
11276                     Register rn,
11277                     const Operand& operand) {
11278  VIXL_ASSERT(AllowAssembler());
11279  CheckIT(cond);
11280  if (operand.IsImmediate()) {
11281    uint32_t imm = operand.GetImmediate();
11282    if (IsUsingT32()) {
11283      ImmediateT32 immediate_t32(imm);
11284      // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
11285      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11286          (imm <= 7)) {
11287        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
11288        AdvanceIT();
11289        return;
11290      }
11291      // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
11292      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
11293          (imm <= 255)) {
11294        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11295        AdvanceIT();
11296        return;
11297      }
11298      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
11299      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
11300          !rd.Is(pc)) {
11301        EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11302                   (immediate_t32.GetEncodingValue() & 0xff) |
11303                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11304                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11305        AdvanceIT();
11306        return;
11307      }
11308      // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
11309      if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255)) {
11310        EmitT32_32(0xf3de8f00U | imm);
11311        AdvanceIT();
11312        return;
11313      }
11314      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
11315      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
11316          !rd.Is(pc)) {
11317        EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
11318                   (immediate_t32.GetEncodingValue() & 0xff) |
11319                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11320                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11321        AdvanceIT();
11322        return;
11323      }
11324    } else {
11325      ImmediateA32 immediate_a32(imm);
11326      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
11327      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
11328        EmitA32(0x02500000U | (cond.GetCondition() << 28) |
11329                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
11330                immediate_a32.GetEncodingValue());
11331        return;
11332      }
11333      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
11334      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
11335        EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
11336                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11337        return;
11338      }
11339    }
11340  }
11341  if (operand.IsImmediateShiftedRegister()) {
11342    Register rm = operand.GetBaseRegister();
11343    if (operand.IsPlainRegister()) {
11344      if (IsUsingT32()) {
11345        // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11346        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11347            rm.IsLow()) {
11348          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
11349                     (rm.GetCode() << 6));
11350          AdvanceIT();
11351          return;
11352        }
11353      }
11354    }
11355    Shift shift = operand.GetShift();
11356    uint32_t amount = operand.GetShiftAmount();
11357    if (IsUsingT32()) {
11358      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
11359      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
11360          !rd.Is(pc)) {
11361        uint32_t amount_ = amount % 32;
11362        EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11363                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
11364                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11365        AdvanceIT();
11366        return;
11367      }
11368      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
11369      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
11370          !rd.Is(pc)) {
11371        uint32_t amount_ = amount % 32;
11372        EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
11373                   (operand.GetTypeEncodingValue() << 4) |
11374                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11375        AdvanceIT();
11376        return;
11377      }
11378    } else {
11379      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
11380      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
11381        uint32_t amount_ = amount % 32;
11382        EmitA32(0x00500000U | (cond.GetCondition() << 28) |
11383                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11384                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11385        return;
11386      }
11387      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
11388      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
11389        uint32_t amount_ = amount % 32;
11390        EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
11391                (rd.GetCode() << 12) | rm.GetCode() |
11392                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11393        return;
11394      }
11395    }
11396  }
11397  if (operand.IsRegisterShiftedRegister()) {
11398    Register rm = operand.GetBaseRegister();
11399    Shift shift = operand.GetShift();
11400    if (IsUsingA32()) {
11401      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
11402      if (cond.IsNotNever()) {
11403        EmitA32(0x00500010U | (cond.GetCondition() << 28) |
11404                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11405                (shift.GetType() << 5) |
11406                (operand.GetShiftRegister().GetCode() << 8));
11407        return;
11408      }
11409    }
11410  }
11411  Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
11412}
11413
11414void Assembler::subs(Register rd, const Operand& operand) {
11415  VIXL_ASSERT(AllowAssembler());
11416  CheckIT(al);
11417  if (operand.IsImmediate()) {
11418    uint32_t imm = operand.GetImmediate();
11419    if (IsUsingT32()) {
11420      // SUBS{<q>} <Rdn>, #<imm8> ; T2
11421      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
11422        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11423        AdvanceIT();
11424        return;
11425      }
11426    }
11427  }
11428  Delegate(kSubs, &Assembler::subs, rd, operand);
11429}
11430
11431void Assembler::subw(Condition cond,
11432                     Register rd,
11433                     Register rn,
11434                     const Operand& operand) {
11435  VIXL_ASSERT(AllowAssembler());
11436  CheckIT(cond);
11437  if (operand.IsImmediate()) {
11438    uint32_t imm = operand.GetImmediate();
11439    if (IsUsingT32()) {
11440      // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
11441      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
11442        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11443                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11444        AdvanceIT();
11445        return;
11446      }
11447      // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
11448      if (rn.Is(sp) && (imm <= 4095)) {
11449        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11450                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11451        AdvanceIT();
11452        return;
11453      }
11454    }
11455  }
11456  Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
11457}
11458
11459void Assembler::svc(Condition cond, uint32_t imm) {
11460  VIXL_ASSERT(AllowAssembler());
11461  CheckIT(cond);
11462  if (IsUsingT32()) {
11463    // SVC{<c>}{<q>} {#}<imm> ; T1
11464    if ((imm <= 255)) {
11465      EmitT32_16(0xdf00 | imm);
11466      AdvanceIT();
11467      return;
11468    }
11469  } else {
11470    // SVC{<c>}{<q>} {#}<imm> ; A1
11471    if ((imm <= 16777215) && cond.IsNotNever()) {
11472      EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
11473      return;
11474    }
11475  }
11476  Delegate(kSvc, &Assembler::svc, cond, imm);
11477}
11478
11479void Assembler::sxtab(Condition cond,
11480                      Register rd,
11481                      Register rn,
11482                      const Operand& operand) {
11483  VIXL_ASSERT(AllowAssembler());
11484  CheckIT(cond);
11485  if (operand.IsImmediateShiftedRegister()) {
11486    Register rm = operand.GetBaseRegister();
11487    Shift shift = operand.GetShift();
11488    uint32_t amount = operand.GetShiftAmount();
11489    if (IsUsingT32()) {
11490      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11491      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11492          ((amount % 8) == 0) && !rn.Is(pc)) {
11493        uint32_t amount_ = amount / 8;
11494        EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11495                   rm.GetCode() | (amount_ << 4));
11496        AdvanceIT();
11497        return;
11498      }
11499    } else {
11500      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11501      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11502          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11503        uint32_t amount_ = amount / 8;
11504        EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
11505                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11506                (amount_ << 10));
11507        return;
11508      }
11509    }
11510  }
11511  Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
11512}
11513
11514void Assembler::sxtab16(Condition cond,
11515                        Register rd,
11516                        Register rn,
11517                        const Operand& operand) {
11518  VIXL_ASSERT(AllowAssembler());
11519  CheckIT(cond);
11520  if (operand.IsImmediateShiftedRegister()) {
11521    Register rm = operand.GetBaseRegister();
11522    Shift shift = operand.GetShift();
11523    uint32_t amount = operand.GetShiftAmount();
11524    if (IsUsingT32()) {
11525      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11526      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11527          ((amount % 8) == 0) && !rn.Is(pc)) {
11528        uint32_t amount_ = amount / 8;
11529        EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11530                   rm.GetCode() | (amount_ << 4));
11531        AdvanceIT();
11532        return;
11533      }
11534    } else {
11535      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11536      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11537          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11538        uint32_t amount_ = amount / 8;
11539        EmitA32(0x06800070U | (cond.GetCondition() << 28) |
11540                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11541                (amount_ << 10));
11542        return;
11543      }
11544    }
11545  }
11546  Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
11547}
11548
11549void Assembler::sxtah(Condition cond,
11550                      Register rd,
11551                      Register rn,
11552                      const Operand& operand) {
11553  VIXL_ASSERT(AllowAssembler());
11554  CheckIT(cond);
11555  if (operand.IsImmediateShiftedRegister()) {
11556    Register rm = operand.GetBaseRegister();
11557    Shift shift = operand.GetShift();
11558    uint32_t amount = operand.GetShiftAmount();
11559    if (IsUsingT32()) {
11560      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11561      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11562          ((amount % 8) == 0) && !rn.Is(pc)) {
11563        uint32_t amount_ = amount / 8;
11564        EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11565                   rm.GetCode() | (amount_ << 4));
11566        AdvanceIT();
11567        return;
11568      }
11569    } else {
11570      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11571      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11572          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11573        uint32_t amount_ = amount / 8;
11574        EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
11575                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11576                (amount_ << 10));
11577        return;
11578      }
11579    }
11580  }
11581  Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
11582}
11583
11584void Assembler::sxtb(Condition cond,
11585                     EncodingSize size,
11586                     Register rd,
11587                     const Operand& operand) {
11588  VIXL_ASSERT(AllowAssembler());
11589  CheckIT(cond);
11590  if (operand.IsImmediateShiftedRegister()) {
11591    Register rm = operand.GetBaseRegister();
11592    if (operand.IsPlainRegister()) {
11593      if (IsUsingT32()) {
11594        // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
11595        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
11596          EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
11597          AdvanceIT();
11598          return;
11599        }
11600      }
11601    }
11602    Shift shift = operand.GetShift();
11603    uint32_t amount = operand.GetShiftAmount();
11604    if (IsUsingT32()) {
11605      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
11606      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
11607          (amount <= 24) && ((amount % 8) == 0)) {
11608        uint32_t amount_ = amount / 8;
11609        EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11610                   (amount_ << 4));
11611        AdvanceIT();
11612        return;
11613      }
11614    } else {
11615      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11616      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11617          ((amount % 8) == 0) && cond.IsNotNever()) {
11618        uint32_t amount_ = amount / 8;
11619        EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
11620                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11621        return;
11622      }
11623    }
11624  }
11625  Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
11626}
11627
11628void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
11629  VIXL_ASSERT(AllowAssembler());
11630  CheckIT(cond);
11631  if (operand.IsImmediateShiftedRegister()) {
11632    Register rm = operand.GetBaseRegister();
11633    Shift shift = operand.GetShift();
11634    uint32_t amount = operand.GetShiftAmount();
11635    if (IsUsingT32()) {
11636      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
11637      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11638          ((amount % 8) == 0)) {
11639        uint32_t amount_ = amount / 8;
11640        EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11641                   (amount_ << 4));
11642        AdvanceIT();
11643        return;
11644      }
11645    } else {
11646      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11647      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11648          ((amount % 8) == 0) && cond.IsNotNever()) {
11649        uint32_t amount_ = amount / 8;
11650        EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
11651                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11652        return;
11653      }
11654    }
11655  }
11656  Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
11657}
11658
11659void Assembler::sxth(Condition cond,
11660                     EncodingSize size,
11661                     Register rd,
11662                     const Operand& operand) {
11663  VIXL_ASSERT(AllowAssembler());
11664  CheckIT(cond);
11665  if (operand.IsImmediateShiftedRegister()) {
11666    Register rm = operand.GetBaseRegister();
11667    if (operand.IsPlainRegister()) {
11668      if (IsUsingT32()) {
11669        // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
11670        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
11671          EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
11672          AdvanceIT();
11673          return;
11674        }
11675      }
11676    }
11677    Shift shift = operand.GetShift();
11678    uint32_t amount = operand.GetShiftAmount();
11679    if (IsUsingT32()) {
11680      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
11681      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
11682          (amount <= 24) && ((amount % 8) == 0)) {
11683        uint32_t amount_ = amount / 8;
11684        EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11685                   (amount_ << 4));
11686        AdvanceIT();
11687        return;
11688      }
11689    } else {
11690      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11691      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11692          ((amount % 8) == 0) && cond.IsNotNever()) {
11693        uint32_t amount_ = amount / 8;
11694        EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
11695                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11696        return;
11697      }
11698    }
11699  }
11700  Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
11701}
11702
11703void Assembler::tbb(Condition cond, Register rn, Register rm) {
11704  VIXL_ASSERT(AllowAssembler());
11705  CheckIT(cond);
11706  if (IsUsingT32()) {
11707    // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
11708    if (OutsideITBlockAndAlOrLast(cond) &&
11709        ((!rm.IsPC()) || AllowUnpredictable())) {
11710      EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
11711      AdvanceIT();
11712      return;
11713    }
11714  }
11715  Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
11716}
11717
11718void Assembler::tbh(Condition cond, Register rn, Register rm) {
11719  VIXL_ASSERT(AllowAssembler());
11720  CheckIT(cond);
11721  if (IsUsingT32()) {
11722    // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
11723    if (OutsideITBlockAndAlOrLast(cond) &&
11724        ((!rm.IsPC()) || AllowUnpredictable())) {
11725      EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
11726      AdvanceIT();
11727      return;
11728    }
11729  }
11730  Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
11731}
11732
11733void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
11734  VIXL_ASSERT(AllowAssembler());
11735  CheckIT(cond);
11736  if (operand.IsImmediate()) {
11737    uint32_t imm = operand.GetImmediate();
11738    if (IsUsingT32()) {
11739      ImmediateT32 immediate_t32(imm);
11740      // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
11741      if (immediate_t32.IsValid()) {
11742        EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
11743                   (immediate_t32.GetEncodingValue() & 0xff) |
11744                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11745                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11746        AdvanceIT();
11747        return;
11748      }
11749    } else {
11750      ImmediateA32 immediate_a32(imm);
11751      // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
11752      if (immediate_a32.IsValid() && cond.IsNotNever()) {
11753        EmitA32(0x03300000U | (cond.GetCondition() << 28) |
11754                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
11755        return;
11756      }
11757    }
11758  }
11759  if (operand.IsImmediateShiftedRegister()) {
11760    Register rm = operand.GetBaseRegister();
11761    Shift shift = operand.GetShift();
11762    uint32_t amount = operand.GetShiftAmount();
11763    if (IsUsingT32()) {
11764      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
11765      if (shift.IsValidAmount(amount)) {
11766        uint32_t amount_ = amount % 32;
11767        EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
11768                   (operand.GetTypeEncodingValue() << 4) |
11769                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11770        AdvanceIT();
11771        return;
11772      }
11773    } else {
11774      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
11775      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
11776        uint32_t amount_ = amount % 32;
11777        EmitA32(0x01300000U | (cond.GetCondition() << 28) |
11778                (rn.GetCode() << 16) | rm.GetCode() |
11779                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11780        return;
11781      }
11782    }
11783  }
11784  if (operand.IsRegisterShiftedRegister()) {
11785    Register rm = operand.GetBaseRegister();
11786    Shift shift = operand.GetShift();
11787    if (IsUsingA32()) {
11788      // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
11789      if (cond.IsNotNever()) {
11790        EmitA32(0x01300010U | (cond.GetCondition() << 28) |
11791                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
11792                (operand.GetShiftRegister().GetCode() << 8));
11793        return;
11794      }
11795    }
11796  }
11797  Delegate(kTeq, &Assembler::teq, cond, rn, operand);
11798}
11799
11800void Assembler::tst(Condition cond,
11801                    EncodingSize size,
11802                    Register rn,
11803                    const Operand& operand) {
11804  VIXL_ASSERT(AllowAssembler());
11805  CheckIT(cond);
11806  if (operand.IsImmediate()) {
11807    uint32_t imm = operand.GetImmediate();
11808    if (IsUsingT32()) {
11809      ImmediateT32 immediate_t32(imm);
11810      // TST{<c>}{<q>} <Rn>, #<const> ; T1
11811      if (!size.IsNarrow() && immediate_t32.IsValid()) {
11812        EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
11813                   (immediate_t32.GetEncodingValue() & 0xff) |
11814                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11815                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11816        AdvanceIT();
11817        return;
11818      }
11819    } else {
11820      ImmediateA32 immediate_a32(imm);
11821      // TST{<c>}{<q>} <Rn>, #<const> ; A1
11822      if (immediate_a32.IsValid() && cond.IsNotNever()) {
11823        EmitA32(0x03100000U | (cond.GetCondition() << 28) |
11824                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
11825        return;
11826      }
11827    }
11828  }
11829  if (operand.IsImmediateShiftedRegister()) {
11830    Register rm = operand.GetBaseRegister();
11831    if (operand.IsPlainRegister()) {
11832      if (IsUsingT32()) {
11833        // TST{<c>}{<q>} <Rn>, <Rm> ; T1
11834        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
11835          EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
11836          AdvanceIT();
11837          return;
11838        }
11839      }
11840    }
11841    Shift shift = operand.GetShift();
11842    uint32_t amount = operand.GetShiftAmount();
11843    if (IsUsingT32()) {
11844      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
11845      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
11846        uint32_t amount_ = amount % 32;
11847        EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
11848                   (operand.GetTypeEncodingValue() << 4) |
11849                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11850        AdvanceIT();
11851        return;
11852      }
11853    } else {
11854      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
11855      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
11856        uint32_t amount_ = amount % 32;
11857        EmitA32(0x01100000U | (cond.GetCondition() << 28) |
11858                (rn.GetCode() << 16) | rm.GetCode() |
11859                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11860        return;
11861      }
11862    }
11863  }
11864  if (operand.IsRegisterShiftedRegister()) {
11865    Register rm = operand.GetBaseRegister();
11866    Shift shift = operand.GetShift();
11867    if (IsUsingA32()) {
11868      // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
11869      if (cond.IsNotNever()) {
11870        EmitA32(0x01100010U | (cond.GetCondition() << 28) |
11871                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
11872                (operand.GetShiftRegister().GetCode() << 8));
11873        return;
11874      }
11875    }
11876  }
11877  Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
11878}
11879
11880void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
11881  VIXL_ASSERT(AllowAssembler());
11882  CheckIT(cond);
11883  if (IsUsingT32()) {
11884    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11885    EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11886               rm.GetCode());
11887    AdvanceIT();
11888    return;
11889  } else {
11890    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11891    if (cond.IsNotNever()) {
11892      EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11893              (rn.GetCode() << 16) | rm.GetCode());
11894      return;
11895    }
11896  }
11897  Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
11898}
11899
11900void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
11901  VIXL_ASSERT(AllowAssembler());
11902  CheckIT(cond);
11903  if (IsUsingT32()) {
11904    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11905    EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11906               rm.GetCode());
11907    AdvanceIT();
11908    return;
11909  } else {
11910    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11911    if (cond.IsNotNever()) {
11912      EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11913              (rn.GetCode() << 16) | rm.GetCode());
11914      return;
11915    }
11916  }
11917  Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
11918}
11919
11920void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
11921  VIXL_ASSERT(AllowAssembler());
11922  CheckIT(cond);
11923  if (IsUsingT32()) {
11924    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11925    EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11926               rm.GetCode());
11927    AdvanceIT();
11928    return;
11929  } else {
11930    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11931    if (cond.IsNotNever()) {
11932      EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11933              (rn.GetCode() << 16) | rm.GetCode());
11934      return;
11935    }
11936  }
11937  Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
11938}
11939
11940void Assembler::ubfx(Condition cond,
11941                     Register rd,
11942                     Register rn,
11943                     uint32_t lsb,
11944                     const Operand& operand) {
11945  VIXL_ASSERT(AllowAssembler());
11946  CheckIT(cond);
11947  if (operand.IsImmediate()) {
11948    uint32_t width = operand.GetImmediate();
11949    if (IsUsingT32()) {
11950      // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
11951      if ((lsb <= 31) &&
11952          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
11953        uint32_t widthm1 = width - 1;
11954        EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11955                   ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
11956        AdvanceIT();
11957        return;
11958      }
11959    } else {
11960      // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
11961      if ((lsb <= 31) && cond.IsNotNever() &&
11962          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
11963        uint32_t widthm1 = width - 1;
11964        EmitA32(0x07e00050U | (cond.GetCondition() << 28) |
11965                (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) |
11966                (widthm1 << 16));
11967        return;
11968      }
11969    }
11970  }
11971  Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, operand);
11972}
11973
11974void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
11975  VIXL_ASSERT(AllowAssembler());
11976  CheckIT(cond);
11977  if (IsUsingT32()) {
11978    // UDF{<c>}{<q>} {#}<imm> ; T1
11979    if (!size.IsWide() && (imm <= 255)) {
11980      if (cond.Is(al) || AllowStronglyDiscouraged()) {
11981        EmitT32_16(0xde00 | imm);
11982        AdvanceIT();
11983        return;
11984      }
11985    }
11986    // UDF{<c>}{<q>} {#}<imm> ; T2
11987    if (!size.IsNarrow() && (imm <= 65535)) {
11988      if (cond.Is(al) || AllowStronglyDiscouraged()) {
11989        EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
11990        AdvanceIT();
11991        return;
11992      }
11993    }
11994  } else {
11995    // UDF{<c>}{<q>} {#}<imm> ; A1
11996    if ((imm <= 65535)) {
11997      if (cond.Is(al) || AllowStronglyDiscouraged()) {
11998        EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
11999        return;
12000      }
12001    }
12002  }
12003  Delegate(kUdf, &Assembler::udf, cond, size, imm);
12004}
12005
12006void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
12007  VIXL_ASSERT(AllowAssembler());
12008  CheckIT(cond);
12009  if (IsUsingT32()) {
12010    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12011    EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12012               rm.GetCode());
12013    AdvanceIT();
12014    return;
12015  } else {
12016    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12017    if (cond.IsNotNever()) {
12018      EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12019              rn.GetCode() | (rm.GetCode() << 8));
12020      return;
12021    }
12022  }
12023  Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
12024}
12025
12026void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
12027  VIXL_ASSERT(AllowAssembler());
12028  CheckIT(cond);
12029  if (IsUsingT32()) {
12030    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12031    EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12032               rm.GetCode());
12033    AdvanceIT();
12034    return;
12035  } else {
12036    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12037    if (cond.IsNotNever()) {
12038      EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12039              (rn.GetCode() << 16) | rm.GetCode());
12040      return;
12041    }
12042  }
12043  Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
12044}
12045
12046void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
12047  VIXL_ASSERT(AllowAssembler());
12048  CheckIT(cond);
12049  if (IsUsingT32()) {
12050    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12051    EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12052               rm.GetCode());
12053    AdvanceIT();
12054    return;
12055  } else {
12056    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12057    if (cond.IsNotNever()) {
12058      EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12059              (rn.GetCode() << 16) | rm.GetCode());
12060      return;
12061    }
12062  }
12063  Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
12064}
12065
12066void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
12067  VIXL_ASSERT(AllowAssembler());
12068  CheckIT(cond);
12069  if (IsUsingT32()) {
12070    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12071    EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12072               rm.GetCode());
12073    AdvanceIT();
12074    return;
12075  } else {
12076    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12077    if (cond.IsNotNever()) {
12078      EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12079              (rn.GetCode() << 16) | rm.GetCode());
12080      return;
12081    }
12082  }
12083  Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
12084}
12085
12086void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
12087  VIXL_ASSERT(AllowAssembler());
12088  CheckIT(cond);
12089  if (IsUsingT32()) {
12090    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12091    EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12092               rm.GetCode());
12093    AdvanceIT();
12094    return;
12095  } else {
12096    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12097    if (cond.IsNotNever()) {
12098      EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12099              (rn.GetCode() << 16) | rm.GetCode());
12100      return;
12101    }
12102  }
12103  Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
12104}
12105
12106void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
12107  VIXL_ASSERT(AllowAssembler());
12108  CheckIT(cond);
12109  if (IsUsingT32()) {
12110    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12111    EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12112               rm.GetCode());
12113    AdvanceIT();
12114    return;
12115  } else {
12116    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12117    if (cond.IsNotNever()) {
12118      EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12119              (rn.GetCode() << 16) | rm.GetCode());
12120      return;
12121    }
12122  }
12123  Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
12124}
12125
12126void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
12127  VIXL_ASSERT(AllowAssembler());
12128  CheckIT(cond);
12129  if (IsUsingT32()) {
12130    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12131    EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12132               rm.GetCode());
12133    AdvanceIT();
12134    return;
12135  } else {
12136    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12137    if (cond.IsNotNever()) {
12138      EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12139              (rn.GetCode() << 16) | rm.GetCode());
12140      return;
12141    }
12142  }
12143  Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
12144}
12145
12146void Assembler::umaal(
12147    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12148  VIXL_ASSERT(AllowAssembler());
12149  CheckIT(cond);
12150  if (IsUsingT32()) {
12151    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12152    EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12153               (rn.GetCode() << 16) | rm.GetCode());
12154    AdvanceIT();
12155    return;
12156  } else {
12157    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12158    if (cond.IsNotNever()) {
12159      EmitA32(0x00400090U | (cond.GetCondition() << 28) |
12160              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12161              (rm.GetCode() << 8));
12162      return;
12163    }
12164  }
12165  Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
12166}
12167
12168void Assembler::umlal(
12169    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12170  VIXL_ASSERT(AllowAssembler());
12171  CheckIT(cond);
12172  if (IsUsingT32()) {
12173    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12174    EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12175               (rn.GetCode() << 16) | rm.GetCode());
12176    AdvanceIT();
12177    return;
12178  } else {
12179    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12180    if (cond.IsNotNever()) {
12181      EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
12182              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12183              (rm.GetCode() << 8));
12184      return;
12185    }
12186  }
12187  Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
12188}
12189
12190void Assembler::umlals(
12191    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12192  VIXL_ASSERT(AllowAssembler());
12193  CheckIT(cond);
12194  if (IsUsingA32()) {
12195    // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12196    if (cond.IsNotNever()) {
12197      EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
12198              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12199              (rm.GetCode() << 8));
12200      return;
12201    }
12202  }
12203  Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
12204}
12205
12206void Assembler::umull(
12207    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12208  VIXL_ASSERT(AllowAssembler());
12209  CheckIT(cond);
12210  if (IsUsingT32()) {
12211    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12212    EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12213               (rn.GetCode() << 16) | rm.GetCode());
12214    AdvanceIT();
12215    return;
12216  } else {
12217    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12218    if (cond.IsNotNever()) {
12219      EmitA32(0x00800090U | (cond.GetCondition() << 28) |
12220              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12221              (rm.GetCode() << 8));
12222      return;
12223    }
12224  }
12225  Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
12226}
12227
12228void Assembler::umulls(
12229    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12230  VIXL_ASSERT(AllowAssembler());
12231  CheckIT(cond);
12232  if (IsUsingA32()) {
12233    // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12234    if (cond.IsNotNever()) {
12235      EmitA32(0x00900090U | (cond.GetCondition() << 28) |
12236              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12237              (rm.GetCode() << 8));
12238      return;
12239    }
12240  }
12241  Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
12242}
12243
12244void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
12245  VIXL_ASSERT(AllowAssembler());
12246  CheckIT(cond);
12247  if (IsUsingT32()) {
12248    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12249    EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12250               rm.GetCode());
12251    AdvanceIT();
12252    return;
12253  } else {
12254    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12255    if (cond.IsNotNever()) {
12256      EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12257              (rn.GetCode() << 16) | rm.GetCode());
12258      return;
12259    }
12260  }
12261  Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
12262}
12263
12264void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
12265  VIXL_ASSERT(AllowAssembler());
12266  CheckIT(cond);
12267  if (IsUsingT32()) {
12268    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12269    EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12270               rm.GetCode());
12271    AdvanceIT();
12272    return;
12273  } else {
12274    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12275    if (cond.IsNotNever()) {
12276      EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12277              (rn.GetCode() << 16) | rm.GetCode());
12278      return;
12279    }
12280  }
12281  Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
12282}
12283
12284void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
12285  VIXL_ASSERT(AllowAssembler());
12286  CheckIT(cond);
12287  if (IsUsingT32()) {
12288    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12289    EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12290               rm.GetCode());
12291    AdvanceIT();
12292    return;
12293  } else {
12294    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12295    if (cond.IsNotNever()) {
12296      EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12297              (rn.GetCode() << 16) | rm.GetCode());
12298      return;
12299    }
12300  }
12301  Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
12302}
12303
12304void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
12305  VIXL_ASSERT(AllowAssembler());
12306  CheckIT(cond);
12307  if (IsUsingT32()) {
12308    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12309    EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12310               rm.GetCode());
12311    AdvanceIT();
12312    return;
12313  } else {
12314    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12315    if (cond.IsNotNever()) {
12316      EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12317              (rn.GetCode() << 16) | rm.GetCode());
12318      return;
12319    }
12320  }
12321  Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
12322}
12323
12324void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
12325  VIXL_ASSERT(AllowAssembler());
12326  CheckIT(cond);
12327  if (IsUsingT32()) {
12328    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12329    EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12330               rm.GetCode());
12331    AdvanceIT();
12332    return;
12333  } else {
12334    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12335    if (cond.IsNotNever()) {
12336      EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12337              (rn.GetCode() << 16) | rm.GetCode());
12338      return;
12339    }
12340  }
12341  Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
12342}
12343
12344void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
12345  VIXL_ASSERT(AllowAssembler());
12346  CheckIT(cond);
12347  if (IsUsingT32()) {
12348    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12349    EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12350               rm.GetCode());
12351    AdvanceIT();
12352    return;
12353  } else {
12354    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12355    if (cond.IsNotNever()) {
12356      EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12357              (rn.GetCode() << 16) | rm.GetCode());
12358      return;
12359    }
12360  }
12361  Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
12362}
12363
12364void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
12365  VIXL_ASSERT(AllowAssembler());
12366  CheckIT(cond);
12367  if (IsUsingT32()) {
12368    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12369    EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12370               rm.GetCode());
12371    AdvanceIT();
12372    return;
12373  } else {
12374    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12375    if (cond.IsNotNever()) {
12376      EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12377              rn.GetCode() | (rm.GetCode() << 8));
12378      return;
12379    }
12380  }
12381  Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
12382}
12383
12384void Assembler::usada8(
12385    Condition cond, Register rd, Register rn, Register rm, Register ra) {
12386  VIXL_ASSERT(AllowAssembler());
12387  CheckIT(cond);
12388  if (IsUsingT32()) {
12389    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
12390    if (!ra.Is(pc)) {
12391      EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12392                 rm.GetCode() | (ra.GetCode() << 12));
12393      AdvanceIT();
12394      return;
12395    }
12396  } else {
12397    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
12398    if (cond.IsNotNever() && !ra.Is(pc)) {
12399      EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12400              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
12401      return;
12402    }
12403  }
12404  Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
12405}
12406
12407void Assembler::usat(Condition cond,
12408                     Register rd,
12409                     uint32_t imm,
12410                     const Operand& operand) {
12411  VIXL_ASSERT(AllowAssembler());
12412  CheckIT(cond);
12413  if (operand.IsImmediateShiftedRegister()) {
12414    Register rn = operand.GetBaseRegister();
12415    Shift shift = operand.GetShift();
12416    uint32_t amount = operand.GetShiftAmount();
12417    if (IsUsingT32()) {
12418      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
12419      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31)) {
12420        EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
12421                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
12422                   ((amount & 0x1c) << 10));
12423        AdvanceIT();
12424        return;
12425      }
12426      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
12427      if ((imm <= 31) && shift.IsLSL() && (amount <= 31)) {
12428        EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
12429                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
12430                   ((amount & 0x1c) << 10));
12431        AdvanceIT();
12432        return;
12433      }
12434    } else {
12435      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
12436      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
12437          cond.IsNotNever()) {
12438        uint32_t amount_ = amount % 32;
12439        EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
12440                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
12441                (amount_ << 7));
12442        return;
12443      }
12444      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
12445      if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever()) {
12446        EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
12447                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
12448                (amount << 7));
12449        return;
12450      }
12451    }
12452  }
12453  Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
12454}
12455
12456void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
12457  VIXL_ASSERT(AllowAssembler());
12458  CheckIT(cond);
12459  if (IsUsingT32()) {
12460    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
12461    if ((imm <= 15)) {
12462      EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
12463                 (rn.GetCode() << 16));
12464      AdvanceIT();
12465      return;
12466    }
12467  } else {
12468    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
12469    if ((imm <= 15) && cond.IsNotNever()) {
12470      EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12471              (imm << 16) | rn.GetCode());
12472      return;
12473    }
12474  }
12475  Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
12476}
12477
12478void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
12479  VIXL_ASSERT(AllowAssembler());
12480  CheckIT(cond);
12481  if (IsUsingT32()) {
12482    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12483    EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12484               rm.GetCode());
12485    AdvanceIT();
12486    return;
12487  } else {
12488    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12489    if (cond.IsNotNever()) {
12490      EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12491              (rn.GetCode() << 16) | rm.GetCode());
12492      return;
12493    }
12494  }
12495  Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
12496}
12497
12498void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
12499  VIXL_ASSERT(AllowAssembler());
12500  CheckIT(cond);
12501  if (IsUsingT32()) {
12502    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12503    EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12504               rm.GetCode());
12505    AdvanceIT();
12506    return;
12507  } else {
12508    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12509    if (cond.IsNotNever()) {
12510      EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12511              (rn.GetCode() << 16) | rm.GetCode());
12512      return;
12513    }
12514  }
12515  Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
12516}
12517
12518void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
12519  VIXL_ASSERT(AllowAssembler());
12520  CheckIT(cond);
12521  if (IsUsingT32()) {
12522    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12523    EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12524               rm.GetCode());
12525    AdvanceIT();
12526    return;
12527  } else {
12528    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12529    if (cond.IsNotNever()) {
12530      EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12531              (rn.GetCode() << 16) | rm.GetCode());
12532      return;
12533    }
12534  }
12535  Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
12536}
12537
12538void Assembler::uxtab(Condition cond,
12539                      Register rd,
12540                      Register rn,
12541                      const Operand& operand) {
12542  VIXL_ASSERT(AllowAssembler());
12543  CheckIT(cond);
12544  if (operand.IsImmediateShiftedRegister()) {
12545    Register rm = operand.GetBaseRegister();
12546    Shift shift = operand.GetShift();
12547    uint32_t amount = operand.GetShiftAmount();
12548    if (IsUsingT32()) {
12549      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12550      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12551          ((amount % 8) == 0) && !rn.Is(pc)) {
12552        uint32_t amount_ = amount / 8;
12553        EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12554                   rm.GetCode() | (amount_ << 4));
12555        AdvanceIT();
12556        return;
12557      }
12558    } else {
12559      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12560      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12561          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12562        uint32_t amount_ = amount / 8;
12563        EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
12564                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12565                (amount_ << 10));
12566        return;
12567      }
12568    }
12569  }
12570  Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
12571}
12572
12573void Assembler::uxtab16(Condition cond,
12574                        Register rd,
12575                        Register rn,
12576                        const Operand& operand) {
12577  VIXL_ASSERT(AllowAssembler());
12578  CheckIT(cond);
12579  if (operand.IsImmediateShiftedRegister()) {
12580    Register rm = operand.GetBaseRegister();
12581    Shift shift = operand.GetShift();
12582    uint32_t amount = operand.GetShiftAmount();
12583    if (IsUsingT32()) {
12584      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12585      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12586          ((amount % 8) == 0) && !rn.Is(pc)) {
12587        uint32_t amount_ = amount / 8;
12588        EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12589                   rm.GetCode() | (amount_ << 4));
12590        AdvanceIT();
12591        return;
12592      }
12593    } else {
12594      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12595      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12596          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12597        uint32_t amount_ = amount / 8;
12598        EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
12599                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12600                (amount_ << 10));
12601        return;
12602      }
12603    }
12604  }
12605  Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
12606}
12607
12608void Assembler::uxtah(Condition cond,
12609                      Register rd,
12610                      Register rn,
12611                      const Operand& operand) {
12612  VIXL_ASSERT(AllowAssembler());
12613  CheckIT(cond);
12614  if (operand.IsImmediateShiftedRegister()) {
12615    Register rm = operand.GetBaseRegister();
12616    Shift shift = operand.GetShift();
12617    uint32_t amount = operand.GetShiftAmount();
12618    if (IsUsingT32()) {
12619      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12620      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12621          ((amount % 8) == 0) && !rn.Is(pc)) {
12622        uint32_t amount_ = amount / 8;
12623        EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12624                   rm.GetCode() | (amount_ << 4));
12625        AdvanceIT();
12626        return;
12627      }
12628    } else {
12629      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12630      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12631          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12632        uint32_t amount_ = amount / 8;
12633        EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
12634                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12635                (amount_ << 10));
12636        return;
12637      }
12638    }
12639  }
12640  Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
12641}
12642
12643void Assembler::uxtb(Condition cond,
12644                     EncodingSize size,
12645                     Register rd,
12646                     const Operand& operand) {
12647  VIXL_ASSERT(AllowAssembler());
12648  CheckIT(cond);
12649  if (operand.IsImmediateShiftedRegister()) {
12650    Register rm = operand.GetBaseRegister();
12651    if (operand.IsPlainRegister()) {
12652      if (IsUsingT32()) {
12653        // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12654        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12655          EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
12656          AdvanceIT();
12657          return;
12658        }
12659      }
12660    }
12661    Shift shift = operand.GetShift();
12662    uint32_t amount = operand.GetShiftAmount();
12663    if (IsUsingT32()) {
12664      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12665      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12666          (amount <= 24) && ((amount % 8) == 0)) {
12667        uint32_t amount_ = amount / 8;
12668        EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12669                   (amount_ << 4));
12670        AdvanceIT();
12671        return;
12672      }
12673    } else {
12674      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12675      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12676          ((amount % 8) == 0) && cond.IsNotNever()) {
12677        uint32_t amount_ = amount / 8;
12678        EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
12679                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12680        return;
12681      }
12682    }
12683  }
12684  Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
12685}
12686
12687void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
12688  VIXL_ASSERT(AllowAssembler());
12689  CheckIT(cond);
12690  if (operand.IsImmediateShiftedRegister()) {
12691    Register rm = operand.GetBaseRegister();
12692    Shift shift = operand.GetShift();
12693    uint32_t amount = operand.GetShiftAmount();
12694    if (IsUsingT32()) {
12695      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12696      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12697          ((amount % 8) == 0)) {
12698        uint32_t amount_ = amount / 8;
12699        EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12700                   (amount_ << 4));
12701        AdvanceIT();
12702        return;
12703      }
12704    } else {
12705      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12706      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12707          ((amount % 8) == 0) && cond.IsNotNever()) {
12708        uint32_t amount_ = amount / 8;
12709        EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
12710                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12711        return;
12712      }
12713    }
12714  }
12715  Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
12716}
12717
12718void Assembler::uxth(Condition cond,
12719                     EncodingSize size,
12720                     Register rd,
12721                     const Operand& operand) {
12722  VIXL_ASSERT(AllowAssembler());
12723  CheckIT(cond);
12724  if (operand.IsImmediateShiftedRegister()) {
12725    Register rm = operand.GetBaseRegister();
12726    if (operand.IsPlainRegister()) {
12727      if (IsUsingT32()) {
12728        // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12729        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12730          EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
12731          AdvanceIT();
12732          return;
12733        }
12734      }
12735    }
12736    Shift shift = operand.GetShift();
12737    uint32_t amount = operand.GetShiftAmount();
12738    if (IsUsingT32()) {
12739      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12740      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12741          (amount <= 24) && ((amount % 8) == 0)) {
12742        uint32_t amount_ = amount / 8;
12743        EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12744                   (amount_ << 4));
12745        AdvanceIT();
12746        return;
12747      }
12748    } else {
12749      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12750      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12751          ((amount % 8) == 0) && cond.IsNotNever()) {
12752        uint32_t amount_ = amount / 8;
12753        EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
12754                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12755        return;
12756      }
12757    }
12758  }
12759  Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
12760}
12761
12762void Assembler::vaba(
12763    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
12764  VIXL_ASSERT(AllowAssembler());
12765  CheckIT(cond);
12766  Dt_U_size_1 encoded_dt(dt);
12767  if (IsUsingT32()) {
12768    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
12769    if (encoded_dt.IsValid()) {
12770      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12771        EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12772                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12773                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12774        AdvanceIT();
12775        return;
12776      }
12777    }
12778  } else {
12779    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
12780    if (encoded_dt.IsValid()) {
12781      if (cond.Is(al)) {
12782        EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12783                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12784                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12785        return;
12786      }
12787    }
12788  }
12789  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
12790}
12791
12792void Assembler::vaba(
12793    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
12794  VIXL_ASSERT(AllowAssembler());
12795  CheckIT(cond);
12796  Dt_U_size_1 encoded_dt(dt);
12797  if (IsUsingT32()) {
12798    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
12799    if (encoded_dt.IsValid()) {
12800      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12801        EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12802                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12803                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12804        AdvanceIT();
12805        return;
12806      }
12807    }
12808  } else {
12809    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
12810    if (encoded_dt.IsValid()) {
12811      if (cond.Is(al)) {
12812        EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12813                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12814                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12815        return;
12816      }
12817    }
12818  }
12819  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
12820}
12821
12822void Assembler::vabal(
12823    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
12824  VIXL_ASSERT(AllowAssembler());
12825  CheckIT(cond);
12826  Dt_U_size_1 encoded_dt(dt);
12827  if (IsUsingT32()) {
12828    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
12829    if (encoded_dt.IsValid()) {
12830      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12831        EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12832                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12833                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12834        AdvanceIT();
12835        return;
12836      }
12837    }
12838  } else {
12839    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
12840    if (encoded_dt.IsValid()) {
12841      if (cond.Is(al)) {
12842        EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12843                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12844                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12845        return;
12846      }
12847    }
12848  }
12849  Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
12850}
12851
12852void Assembler::vabd(
12853    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
12854  VIXL_ASSERT(AllowAssembler());
12855  CheckIT(cond);
12856  Dt_U_size_1 encoded_dt(dt);
12857  if (IsUsingT32()) {
12858    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
12859    if (dt.Is(F32)) {
12860      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12861        EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12862                   rm.Encode(5, 0));
12863        AdvanceIT();
12864        return;
12865      }
12866    }
12867    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
12868    if (encoded_dt.IsValid()) {
12869      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12870        EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12871                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12872                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12873        AdvanceIT();
12874        return;
12875      }
12876    }
12877  } else {
12878    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
12879    if (dt.Is(F32)) {
12880      if (cond.Is(al)) {
12881        EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12882                rm.Encode(5, 0));
12883        return;
12884      }
12885    }
12886    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
12887    if (encoded_dt.IsValid()) {
12888      if (cond.Is(al)) {
12889        EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12890                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12891                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12892        return;
12893      }
12894    }
12895  }
12896  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
12897}
12898
12899void Assembler::vabd(
12900    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
12901  VIXL_ASSERT(AllowAssembler());
12902  CheckIT(cond);
12903  Dt_U_size_1 encoded_dt(dt);
12904  if (IsUsingT32()) {
12905    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
12906    if (dt.Is(F32)) {
12907      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12908        EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12909                   rm.Encode(5, 0));
12910        AdvanceIT();
12911        return;
12912      }
12913    }
12914    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
12915    if (encoded_dt.IsValid()) {
12916      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12917        EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12918                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12919                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12920        AdvanceIT();
12921        return;
12922      }
12923    }
12924  } else {
12925    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
12926    if (dt.Is(F32)) {
12927      if (cond.Is(al)) {
12928        EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12929                rm.Encode(5, 0));
12930        return;
12931      }
12932    }
12933    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
12934    if (encoded_dt.IsValid()) {
12935      if (cond.Is(al)) {
12936        EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12937                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12938                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12939        return;
12940      }
12941    }
12942  }
12943  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
12944}
12945
12946void Assembler::vabdl(
12947    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
12948  VIXL_ASSERT(AllowAssembler());
12949  CheckIT(cond);
12950  Dt_U_size_1 encoded_dt(dt);
12951  if (IsUsingT32()) {
12952    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
12953    if (encoded_dt.IsValid()) {
12954      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12955        EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12956                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12957                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12958        AdvanceIT();
12959        return;
12960      }
12961    }
12962  } else {
12963    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
12964    if (encoded_dt.IsValid()) {
12965      if (cond.Is(al)) {
12966        EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12967                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12968                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12969        return;
12970      }
12971    }
12972  }
12973  Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
12974}
12975
12976void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
12977  VIXL_ASSERT(AllowAssembler());
12978  CheckIT(cond);
12979  Dt_F_size_1 encoded_dt(dt);
12980  if (IsUsingT32()) {
12981    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
12982    if (encoded_dt.IsValid()) {
12983      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12984        EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
12985                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
12986                   rd.Encode(22, 12) | rm.Encode(5, 0));
12987        AdvanceIT();
12988        return;
12989      }
12990    }
12991    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
12992    if (dt.Is(F64)) {
12993      EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
12994      AdvanceIT();
12995      return;
12996    }
12997  } else {
12998    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
12999    if (encoded_dt.IsValid()) {
13000      if (cond.Is(al)) {
13001        EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13002                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13003                rd.Encode(22, 12) | rm.Encode(5, 0));
13004        return;
13005      }
13006    }
13007    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
13008    if (dt.Is(F64) && cond.IsNotNever()) {
13009      EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13010              rm.Encode(5, 0));
13011      return;
13012    }
13013  }
13014  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13015}
13016
13017void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
13018  VIXL_ASSERT(AllowAssembler());
13019  CheckIT(cond);
13020  Dt_F_size_1 encoded_dt(dt);
13021  if (IsUsingT32()) {
13022    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
13023    if (encoded_dt.IsValid()) {
13024      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13025        EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13026                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13027                   rd.Encode(22, 12) | rm.Encode(5, 0));
13028        AdvanceIT();
13029        return;
13030      }
13031    }
13032  } else {
13033    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
13034    if (encoded_dt.IsValid()) {
13035      if (cond.Is(al)) {
13036        EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13037                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13038                rd.Encode(22, 12) | rm.Encode(5, 0));
13039        return;
13040      }
13041    }
13042  }
13043  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13044}
13045
13046void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
13047  VIXL_ASSERT(AllowAssembler());
13048  CheckIT(cond);
13049  if (IsUsingT32()) {
13050    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
13051    if (dt.Is(F32)) {
13052      EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
13053      AdvanceIT();
13054      return;
13055    }
13056  } else {
13057    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
13058    if (dt.Is(F32) && cond.IsNotNever()) {
13059      EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13060              rm.Encode(5, 0));
13061      return;
13062    }
13063  }
13064  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13065}
13066
13067void Assembler::vacge(
13068    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13069  VIXL_ASSERT(AllowAssembler());
13070  CheckIT(cond);
13071  if (IsUsingT32()) {
13072    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13073    if (dt.Is(F32)) {
13074      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13075        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13076                   rm.Encode(5, 0));
13077        AdvanceIT();
13078        return;
13079      }
13080    }
13081  } else {
13082    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13083    if (dt.Is(F32)) {
13084      if (cond.Is(al)) {
13085        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13086                rm.Encode(5, 0));
13087        return;
13088      }
13089    }
13090  }
13091  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
13092}
13093
13094void Assembler::vacge(
13095    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13096  VIXL_ASSERT(AllowAssembler());
13097  CheckIT(cond);
13098  if (IsUsingT32()) {
13099    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13100    if (dt.Is(F32)) {
13101      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13102        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13103                   rm.Encode(5, 0));
13104        AdvanceIT();
13105        return;
13106      }
13107    }
13108  } else {
13109    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13110    if (dt.Is(F32)) {
13111      if (cond.Is(al)) {
13112        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13113                rm.Encode(5, 0));
13114        return;
13115      }
13116    }
13117  }
13118  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
13119}
13120
13121void Assembler::vacgt(
13122    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13123  VIXL_ASSERT(AllowAssembler());
13124  CheckIT(cond);
13125  if (IsUsingT32()) {
13126    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13127    if (dt.Is(F32)) {
13128      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13129        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13130                   rm.Encode(5, 0));
13131        AdvanceIT();
13132        return;
13133      }
13134    }
13135  } else {
13136    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13137    if (dt.Is(F32)) {
13138      if (cond.Is(al)) {
13139        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13140                rm.Encode(5, 0));
13141        return;
13142      }
13143    }
13144  }
13145  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
13146}
13147
13148void Assembler::vacgt(
13149    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13150  VIXL_ASSERT(AllowAssembler());
13151  CheckIT(cond);
13152  if (IsUsingT32()) {
13153    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13154    if (dt.Is(F32)) {
13155      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13156        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13157                   rm.Encode(5, 0));
13158        AdvanceIT();
13159        return;
13160      }
13161    }
13162  } else {
13163    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13164    if (dt.Is(F32)) {
13165      if (cond.Is(al)) {
13166        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13167                rm.Encode(5, 0));
13168        return;
13169      }
13170    }
13171  }
13172  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
13173}
13174
13175void Assembler::vacle(
13176    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13177  VIXL_ASSERT(AllowAssembler());
13178  CheckIT(cond);
13179  if (IsUsingT32()) {
13180    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13181    if (dt.Is(F32)) {
13182      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13183        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13184                   rm.Encode(5, 0));
13185        AdvanceIT();
13186        return;
13187      }
13188    }
13189  } else {
13190    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13191    if (dt.Is(F32)) {
13192      if (cond.Is(al)) {
13193        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13194                rm.Encode(5, 0));
13195        return;
13196      }
13197    }
13198  }
13199  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
13200}
13201
13202void Assembler::vacle(
13203    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13204  VIXL_ASSERT(AllowAssembler());
13205  CheckIT(cond);
13206  if (IsUsingT32()) {
13207    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13208    if (dt.Is(F32)) {
13209      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13210        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13211                   rm.Encode(5, 0));
13212        AdvanceIT();
13213        return;
13214      }
13215    }
13216  } else {
13217    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13218    if (dt.Is(F32)) {
13219      if (cond.Is(al)) {
13220        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13221                rm.Encode(5, 0));
13222        return;
13223      }
13224    }
13225  }
13226  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
13227}
13228
13229void Assembler::vaclt(
13230    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13231  VIXL_ASSERT(AllowAssembler());
13232  CheckIT(cond);
13233  if (IsUsingT32()) {
13234    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13235    if (dt.Is(F32)) {
13236      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13237        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13238                   rm.Encode(5, 0));
13239        AdvanceIT();
13240        return;
13241      }
13242    }
13243  } else {
13244    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13245    if (dt.Is(F32)) {
13246      if (cond.Is(al)) {
13247        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13248                rm.Encode(5, 0));
13249        return;
13250      }
13251    }
13252  }
13253  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
13254}
13255
13256void Assembler::vaclt(
13257    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13258  VIXL_ASSERT(AllowAssembler());
13259  CheckIT(cond);
13260  if (IsUsingT32()) {
13261    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13262    if (dt.Is(F32)) {
13263      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13264        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13265                   rm.Encode(5, 0));
13266        AdvanceIT();
13267        return;
13268      }
13269    }
13270  } else {
13271    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13272    if (dt.Is(F32)) {
13273      if (cond.Is(al)) {
13274        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13275                rm.Encode(5, 0));
13276        return;
13277      }
13278    }
13279  }
13280  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
13281}
13282
13283void Assembler::vadd(
13284    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13285  VIXL_ASSERT(AllowAssembler());
13286  CheckIT(cond);
13287  Dt_size_2 encoded_dt(dt);
13288  if (IsUsingT32()) {
13289    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13290    if (dt.Is(F32)) {
13291      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13292        EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13293                   rm.Encode(5, 0));
13294        AdvanceIT();
13295        return;
13296      }
13297    }
13298    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
13299    if (dt.Is(F64)) {
13300      EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13301                 rm.Encode(5, 0));
13302      AdvanceIT();
13303      return;
13304    }
13305    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13306    if (encoded_dt.IsValid()) {
13307      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13308        EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
13309                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13310        AdvanceIT();
13311        return;
13312      }
13313    }
13314  } else {
13315    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13316    if (dt.Is(F32)) {
13317      if (cond.Is(al)) {
13318        EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13319                rm.Encode(5, 0));
13320        return;
13321      }
13322    }
13323    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
13324    if (dt.Is(F64) && cond.IsNotNever()) {
13325      EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13326              rn.Encode(7, 16) | rm.Encode(5, 0));
13327      return;
13328    }
13329    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13330    if (encoded_dt.IsValid()) {
13331      if (cond.Is(al)) {
13332        EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
13333                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13334        return;
13335      }
13336    }
13337  }
13338  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13339}
13340
13341void Assembler::vadd(
13342    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13343  VIXL_ASSERT(AllowAssembler());
13344  CheckIT(cond);
13345  Dt_size_2 encoded_dt(dt);
13346  if (IsUsingT32()) {
13347    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13348    if (dt.Is(F32)) {
13349      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13350        EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13351                   rm.Encode(5, 0));
13352        AdvanceIT();
13353        return;
13354      }
13355    }
13356    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
13357    if (encoded_dt.IsValid()) {
13358      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13359        EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
13360                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13361        AdvanceIT();
13362        return;
13363      }
13364    }
13365  } else {
13366    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13367    if (dt.Is(F32)) {
13368      if (cond.Is(al)) {
13369        EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13370                rm.Encode(5, 0));
13371        return;
13372      }
13373    }
13374    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
13375    if (encoded_dt.IsValid()) {
13376      if (cond.Is(al)) {
13377        EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
13378                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13379        return;
13380      }
13381    }
13382  }
13383  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13384}
13385
13386void Assembler::vadd(
13387    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
13388  VIXL_ASSERT(AllowAssembler());
13389  CheckIT(cond);
13390  if (IsUsingT32()) {
13391    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
13392    if (dt.Is(F32)) {
13393      EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13394                 rm.Encode(5, 0));
13395      AdvanceIT();
13396      return;
13397    }
13398  } else {
13399    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
13400    if (dt.Is(F32) && cond.IsNotNever()) {
13401      EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13402              rn.Encode(7, 16) | rm.Encode(5, 0));
13403      return;
13404    }
13405  }
13406  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13407}
13408
13409void Assembler::vaddhn(
13410    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
13411  VIXL_ASSERT(AllowAssembler());
13412  CheckIT(cond);
13413  Dt_size_3 encoded_dt(dt);
13414  if (IsUsingT32()) {
13415    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
13416    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
13417      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13418        EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
13419                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13420        AdvanceIT();
13421        return;
13422      }
13423    }
13424  } else {
13425    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
13426    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
13427      if (cond.Is(al)) {
13428        EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
13429                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13430        return;
13431      }
13432    }
13433  }
13434  Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
13435}
13436
13437void Assembler::vaddl(
13438    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
13439  VIXL_ASSERT(AllowAssembler());
13440  CheckIT(cond);
13441  Dt_U_size_1 encoded_dt(dt);
13442  if (IsUsingT32()) {
13443    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13444    if (encoded_dt.IsValid()) {
13445      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13446        EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13447                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13448                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13449        AdvanceIT();
13450        return;
13451      }
13452    }
13453  } else {
13454    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13455    if (encoded_dt.IsValid()) {
13456      if (cond.Is(al)) {
13457        EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13458                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13459                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13460        return;
13461      }
13462    }
13463  }
13464  Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
13465}
13466
13467void Assembler::vaddw(
13468    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
13469  VIXL_ASSERT(AllowAssembler());
13470  CheckIT(cond);
13471  Dt_U_size_1 encoded_dt(dt);
13472  if (IsUsingT32()) {
13473    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
13474    if (encoded_dt.IsValid()) {
13475      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13476        EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13477                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13478                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13479        AdvanceIT();
13480        return;
13481      }
13482    }
13483  } else {
13484    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
13485    if (encoded_dt.IsValid()) {
13486      if (cond.Is(al)) {
13487        EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13488                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13489                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13490        return;
13491      }
13492    }
13493  }
13494  Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
13495}
13496
13497void Assembler::vand(Condition cond,
13498                     DataType dt,
13499                     DRegister rd,
13500                     DRegister rn,
13501                     const DOperand& operand) {
13502  VIXL_ASSERT(AllowAssembler());
13503  CheckIT(cond);
13504  if (operand.IsImmediate()) {
13505    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
13506    if (IsUsingT32()) {
13507      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
13508      if (encoded_dt.IsValid() && rd.Is(rn)) {
13509        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13510          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
13511                     rd.Encode(22, 12) |
13512                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13513                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13514                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13515          AdvanceIT();
13516          return;
13517        }
13518      }
13519    } else {
13520      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
13521      if (encoded_dt.IsValid() && rd.Is(rn)) {
13522        if (cond.Is(al)) {
13523          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
13524                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13525                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13526                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13527          return;
13528        }
13529      }
13530    }
13531  }
13532  if (operand.IsRegister()) {
13533    DRegister rm = operand.GetRegister();
13534    USE(dt);
13535    if (IsUsingT32()) {
13536      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13537      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13538        EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13539                   rm.Encode(5, 0));
13540        AdvanceIT();
13541        return;
13542      }
13543    } else {
13544      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13545      if (cond.Is(al)) {
13546        EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13547                rm.Encode(5, 0));
13548        return;
13549      }
13550    }
13551  }
13552  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
13553}
13554
13555void Assembler::vand(Condition cond,
13556                     DataType dt,
13557                     QRegister rd,
13558                     QRegister rn,
13559                     const QOperand& operand) {
13560  VIXL_ASSERT(AllowAssembler());
13561  CheckIT(cond);
13562  if (operand.IsImmediate()) {
13563    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
13564    if (IsUsingT32()) {
13565      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
13566      if (encoded_dt.IsValid() && rd.Is(rn)) {
13567        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13568          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
13569                     rd.Encode(22, 12) |
13570                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13571                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13572                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13573          AdvanceIT();
13574          return;
13575        }
13576      }
13577    } else {
13578      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
13579      if (encoded_dt.IsValid() && rd.Is(rn)) {
13580        if (cond.Is(al)) {
13581          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
13582                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13583                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13584                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13585          return;
13586        }
13587      }
13588    }
13589  }
13590  if (operand.IsRegister()) {
13591    QRegister rm = operand.GetRegister();
13592    USE(dt);
13593    if (IsUsingT32()) {
13594      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13595      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13596        EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13597                   rm.Encode(5, 0));
13598        AdvanceIT();
13599        return;
13600      }
13601    } else {
13602      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13603      if (cond.Is(al)) {
13604        EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13605                rm.Encode(5, 0));
13606        return;
13607      }
13608    }
13609  }
13610  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
13611}
13612
13613void Assembler::vbic(Condition cond,
13614                     DataType dt,
13615                     DRegister rd,
13616                     DRegister rn,
13617                     const DOperand& operand) {
13618  VIXL_ASSERT(AllowAssembler());
13619  CheckIT(cond);
13620  if (operand.IsImmediate()) {
13621    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
13622    if (IsUsingT32()) {
13623      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
13624      if (encoded_dt.IsValid() && rd.Is(rn)) {
13625        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13626          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
13627                     rd.Encode(22, 12) |
13628                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13629                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13630                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13631          AdvanceIT();
13632          return;
13633        }
13634      }
13635    } else {
13636      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
13637      if (encoded_dt.IsValid() && rd.Is(rn)) {
13638        if (cond.Is(al)) {
13639          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
13640                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13641                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13642                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13643          return;
13644        }
13645      }
13646    }
13647  }
13648  if (operand.IsRegister()) {
13649    DRegister rm = operand.GetRegister();
13650    USE(dt);
13651    if (IsUsingT32()) {
13652      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13653      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13654        EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13655                   rm.Encode(5, 0));
13656        AdvanceIT();
13657        return;
13658      }
13659    } else {
13660      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13661      if (cond.Is(al)) {
13662        EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13663                rm.Encode(5, 0));
13664        return;
13665      }
13666    }
13667  }
13668  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
13669}
13670
13671void Assembler::vbic(Condition cond,
13672                     DataType dt,
13673                     QRegister rd,
13674                     QRegister rn,
13675                     const QOperand& operand) {
13676  VIXL_ASSERT(AllowAssembler());
13677  CheckIT(cond);
13678  if (operand.IsImmediate()) {
13679    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
13680    if (IsUsingT32()) {
13681      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
13682      if (encoded_dt.IsValid() && rd.Is(rn)) {
13683        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13684          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
13685                     rd.Encode(22, 12) |
13686                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13687                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13688                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13689          AdvanceIT();
13690          return;
13691        }
13692      }
13693    } else {
13694      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
13695      if (encoded_dt.IsValid() && rd.Is(rn)) {
13696        if (cond.Is(al)) {
13697          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
13698                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13699                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13700                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13701          return;
13702        }
13703      }
13704    }
13705  }
13706  if (operand.IsRegister()) {
13707    QRegister rm = operand.GetRegister();
13708    USE(dt);
13709    if (IsUsingT32()) {
13710      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13711      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13712        EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13713                   rm.Encode(5, 0));
13714        AdvanceIT();
13715        return;
13716      }
13717    } else {
13718      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13719      if (cond.Is(al)) {
13720        EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13721                rm.Encode(5, 0));
13722        return;
13723      }
13724    }
13725  }
13726  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
13727}
13728
13729void Assembler::vbif(
13730    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13731  VIXL_ASSERT(AllowAssembler());
13732  CheckIT(cond);
13733  USE(dt);
13734  if (IsUsingT32()) {
13735    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13736    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13737      EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13738                 rm.Encode(5, 0));
13739      AdvanceIT();
13740      return;
13741    }
13742  } else {
13743    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13744    if (cond.Is(al)) {
13745      EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13746              rm.Encode(5, 0));
13747      return;
13748    }
13749  }
13750  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
13751}
13752
13753void Assembler::vbif(
13754    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13755  VIXL_ASSERT(AllowAssembler());
13756  CheckIT(cond);
13757  USE(dt);
13758  if (IsUsingT32()) {
13759    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13760    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13761      EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13762                 rm.Encode(5, 0));
13763      AdvanceIT();
13764      return;
13765    }
13766  } else {
13767    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13768    if (cond.Is(al)) {
13769      EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13770              rm.Encode(5, 0));
13771      return;
13772    }
13773  }
13774  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
13775}
13776
13777void Assembler::vbit(
13778    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13779  VIXL_ASSERT(AllowAssembler());
13780  CheckIT(cond);
13781  USE(dt);
13782  if (IsUsingT32()) {
13783    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13784    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13785      EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13786                 rm.Encode(5, 0));
13787      AdvanceIT();
13788      return;
13789    }
13790  } else {
13791    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13792    if (cond.Is(al)) {
13793      EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13794              rm.Encode(5, 0));
13795      return;
13796    }
13797  }
13798  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
13799}
13800
13801void Assembler::vbit(
13802    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13803  VIXL_ASSERT(AllowAssembler());
13804  CheckIT(cond);
13805  USE(dt);
13806  if (IsUsingT32()) {
13807    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13808    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13809      EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13810                 rm.Encode(5, 0));
13811      AdvanceIT();
13812      return;
13813    }
13814  } else {
13815    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13816    if (cond.Is(al)) {
13817      EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13818              rm.Encode(5, 0));
13819      return;
13820    }
13821  }
13822  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
13823}
13824
13825void Assembler::vbsl(
13826    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13827  VIXL_ASSERT(AllowAssembler());
13828  CheckIT(cond);
13829  USE(dt);
13830  if (IsUsingT32()) {
13831    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13832    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13833      EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13834                 rm.Encode(5, 0));
13835      AdvanceIT();
13836      return;
13837    }
13838  } else {
13839    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13840    if (cond.Is(al)) {
13841      EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13842              rm.Encode(5, 0));
13843      return;
13844    }
13845  }
13846  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
13847}
13848
13849void Assembler::vbsl(
13850    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13851  VIXL_ASSERT(AllowAssembler());
13852  CheckIT(cond);
13853  USE(dt);
13854  if (IsUsingT32()) {
13855    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13856    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13857      EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13858                 rm.Encode(5, 0));
13859      AdvanceIT();
13860      return;
13861    }
13862  } else {
13863    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13864    if (cond.Is(al)) {
13865      EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13866              rm.Encode(5, 0));
13867      return;
13868    }
13869  }
13870  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
13871}
13872
13873void Assembler::vceq(Condition cond,
13874                     DataType dt,
13875                     DRegister rd,
13876                     DRegister rm,
13877                     const DOperand& operand) {
13878  VIXL_ASSERT(AllowAssembler());
13879  CheckIT(cond);
13880  if (operand.IsImmediate()) {
13881    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
13882      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
13883      Dt_F_size_2 encoded_dt(dt);
13884      if (IsUsingT32()) {
13885        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
13886        if (encoded_dt.IsValid() && (imm == 0)) {
13887          if (cond.Is(al) || AllowStronglyDiscouraged()) {
13888            EmitT32_32(0xffb10100U |
13889                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13890                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13891                       rd.Encode(22, 12) | rm.Encode(5, 0));
13892            AdvanceIT();
13893            return;
13894          }
13895        }
13896      } else {
13897        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
13898        if (encoded_dt.IsValid() && (imm == 0)) {
13899          if (cond.Is(al)) {
13900            EmitA32(0xf3b10100U |
13901                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13902                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13903                    rd.Encode(22, 12) | rm.Encode(5, 0));
13904            return;
13905          }
13906        }
13907      }
13908    }
13909  }
13910  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
13911}
13912
13913void Assembler::vceq(Condition cond,
13914                     DataType dt,
13915                     QRegister rd,
13916                     QRegister rm,
13917                     const QOperand& operand) {
13918  VIXL_ASSERT(AllowAssembler());
13919  CheckIT(cond);
13920  if (operand.IsImmediate()) {
13921    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
13922      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
13923      Dt_F_size_2 encoded_dt(dt);
13924      if (IsUsingT32()) {
13925        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
13926        if (encoded_dt.IsValid() && (imm == 0)) {
13927          if (cond.Is(al) || AllowStronglyDiscouraged()) {
13928            EmitT32_32(0xffb10140U |
13929                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13930                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13931                       rd.Encode(22, 12) | rm.Encode(5, 0));
13932            AdvanceIT();
13933            return;
13934          }
13935        }
13936      } else {
13937        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
13938        if (encoded_dt.IsValid() && (imm == 0)) {
13939          if (cond.Is(al)) {
13940            EmitA32(0xf3b10140U |
13941                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13942                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13943                    rd.Encode(22, 12) | rm.Encode(5, 0));
13944            return;
13945          }
13946        }
13947      }
13948    }
13949  }
13950  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
13951}
13952
13953void Assembler::vceq(
13954    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13955  VIXL_ASSERT(AllowAssembler());
13956  CheckIT(cond);
13957  Dt_size_4 encoded_dt(dt);
13958  Dt_sz_1 encoded_dt_2(dt);
13959  if (IsUsingT32()) {
13960    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13961    if (encoded_dt.IsValid()) {
13962      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13963        EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
13964                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13965        AdvanceIT();
13966        return;
13967      }
13968    }
13969    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
13970    if (encoded_dt_2.IsValid()) {
13971      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13972        EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
13973                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13974        AdvanceIT();
13975        return;
13976      }
13977    }
13978  } else {
13979    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13980    if (encoded_dt.IsValid()) {
13981      if (cond.Is(al)) {
13982        EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
13983                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13984        return;
13985      }
13986    }
13987    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
13988    if (encoded_dt_2.IsValid()) {
13989      if (cond.Is(al)) {
13990        EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
13991                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13992        return;
13993      }
13994    }
13995  }
13996  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
13997}
13998
13999void Assembler::vceq(
14000    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14001  VIXL_ASSERT(AllowAssembler());
14002  CheckIT(cond);
14003  Dt_size_4 encoded_dt(dt);
14004  Dt_sz_1 encoded_dt_2(dt);
14005  if (IsUsingT32()) {
14006    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14007    if (encoded_dt.IsValid()) {
14008      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14009        EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
14010                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14011        AdvanceIT();
14012        return;
14013      }
14014    }
14015    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
14016    if (encoded_dt_2.IsValid()) {
14017      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14018        EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
14019                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14020        AdvanceIT();
14021        return;
14022      }
14023    }
14024  } else {
14025    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14026    if (encoded_dt.IsValid()) {
14027      if (cond.Is(al)) {
14028        EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
14029                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14030        return;
14031      }
14032    }
14033    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
14034    if (encoded_dt_2.IsValid()) {
14035      if (cond.Is(al)) {
14036        EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
14037                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14038        return;
14039      }
14040    }
14041  }
14042  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
14043}
14044
14045void Assembler::vcge(Condition cond,
14046                     DataType dt,
14047                     DRegister rd,
14048                     DRegister rm,
14049                     const DOperand& operand) {
14050  VIXL_ASSERT(AllowAssembler());
14051  CheckIT(cond);
14052  if (operand.IsImmediate()) {
14053    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14054      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14055      Dt_F_size_1 encoded_dt(dt);
14056      if (IsUsingT32()) {
14057        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14058        if (encoded_dt.IsValid() && (imm == 0)) {
14059          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14060            EmitT32_32(0xffb10080U |
14061                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14062                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14063                       rd.Encode(22, 12) | rm.Encode(5, 0));
14064            AdvanceIT();
14065            return;
14066          }
14067        }
14068      } else {
14069        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14070        if (encoded_dt.IsValid() && (imm == 0)) {
14071          if (cond.Is(al)) {
14072            EmitA32(0xf3b10080U |
14073                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14074                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14075                    rd.Encode(22, 12) | rm.Encode(5, 0));
14076            return;
14077          }
14078        }
14079      }
14080    }
14081  }
14082  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
14083}
14084
14085void Assembler::vcge(Condition cond,
14086                     DataType dt,
14087                     QRegister rd,
14088                     QRegister rm,
14089                     const QOperand& operand) {
14090  VIXL_ASSERT(AllowAssembler());
14091  CheckIT(cond);
14092  if (operand.IsImmediate()) {
14093    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14094      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14095      Dt_F_size_1 encoded_dt(dt);
14096      if (IsUsingT32()) {
14097        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14098        if (encoded_dt.IsValid() && (imm == 0)) {
14099          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14100            EmitT32_32(0xffb100c0U |
14101                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14102                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14103                       rd.Encode(22, 12) | rm.Encode(5, 0));
14104            AdvanceIT();
14105            return;
14106          }
14107        }
14108      } else {
14109        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14110        if (encoded_dt.IsValid() && (imm == 0)) {
14111          if (cond.Is(al)) {
14112            EmitA32(0xf3b100c0U |
14113                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14114                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14115                    rd.Encode(22, 12) | rm.Encode(5, 0));
14116            return;
14117          }
14118        }
14119      }
14120    }
14121  }
14122  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
14123}
14124
14125void Assembler::vcge(
14126    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14127  VIXL_ASSERT(AllowAssembler());
14128  CheckIT(cond);
14129  Dt_U_size_1 encoded_dt(dt);
14130  if (IsUsingT32()) {
14131    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14132    if (encoded_dt.IsValid()) {
14133      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14134        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14135                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14136                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14137        AdvanceIT();
14138        return;
14139      }
14140    }
14141    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14142    if (dt.Is(F32)) {
14143      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14144        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14145                   rm.Encode(5, 0));
14146        AdvanceIT();
14147        return;
14148      }
14149    }
14150  } else {
14151    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14152    if (encoded_dt.IsValid()) {
14153      if (cond.Is(al)) {
14154        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14155                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14156                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14157        return;
14158      }
14159    }
14160    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14161    if (dt.Is(F32)) {
14162      if (cond.Is(al)) {
14163        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14164                rm.Encode(5, 0));
14165        return;
14166      }
14167    }
14168  }
14169  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
14170}
14171
14172void Assembler::vcge(
14173    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14174  VIXL_ASSERT(AllowAssembler());
14175  CheckIT(cond);
14176  Dt_U_size_1 encoded_dt(dt);
14177  if (IsUsingT32()) {
14178    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14179    if (encoded_dt.IsValid()) {
14180      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14181        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14182                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14183                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14184        AdvanceIT();
14185        return;
14186      }
14187    }
14188    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14189    if (dt.Is(F32)) {
14190      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14191        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14192                   rm.Encode(5, 0));
14193        AdvanceIT();
14194        return;
14195      }
14196    }
14197  } else {
14198    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14199    if (encoded_dt.IsValid()) {
14200      if (cond.Is(al)) {
14201        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14202                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14203                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14204        return;
14205      }
14206    }
14207    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14208    if (dt.Is(F32)) {
14209      if (cond.Is(al)) {
14210        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14211                rm.Encode(5, 0));
14212        return;
14213      }
14214    }
14215  }
14216  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
14217}
14218
14219void Assembler::vcgt(Condition cond,
14220                     DataType dt,
14221                     DRegister rd,
14222                     DRegister rm,
14223                     const DOperand& operand) {
14224  VIXL_ASSERT(AllowAssembler());
14225  CheckIT(cond);
14226  if (operand.IsImmediate()) {
14227    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14228      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14229      Dt_F_size_1 encoded_dt(dt);
14230      if (IsUsingT32()) {
14231        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14232        if (encoded_dt.IsValid() && (imm == 0)) {
14233          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14234            EmitT32_32(0xffb10000U |
14235                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14236                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14237                       rd.Encode(22, 12) | rm.Encode(5, 0));
14238            AdvanceIT();
14239            return;
14240          }
14241        }
14242      } else {
14243        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14244        if (encoded_dt.IsValid() && (imm == 0)) {
14245          if (cond.Is(al)) {
14246            EmitA32(0xf3b10000U |
14247                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14248                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14249                    rd.Encode(22, 12) | rm.Encode(5, 0));
14250            return;
14251          }
14252        }
14253      }
14254    }
14255  }
14256  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
14257}
14258
14259void Assembler::vcgt(Condition cond,
14260                     DataType dt,
14261                     QRegister rd,
14262                     QRegister rm,
14263                     const QOperand& operand) {
14264  VIXL_ASSERT(AllowAssembler());
14265  CheckIT(cond);
14266  if (operand.IsImmediate()) {
14267    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14268      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14269      Dt_F_size_1 encoded_dt(dt);
14270      if (IsUsingT32()) {
14271        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14272        if (encoded_dt.IsValid() && (imm == 0)) {
14273          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14274            EmitT32_32(0xffb10040U |
14275                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14276                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14277                       rd.Encode(22, 12) | rm.Encode(5, 0));
14278            AdvanceIT();
14279            return;
14280          }
14281        }
14282      } else {
14283        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14284        if (encoded_dt.IsValid() && (imm == 0)) {
14285          if (cond.Is(al)) {
14286            EmitA32(0xf3b10040U |
14287                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14288                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14289                    rd.Encode(22, 12) | rm.Encode(5, 0));
14290            return;
14291          }
14292        }
14293      }
14294    }
14295  }
14296  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
14297}
14298
14299void Assembler::vcgt(
14300    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14301  VIXL_ASSERT(AllowAssembler());
14302  CheckIT(cond);
14303  Dt_U_size_1 encoded_dt(dt);
14304  if (IsUsingT32()) {
14305    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14306    if (encoded_dt.IsValid()) {
14307      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14308        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14309                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14310                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14311        AdvanceIT();
14312        return;
14313      }
14314    }
14315    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14316    if (dt.Is(F32)) {
14317      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14318        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14319                   rm.Encode(5, 0));
14320        AdvanceIT();
14321        return;
14322      }
14323    }
14324  } else {
14325    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14326    if (encoded_dt.IsValid()) {
14327      if (cond.Is(al)) {
14328        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14329                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14330                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14331        return;
14332      }
14333    }
14334    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14335    if (dt.Is(F32)) {
14336      if (cond.Is(al)) {
14337        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14338                rm.Encode(5, 0));
14339        return;
14340      }
14341    }
14342  }
14343  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
14344}
14345
14346void Assembler::vcgt(
14347    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14348  VIXL_ASSERT(AllowAssembler());
14349  CheckIT(cond);
14350  Dt_U_size_1 encoded_dt(dt);
14351  if (IsUsingT32()) {
14352    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14353    if (encoded_dt.IsValid()) {
14354      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14355        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14356                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14357                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14358        AdvanceIT();
14359        return;
14360      }
14361    }
14362    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14363    if (dt.Is(F32)) {
14364      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14365        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14366                   rm.Encode(5, 0));
14367        AdvanceIT();
14368        return;
14369      }
14370    }
14371  } else {
14372    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14373    if (encoded_dt.IsValid()) {
14374      if (cond.Is(al)) {
14375        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14376                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14377                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14378        return;
14379      }
14380    }
14381    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14382    if (dt.Is(F32)) {
14383      if (cond.Is(al)) {
14384        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14385                rm.Encode(5, 0));
14386        return;
14387      }
14388    }
14389  }
14390  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
14391}
14392
14393void Assembler::vcle(Condition cond,
14394                     DataType dt,
14395                     DRegister rd,
14396                     DRegister rm,
14397                     const DOperand& operand) {
14398  VIXL_ASSERT(AllowAssembler());
14399  CheckIT(cond);
14400  if (operand.IsImmediate()) {
14401    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14402      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14403      Dt_F_size_1 encoded_dt(dt);
14404      if (IsUsingT32()) {
14405        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14406        if (encoded_dt.IsValid() && (imm == 0)) {
14407          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14408            EmitT32_32(0xffb10180U |
14409                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14410                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14411                       rd.Encode(22, 12) | rm.Encode(5, 0));
14412            AdvanceIT();
14413            return;
14414          }
14415        }
14416      } else {
14417        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14418        if (encoded_dt.IsValid() && (imm == 0)) {
14419          if (cond.Is(al)) {
14420            EmitA32(0xf3b10180U |
14421                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14422                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14423                    rd.Encode(22, 12) | rm.Encode(5, 0));
14424            return;
14425          }
14426        }
14427      }
14428    }
14429  }
14430  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
14431}
14432
14433void Assembler::vcle(Condition cond,
14434                     DataType dt,
14435                     QRegister rd,
14436                     QRegister rm,
14437                     const QOperand& operand) {
14438  VIXL_ASSERT(AllowAssembler());
14439  CheckIT(cond);
14440  if (operand.IsImmediate()) {
14441    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14442      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14443      Dt_F_size_1 encoded_dt(dt);
14444      if (IsUsingT32()) {
14445        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14446        if (encoded_dt.IsValid() && (imm == 0)) {
14447          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14448            EmitT32_32(0xffb101c0U |
14449                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14450                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14451                       rd.Encode(22, 12) | rm.Encode(5, 0));
14452            AdvanceIT();
14453            return;
14454          }
14455        }
14456      } else {
14457        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14458        if (encoded_dt.IsValid() && (imm == 0)) {
14459          if (cond.Is(al)) {
14460            EmitA32(0xf3b101c0U |
14461                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14462                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14463                    rd.Encode(22, 12) | rm.Encode(5, 0));
14464            return;
14465          }
14466        }
14467      }
14468    }
14469  }
14470  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
14471}
14472
14473void Assembler::vcle(
14474    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14475  VIXL_ASSERT(AllowAssembler());
14476  CheckIT(cond);
14477  Dt_U_size_1 encoded_dt(dt);
14478  if (IsUsingT32()) {
14479    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14480    if (encoded_dt.IsValid()) {
14481      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14482        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14483                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14484                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14485        AdvanceIT();
14486        return;
14487      }
14488    }
14489    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14490    if (dt.Is(F32)) {
14491      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14492        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14493                   rm.Encode(5, 0));
14494        AdvanceIT();
14495        return;
14496      }
14497    }
14498  } else {
14499    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14500    if (encoded_dt.IsValid()) {
14501      if (cond.Is(al)) {
14502        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14503                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14504                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14505        return;
14506      }
14507    }
14508    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14509    if (dt.Is(F32)) {
14510      if (cond.Is(al)) {
14511        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14512                rm.Encode(5, 0));
14513        return;
14514      }
14515    }
14516  }
14517  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
14518}
14519
14520void Assembler::vcle(
14521    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14522  VIXL_ASSERT(AllowAssembler());
14523  CheckIT(cond);
14524  Dt_U_size_1 encoded_dt(dt);
14525  if (IsUsingT32()) {
14526    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14527    if (encoded_dt.IsValid()) {
14528      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14529        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14530                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14531                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14532        AdvanceIT();
14533        return;
14534      }
14535    }
14536    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14537    if (dt.Is(F32)) {
14538      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14539        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14540                   rm.Encode(5, 0));
14541        AdvanceIT();
14542        return;
14543      }
14544    }
14545  } else {
14546    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14547    if (encoded_dt.IsValid()) {
14548      if (cond.Is(al)) {
14549        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14550                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14551                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14552        return;
14553      }
14554    }
14555    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14556    if (dt.Is(F32)) {
14557      if (cond.Is(al)) {
14558        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14559                rm.Encode(5, 0));
14560        return;
14561      }
14562    }
14563  }
14564  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
14565}
14566
14567void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14568  VIXL_ASSERT(AllowAssembler());
14569  CheckIT(cond);
14570  Dt_size_5 encoded_dt(dt);
14571  if (IsUsingT32()) {
14572    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14573    if (encoded_dt.IsValid()) {
14574      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14575        EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
14576                   rd.Encode(22, 12) | rm.Encode(5, 0));
14577        AdvanceIT();
14578        return;
14579      }
14580    }
14581  } else {
14582    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14583    if (encoded_dt.IsValid()) {
14584      if (cond.Is(al)) {
14585        EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
14586                rd.Encode(22, 12) | rm.Encode(5, 0));
14587        return;
14588      }
14589    }
14590  }
14591  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
14592}
14593
14594void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
14595  VIXL_ASSERT(AllowAssembler());
14596  CheckIT(cond);
14597  Dt_size_5 encoded_dt(dt);
14598  if (IsUsingT32()) {
14599    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14600    if (encoded_dt.IsValid()) {
14601      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14602        EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
14603                   rd.Encode(22, 12) | rm.Encode(5, 0));
14604        AdvanceIT();
14605        return;
14606      }
14607    }
14608  } else {
14609    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14610    if (encoded_dt.IsValid()) {
14611      if (cond.Is(al)) {
14612        EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
14613                rd.Encode(22, 12) | rm.Encode(5, 0));
14614        return;
14615      }
14616    }
14617  }
14618  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
14619}
14620
14621void Assembler::vclt(Condition cond,
14622                     DataType dt,
14623                     DRegister rd,
14624                     DRegister rm,
14625                     const DOperand& operand) {
14626  VIXL_ASSERT(AllowAssembler());
14627  CheckIT(cond);
14628  if (operand.IsImmediate()) {
14629    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14630      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14631      Dt_F_size_1 encoded_dt(dt);
14632      if (IsUsingT32()) {
14633        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14634        if (encoded_dt.IsValid() && (imm == 0)) {
14635          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14636            EmitT32_32(0xffb10200U |
14637                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14638                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14639                       rd.Encode(22, 12) | rm.Encode(5, 0));
14640            AdvanceIT();
14641            return;
14642          }
14643        }
14644      } else {
14645        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14646        if (encoded_dt.IsValid() && (imm == 0)) {
14647          if (cond.Is(al)) {
14648            EmitA32(0xf3b10200U |
14649                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14650                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14651                    rd.Encode(22, 12) | rm.Encode(5, 0));
14652            return;
14653          }
14654        }
14655      }
14656    }
14657  }
14658  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
14659}
14660
14661void Assembler::vclt(Condition cond,
14662                     DataType dt,
14663                     QRegister rd,
14664                     QRegister rm,
14665                     const QOperand& operand) {
14666  VIXL_ASSERT(AllowAssembler());
14667  CheckIT(cond);
14668  if (operand.IsImmediate()) {
14669    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14670      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14671      Dt_F_size_1 encoded_dt(dt);
14672      if (IsUsingT32()) {
14673        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14674        if (encoded_dt.IsValid() && (imm == 0)) {
14675          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14676            EmitT32_32(0xffb10240U |
14677                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14678                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14679                       rd.Encode(22, 12) | rm.Encode(5, 0));
14680            AdvanceIT();
14681            return;
14682          }
14683        }
14684      } else {
14685        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14686        if (encoded_dt.IsValid() && (imm == 0)) {
14687          if (cond.Is(al)) {
14688            EmitA32(0xf3b10240U |
14689                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14690                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14691                    rd.Encode(22, 12) | rm.Encode(5, 0));
14692            return;
14693          }
14694        }
14695      }
14696    }
14697  }
14698  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
14699}
14700
14701void Assembler::vclt(
14702    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14703  VIXL_ASSERT(AllowAssembler());
14704  CheckIT(cond);
14705  Dt_U_size_1 encoded_dt(dt);
14706  if (IsUsingT32()) {
14707    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14708    if (encoded_dt.IsValid()) {
14709      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14710        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14711                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14712                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14713        AdvanceIT();
14714        return;
14715      }
14716    }
14717    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14718    if (dt.Is(F32)) {
14719      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14720        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14721                   rm.Encode(5, 0));
14722        AdvanceIT();
14723        return;
14724      }
14725    }
14726  } else {
14727    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14728    if (encoded_dt.IsValid()) {
14729      if (cond.Is(al)) {
14730        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14731                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14732                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14733        return;
14734      }
14735    }
14736    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14737    if (dt.Is(F32)) {
14738      if (cond.Is(al)) {
14739        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14740                rm.Encode(5, 0));
14741        return;
14742      }
14743    }
14744  }
14745  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
14746}
14747
14748void Assembler::vclt(
14749    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14750  VIXL_ASSERT(AllowAssembler());
14751  CheckIT(cond);
14752  Dt_U_size_1 encoded_dt(dt);
14753  if (IsUsingT32()) {
14754    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14755    if (encoded_dt.IsValid()) {
14756      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14757        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14758                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14759                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14760        AdvanceIT();
14761        return;
14762      }
14763    }
14764    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14765    if (dt.Is(F32)) {
14766      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14767        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14768                   rm.Encode(5, 0));
14769        AdvanceIT();
14770        return;
14771      }
14772    }
14773  } else {
14774    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14775    if (encoded_dt.IsValid()) {
14776      if (cond.Is(al)) {
14777        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14778                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14779                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14780        return;
14781      }
14782    }
14783    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14784    if (dt.Is(F32)) {
14785      if (cond.Is(al)) {
14786        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14787                rm.Encode(5, 0));
14788        return;
14789      }
14790    }
14791  }
14792  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
14793}
14794
14795void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14796  VIXL_ASSERT(AllowAssembler());
14797  CheckIT(cond);
14798  Dt_size_4 encoded_dt(dt);
14799  if (IsUsingT32()) {
14800    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14801    if (encoded_dt.IsValid()) {
14802      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14803        EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
14804                   rd.Encode(22, 12) | rm.Encode(5, 0));
14805        AdvanceIT();
14806        return;
14807      }
14808    }
14809  } else {
14810    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14811    if (encoded_dt.IsValid()) {
14812      if (cond.Is(al)) {
14813        EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
14814                rd.Encode(22, 12) | rm.Encode(5, 0));
14815        return;
14816      }
14817    }
14818  }
14819  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
14820}
14821
14822void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
14823  VIXL_ASSERT(AllowAssembler());
14824  CheckIT(cond);
14825  Dt_size_4 encoded_dt(dt);
14826  if (IsUsingT32()) {
14827    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14828    if (encoded_dt.IsValid()) {
14829      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14830        EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
14831                   rd.Encode(22, 12) | rm.Encode(5, 0));
14832        AdvanceIT();
14833        return;
14834      }
14835    }
14836  } else {
14837    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14838    if (encoded_dt.IsValid()) {
14839      if (cond.Is(al)) {
14840        EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
14841                rd.Encode(22, 12) | rm.Encode(5, 0));
14842        return;
14843      }
14844    }
14845  }
14846  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
14847}
14848
14849void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm) {
14850  VIXL_ASSERT(AllowAssembler());
14851  CheckIT(cond);
14852  if (IsUsingT32()) {
14853    // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
14854    if (dt.Is(F32)) {
14855      EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
14856      AdvanceIT();
14857      return;
14858    }
14859  } else {
14860    // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
14861    if (dt.Is(F32) && cond.IsNotNever()) {
14862      EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14863              rm.Encode(5, 0));
14864      return;
14865    }
14866  }
14867  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
14868}
14869
14870void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14871  VIXL_ASSERT(AllowAssembler());
14872  CheckIT(cond);
14873  if (IsUsingT32()) {
14874    // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
14875    if (dt.Is(F64)) {
14876      EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
14877      AdvanceIT();
14878      return;
14879    }
14880  } else {
14881    // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
14882    if (dt.Is(F64) && cond.IsNotNever()) {
14883      EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14884              rm.Encode(5, 0));
14885      return;
14886    }
14887  }
14888  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
14889}
14890
14891void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, double imm) {
14892  VIXL_ASSERT(AllowAssembler());
14893  CheckIT(cond);
14894  if (IsUsingT32()) {
14895    // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
14896    if (dt.Is(F32) && (imm == 0.0)) {
14897      EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
14898      AdvanceIT();
14899      return;
14900    }
14901  } else {
14902    // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
14903    if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
14904      EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14905      return;
14906    }
14907  }
14908  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
14909}
14910
14911void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, double imm) {
14912  VIXL_ASSERT(AllowAssembler());
14913  CheckIT(cond);
14914  if (IsUsingT32()) {
14915    // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
14916    if (dt.Is(F64) && (imm == 0.0)) {
14917      EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
14918      AdvanceIT();
14919      return;
14920    }
14921  } else {
14922    // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
14923    if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
14924      EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14925      return;
14926    }
14927  }
14928  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
14929}
14930
14931void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm) {
14932  VIXL_ASSERT(AllowAssembler());
14933  CheckIT(cond);
14934  if (IsUsingT32()) {
14935    // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
14936    if (dt.Is(F32)) {
14937      EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14938      AdvanceIT();
14939      return;
14940    }
14941  } else {
14942    // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
14943    if (dt.Is(F32) && cond.IsNotNever()) {
14944      EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14945              rm.Encode(5, 0));
14946      return;
14947    }
14948  }
14949  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
14950}
14951
14952void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14953  VIXL_ASSERT(AllowAssembler());
14954  CheckIT(cond);
14955  if (IsUsingT32()) {
14956    // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
14957    if (dt.Is(F64)) {
14958      EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14959      AdvanceIT();
14960      return;
14961    }
14962  } else {
14963    // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
14964    if (dt.Is(F64) && cond.IsNotNever()) {
14965      EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14966              rm.Encode(5, 0));
14967      return;
14968    }
14969  }
14970  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
14971}
14972
14973void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, double imm) {
14974  VIXL_ASSERT(AllowAssembler());
14975  CheckIT(cond);
14976  if (IsUsingT32()) {
14977    // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
14978    if (dt.Is(F32) && (imm == 0.0)) {
14979      EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
14980      AdvanceIT();
14981      return;
14982    }
14983  } else {
14984    // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
14985    if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
14986      EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14987      return;
14988    }
14989  }
14990  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
14991}
14992
14993void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, double imm) {
14994  VIXL_ASSERT(AllowAssembler());
14995  CheckIT(cond);
14996  if (IsUsingT32()) {
14997    // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
14998    if (dt.Is(F64) && (imm == 0.0)) {
14999      EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
15000      AdvanceIT();
15001      return;
15002    }
15003  } else {
15004    // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
15005    if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
15006      EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
15007      return;
15008    }
15009  }
15010  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
15011}
15012
15013void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
15014  VIXL_ASSERT(AllowAssembler());
15015  CheckIT(cond);
15016  if (IsUsingT32()) {
15017    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
15018    if (dt.Is(Untyped8)) {
15019      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15020        EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
15021        AdvanceIT();
15022        return;
15023      }
15024    }
15025  } else {
15026    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
15027    if (dt.Is(Untyped8)) {
15028      if (cond.Is(al)) {
15029        EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
15030        return;
15031      }
15032    }
15033  }
15034  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
15035}
15036
15037void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
15038  VIXL_ASSERT(AllowAssembler());
15039  CheckIT(cond);
15040  if (IsUsingT32()) {
15041    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
15042    if (dt.Is(Untyped8)) {
15043      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15044        EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
15045        AdvanceIT();
15046        return;
15047      }
15048    }
15049  } else {
15050    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
15051    if (dt.Is(Untyped8)) {
15052      if (cond.Is(al)) {
15053        EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
15054        return;
15055      }
15056    }
15057  }
15058  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
15059}
15060
15061void Assembler::vcvt(
15062    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
15063  VIXL_ASSERT(AllowAssembler());
15064  CheckIT(cond);
15065  Dt_op_2 encoded_dt(dt2);
15066  if (IsUsingT32()) {
15067    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
15068    if (dt1.Is(F64) && dt2.Is(F32)) {
15069      EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15070      AdvanceIT();
15071      return;
15072    }
15073    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
15074    if (dt1.Is(F64) && encoded_dt.IsValid()) {
15075      EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
15076                 rd.Encode(22, 12) | rm.Encode(5, 0));
15077      AdvanceIT();
15078      return;
15079    }
15080  } else {
15081    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
15082    if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
15083      EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15084              rm.Encode(5, 0));
15085      return;
15086    }
15087    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
15088    if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
15089      EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
15090              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
15091              rm.Encode(5, 0));
15092      return;
15093    }
15094  }
15095  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15096}
15097
15098void Assembler::vcvt(
15099    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15100  VIXL_ASSERT(AllowAssembler());
15101  CheckIT(cond);
15102  if (IsUsingT32()) {
15103    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
15104    if (dt1.Is(F32) && dt2.Is(F64)) {
15105      EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15106      AdvanceIT();
15107      return;
15108    }
15109    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
15110    if (dt1.Is(U32) && dt2.Is(F64)) {
15111      EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15112      AdvanceIT();
15113      return;
15114    }
15115    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
15116    if (dt1.Is(S32) && dt2.Is(F64)) {
15117      EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15118      AdvanceIT();
15119      return;
15120    }
15121  } else {
15122    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
15123    if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
15124      EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15125              rm.Encode(5, 0));
15126      return;
15127    }
15128    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
15129    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
15130      EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15131              rm.Encode(5, 0));
15132      return;
15133    }
15134    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
15135    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
15136      EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15137              rm.Encode(5, 0));
15138      return;
15139    }
15140  }
15141  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15142}
15143
15144void Assembler::vcvt(Condition cond,
15145                     DataType dt1,
15146                     DataType dt2,
15147                     DRegister rd,
15148                     DRegister rm,
15149                     int32_t fbits) {
15150  VIXL_ASSERT(AllowAssembler());
15151  CheckIT(cond);
15152  Dt_op_U_1 encoded_dt(dt1, dt2);
15153  Dt_U_sx_1 encoded_dt_2(dt2);
15154  Dt_U_sx_1 encoded_dt_3(dt1);
15155  if (IsUsingT32()) {
15156    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
15157    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15158      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15159        uint32_t fbits_ = 64 - fbits;
15160        EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
15161                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15162                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15163        AdvanceIT();
15164        return;
15165      }
15166    }
15167    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
15168    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
15169        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15170         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15171      unsigned offset = 32;
15172      if (dt2.Is(S16) || dt2.Is(U16)) {
15173        offset = 16;
15174      }
15175      uint32_t fbits_ = offset - fbits;
15176      EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15177                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15178                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15179                 ((fbits_ & 0x1e) >> 1));
15180      AdvanceIT();
15181      return;
15182    }
15183    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
15184    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
15185        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15186         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15187      unsigned offset = 32;
15188      if (dt1.Is(S16) || dt1.Is(U16)) {
15189        offset = 16;
15190      }
15191      uint32_t fbits_ = offset - fbits;
15192      EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
15193                 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
15194                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15195                 ((fbits_ & 0x1e) >> 1));
15196      AdvanceIT();
15197      return;
15198    }
15199  } else {
15200    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
15201    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15202      if (cond.Is(al)) {
15203        uint32_t fbits_ = 64 - fbits;
15204        EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
15205                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15206                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15207        return;
15208      }
15209    }
15210    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
15211    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
15212        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15213         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15214        cond.IsNotNever()) {
15215      unsigned offset = 32;
15216      if (dt2.Is(S16) || dt2.Is(U16)) {
15217        offset = 16;
15218      }
15219      uint32_t fbits_ = offset - fbits;
15220      EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
15221              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15222              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15223              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15224              ((fbits_ & 0x1e) >> 1));
15225      return;
15226    }
15227    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
15228    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
15229        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15230         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15231        cond.IsNotNever()) {
15232      unsigned offset = 32;
15233      if (dt1.Is(S16) || dt1.Is(U16)) {
15234        offset = 16;
15235      }
15236      uint32_t fbits_ = offset - fbits;
15237      EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
15238              ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
15239              ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
15240              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15241              ((fbits_ & 0x1e) >> 1));
15242      return;
15243    }
15244  }
15245  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15246}
15247
15248void Assembler::vcvt(Condition cond,
15249                     DataType dt1,
15250                     DataType dt2,
15251                     QRegister rd,
15252                     QRegister rm,
15253                     int32_t fbits) {
15254  VIXL_ASSERT(AllowAssembler());
15255  CheckIT(cond);
15256  Dt_op_U_1 encoded_dt(dt1, dt2);
15257  if (IsUsingT32()) {
15258    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
15259    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15260      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15261        uint32_t fbits_ = 64 - fbits;
15262        EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
15263                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15264                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15265        AdvanceIT();
15266        return;
15267      }
15268    }
15269  } else {
15270    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
15271    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15272      if (cond.Is(al)) {
15273        uint32_t fbits_ = 64 - fbits;
15274        EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
15275                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15276                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15277        return;
15278      }
15279    }
15280  }
15281  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15282}
15283
15284void Assembler::vcvt(Condition cond,
15285                     DataType dt1,
15286                     DataType dt2,
15287                     SRegister rd,
15288                     SRegister rm,
15289                     int32_t fbits) {
15290  VIXL_ASSERT(AllowAssembler());
15291  CheckIT(cond);
15292  Dt_U_sx_1 encoded_dt(dt2);
15293  Dt_U_sx_1 encoded_dt_2(dt1);
15294  if (IsUsingT32()) {
15295    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
15296    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
15297        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15298         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15299      unsigned offset = 32;
15300      if (dt2.Is(S16) || dt2.Is(U16)) {
15301        offset = 16;
15302      }
15303      uint32_t fbits_ = offset - fbits;
15304      EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
15305                 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
15306                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15307                 ((fbits_ & 0x1e) >> 1));
15308      AdvanceIT();
15309      return;
15310    }
15311    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
15312    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
15313        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15314         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15315      unsigned offset = 32;
15316      if (dt1.Is(S16) || dt1.Is(U16)) {
15317        offset = 16;
15318      }
15319      uint32_t fbits_ = offset - fbits;
15320      EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15321                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15322                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15323                 ((fbits_ & 0x1e) >> 1));
15324      AdvanceIT();
15325      return;
15326    }
15327  } else {
15328    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
15329    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
15330        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15331         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15332        cond.IsNotNever()) {
15333      unsigned offset = 32;
15334      if (dt2.Is(S16) || dt2.Is(U16)) {
15335        offset = 16;
15336      }
15337      uint32_t fbits_ = offset - fbits;
15338      EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
15339              ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
15340              ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
15341              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15342              ((fbits_ & 0x1e) >> 1));
15343      return;
15344    }
15345    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
15346    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
15347        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15348         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15349        cond.IsNotNever()) {
15350      unsigned offset = 32;
15351      if (dt1.Is(S16) || dt1.Is(U16)) {
15352        offset = 16;
15353      }
15354      uint32_t fbits_ = offset - fbits;
15355      EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
15356              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15357              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15358              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15359              ((fbits_ & 0x1e) >> 1));
15360      return;
15361    }
15362  }
15363  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15364}
15365
15366void Assembler::vcvt(
15367    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15368  VIXL_ASSERT(AllowAssembler());
15369  CheckIT(cond);
15370  Dt_op_1 encoded_dt(dt1, dt2);
15371  if (IsUsingT32()) {
15372    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
15373    if (encoded_dt.IsValid()) {
15374      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15375        EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
15376                   rd.Encode(22, 12) | rm.Encode(5, 0));
15377        AdvanceIT();
15378        return;
15379      }
15380    }
15381  } else {
15382    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
15383    if (encoded_dt.IsValid()) {
15384      if (cond.Is(al)) {
15385        EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
15386                rd.Encode(22, 12) | rm.Encode(5, 0));
15387        return;
15388      }
15389    }
15390  }
15391  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15392}
15393
15394void Assembler::vcvt(
15395    Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15396  VIXL_ASSERT(AllowAssembler());
15397  CheckIT(cond);
15398  Dt_op_1 encoded_dt(dt1, dt2);
15399  if (IsUsingT32()) {
15400    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
15401    if (encoded_dt.IsValid()) {
15402      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15403        EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
15404                   rd.Encode(22, 12) | rm.Encode(5, 0));
15405        AdvanceIT();
15406        return;
15407      }
15408    }
15409  } else {
15410    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
15411    if (encoded_dt.IsValid()) {
15412      if (cond.Is(al)) {
15413        EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
15414                rd.Encode(22, 12) | rm.Encode(5, 0));
15415        return;
15416      }
15417    }
15418  }
15419  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15420}
15421
15422void Assembler::vcvt(
15423    Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
15424  VIXL_ASSERT(AllowAssembler());
15425  CheckIT(cond);
15426  if (IsUsingT32()) {
15427    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
15428    if (dt1.Is(F16) && dt2.Is(F32)) {
15429      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15430        EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
15431        AdvanceIT();
15432        return;
15433      }
15434    }
15435  } else {
15436    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
15437    if (dt1.Is(F16) && dt2.Is(F32)) {
15438      if (cond.Is(al)) {
15439        EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
15440        return;
15441      }
15442    }
15443  }
15444  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15445}
15446
15447void Assembler::vcvt(
15448    Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
15449  VIXL_ASSERT(AllowAssembler());
15450  CheckIT(cond);
15451  if (IsUsingT32()) {
15452    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
15453    if (dt1.Is(F32) && dt2.Is(F16)) {
15454      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15455        EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
15456        AdvanceIT();
15457        return;
15458      }
15459    }
15460  } else {
15461    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
15462    if (dt1.Is(F32) && dt2.Is(F16)) {
15463      if (cond.Is(al)) {
15464        EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
15465        return;
15466      }
15467    }
15468  }
15469  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15470}
15471
15472void Assembler::vcvt(
15473    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15474  VIXL_ASSERT(AllowAssembler());
15475  CheckIT(cond);
15476  Dt_op_2 encoded_dt(dt2);
15477  if (IsUsingT32()) {
15478    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
15479    if (dt1.Is(U32) && dt2.Is(F32)) {
15480      EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15481      AdvanceIT();
15482      return;
15483    }
15484    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
15485    if (dt1.Is(S32) && dt2.Is(F32)) {
15486      EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15487      AdvanceIT();
15488      return;
15489    }
15490    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
15491    if (dt1.Is(F32) && encoded_dt.IsValid()) {
15492      EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
15493                 rd.Encode(22, 12) | rm.Encode(5, 0));
15494      AdvanceIT();
15495      return;
15496    }
15497  } else {
15498    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
15499    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
15500      EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15501              rm.Encode(5, 0));
15502      return;
15503    }
15504    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
15505    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
15506      EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15507              rm.Encode(5, 0));
15508      return;
15509    }
15510    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
15511    if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
15512      EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
15513              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
15514              rm.Encode(5, 0));
15515      return;
15516    }
15517  }
15518  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15519}
15520
15521void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15522  VIXL_ASSERT(AllowAssembler());
15523  CheckIT(al);
15524  Dt_op_3 encoded_dt(dt1);
15525  if (IsUsingT32()) {
15526    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15527    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15528      EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
15529                 rd.Encode(22, 12) | rm.Encode(5, 0));
15530      AdvanceIT();
15531      return;
15532    }
15533  } else {
15534    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15535    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15536      EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
15537              rd.Encode(22, 12) | rm.Encode(5, 0));
15538      return;
15539    }
15540  }
15541  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15542}
15543
15544void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15545  VIXL_ASSERT(AllowAssembler());
15546  CheckIT(al);
15547  Dt_op_3 encoded_dt(dt1);
15548  if (IsUsingT32()) {
15549    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15550    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15551      EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
15552                 rd.Encode(22, 12) | rm.Encode(5, 0));
15553      AdvanceIT();
15554      return;
15555    }
15556  } else {
15557    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15558    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15559      EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
15560              rd.Encode(22, 12) | rm.Encode(5, 0));
15561      return;
15562    }
15563  }
15564  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15565}
15566
15567void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15568  VIXL_ASSERT(AllowAssembler());
15569  CheckIT(al);
15570  Dt_op_2 encoded_dt(dt1);
15571  if (IsUsingT32()) {
15572    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15573    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15574      EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
15575                 rd.Encode(22, 12) | rm.Encode(5, 0));
15576      AdvanceIT();
15577      return;
15578    }
15579  } else {
15580    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15581    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15582      EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
15583              rd.Encode(22, 12) | rm.Encode(5, 0));
15584      return;
15585    }
15586  }
15587  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15588}
15589
15590void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15591  VIXL_ASSERT(AllowAssembler());
15592  CheckIT(al);
15593  Dt_op_2 encoded_dt(dt1);
15594  if (IsUsingT32()) {
15595    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15596    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15597      EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
15598                 rd.Encode(22, 12) | rm.Encode(5, 0));
15599      AdvanceIT();
15600      return;
15601    }
15602  } else {
15603    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15604    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15605      EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
15606              rd.Encode(22, 12) | rm.Encode(5, 0));
15607      return;
15608    }
15609  }
15610  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15611}
15612
15613void Assembler::vcvtb(
15614    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15615  VIXL_ASSERT(AllowAssembler());
15616  CheckIT(cond);
15617  if (IsUsingT32()) {
15618    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
15619    if (dt1.Is(F32) && dt2.Is(F16)) {
15620      EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15621      AdvanceIT();
15622      return;
15623    }
15624    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
15625    if (dt1.Is(F16) && dt2.Is(F32)) {
15626      EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15627      AdvanceIT();
15628      return;
15629    }
15630  } else {
15631    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
15632    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
15633      EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15634              rm.Encode(5, 0));
15635      return;
15636    }
15637    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
15638    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
15639      EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15640              rm.Encode(5, 0));
15641      return;
15642    }
15643  }
15644  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15645}
15646
15647void Assembler::vcvtb(
15648    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
15649  VIXL_ASSERT(AllowAssembler());
15650  CheckIT(cond);
15651  if (IsUsingT32()) {
15652    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
15653    if (dt1.Is(F64) && dt2.Is(F16)) {
15654      EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15655      AdvanceIT();
15656      return;
15657    }
15658  } else {
15659    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
15660    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
15661      EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15662              rm.Encode(5, 0));
15663      return;
15664    }
15665  }
15666  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15667}
15668
15669void Assembler::vcvtb(
15670    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15671  VIXL_ASSERT(AllowAssembler());
15672  CheckIT(cond);
15673  if (IsUsingT32()) {
15674    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
15675    if (dt1.Is(F16) && dt2.Is(F64)) {
15676      EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15677      AdvanceIT();
15678      return;
15679    }
15680  } else {
15681    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
15682    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
15683      EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15684              rm.Encode(5, 0));
15685      return;
15686    }
15687  }
15688  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15689}
15690
15691void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15692  VIXL_ASSERT(AllowAssembler());
15693  CheckIT(al);
15694  Dt_op_3 encoded_dt(dt1);
15695  if (IsUsingT32()) {
15696    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15697    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15698      EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
15699                 rd.Encode(22, 12) | rm.Encode(5, 0));
15700      AdvanceIT();
15701      return;
15702    }
15703  } else {
15704    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15705    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15706      EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
15707              rd.Encode(22, 12) | rm.Encode(5, 0));
15708      return;
15709    }
15710  }
15711  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15712}
15713
15714void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15715  VIXL_ASSERT(AllowAssembler());
15716  CheckIT(al);
15717  Dt_op_3 encoded_dt(dt1);
15718  if (IsUsingT32()) {
15719    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15720    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15721      EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
15722                 rd.Encode(22, 12) | rm.Encode(5, 0));
15723      AdvanceIT();
15724      return;
15725    }
15726  } else {
15727    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15728    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15729      EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
15730              rd.Encode(22, 12) | rm.Encode(5, 0));
15731      return;
15732    }
15733  }
15734  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15735}
15736
15737void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15738  VIXL_ASSERT(AllowAssembler());
15739  CheckIT(al);
15740  Dt_op_2 encoded_dt(dt1);
15741  if (IsUsingT32()) {
15742    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15743    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15744      EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
15745                 rd.Encode(22, 12) | rm.Encode(5, 0));
15746      AdvanceIT();
15747      return;
15748    }
15749  } else {
15750    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15751    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15752      EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
15753              rd.Encode(22, 12) | rm.Encode(5, 0));
15754      return;
15755    }
15756  }
15757  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15758}
15759
15760void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15761  VIXL_ASSERT(AllowAssembler());
15762  CheckIT(al);
15763  Dt_op_2 encoded_dt(dt1);
15764  if (IsUsingT32()) {
15765    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15766    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15767      EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
15768                 rd.Encode(22, 12) | rm.Encode(5, 0));
15769      AdvanceIT();
15770      return;
15771    }
15772  } else {
15773    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15774    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15775      EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
15776              rd.Encode(22, 12) | rm.Encode(5, 0));
15777      return;
15778    }
15779  }
15780  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15781}
15782
15783void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15784  VIXL_ASSERT(AllowAssembler());
15785  CheckIT(al);
15786  Dt_op_3 encoded_dt(dt1);
15787  if (IsUsingT32()) {
15788    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15789    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15790      EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
15791                 rd.Encode(22, 12) | rm.Encode(5, 0));
15792      AdvanceIT();
15793      return;
15794    }
15795  } else {
15796    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15797    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15798      EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
15799              rd.Encode(22, 12) | rm.Encode(5, 0));
15800      return;
15801    }
15802  }
15803  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15804}
15805
15806void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15807  VIXL_ASSERT(AllowAssembler());
15808  CheckIT(al);
15809  Dt_op_3 encoded_dt(dt1);
15810  if (IsUsingT32()) {
15811    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15812    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15813      EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
15814                 rd.Encode(22, 12) | rm.Encode(5, 0));
15815      AdvanceIT();
15816      return;
15817    }
15818  } else {
15819    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15820    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15821      EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
15822              rd.Encode(22, 12) | rm.Encode(5, 0));
15823      return;
15824    }
15825  }
15826  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15827}
15828
15829void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15830  VIXL_ASSERT(AllowAssembler());
15831  CheckIT(al);
15832  Dt_op_2 encoded_dt(dt1);
15833  if (IsUsingT32()) {
15834    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15835    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15836      EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
15837                 rd.Encode(22, 12) | rm.Encode(5, 0));
15838      AdvanceIT();
15839      return;
15840    }
15841  } else {
15842    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15843    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15844      EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
15845              rd.Encode(22, 12) | rm.Encode(5, 0));
15846      return;
15847    }
15848  }
15849  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15850}
15851
15852void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15853  VIXL_ASSERT(AllowAssembler());
15854  CheckIT(al);
15855  Dt_op_2 encoded_dt(dt1);
15856  if (IsUsingT32()) {
15857    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15858    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15859      EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
15860                 rd.Encode(22, 12) | rm.Encode(5, 0));
15861      AdvanceIT();
15862      return;
15863    }
15864  } else {
15865    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15866    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15867      EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
15868              rd.Encode(22, 12) | rm.Encode(5, 0));
15869      return;
15870    }
15871  }
15872  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15873}
15874
15875void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15876  VIXL_ASSERT(AllowAssembler());
15877  CheckIT(al);
15878  Dt_op_3 encoded_dt(dt1);
15879  if (IsUsingT32()) {
15880    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15881    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15882      EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
15883                 rd.Encode(22, 12) | rm.Encode(5, 0));
15884      AdvanceIT();
15885      return;
15886    }
15887  } else {
15888    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15889    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15890      EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
15891              rd.Encode(22, 12) | rm.Encode(5, 0));
15892      return;
15893    }
15894  }
15895  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15896}
15897
15898void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15899  VIXL_ASSERT(AllowAssembler());
15900  CheckIT(al);
15901  Dt_op_3 encoded_dt(dt1);
15902  if (IsUsingT32()) {
15903    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15904    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15905      EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
15906                 rd.Encode(22, 12) | rm.Encode(5, 0));
15907      AdvanceIT();
15908      return;
15909    }
15910  } else {
15911    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15912    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15913      EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
15914              rd.Encode(22, 12) | rm.Encode(5, 0));
15915      return;
15916    }
15917  }
15918  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15919}
15920
15921void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15922  VIXL_ASSERT(AllowAssembler());
15923  CheckIT(al);
15924  Dt_op_2 encoded_dt(dt1);
15925  if (IsUsingT32()) {
15926    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15927    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15928      EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
15929                 rd.Encode(22, 12) | rm.Encode(5, 0));
15930      AdvanceIT();
15931      return;
15932    }
15933  } else {
15934    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15935    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15936      EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
15937              rd.Encode(22, 12) | rm.Encode(5, 0));
15938      return;
15939    }
15940  }
15941  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15942}
15943
15944void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15945  VIXL_ASSERT(AllowAssembler());
15946  CheckIT(al);
15947  Dt_op_2 encoded_dt(dt1);
15948  if (IsUsingT32()) {
15949    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15950    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15951      EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
15952                 rd.Encode(22, 12) | rm.Encode(5, 0));
15953      AdvanceIT();
15954      return;
15955    }
15956  } else {
15957    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15958    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15959      EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
15960              rd.Encode(22, 12) | rm.Encode(5, 0));
15961      return;
15962    }
15963  }
15964  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15965}
15966
15967void Assembler::vcvtr(
15968    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15969  VIXL_ASSERT(AllowAssembler());
15970  CheckIT(cond);
15971  if (IsUsingT32()) {
15972    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
15973    if (dt1.Is(U32) && dt2.Is(F32)) {
15974      EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15975      AdvanceIT();
15976      return;
15977    }
15978    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
15979    if (dt1.Is(S32) && dt2.Is(F32)) {
15980      EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15981      AdvanceIT();
15982      return;
15983    }
15984  } else {
15985    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
15986    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
15987      EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15988              rm.Encode(5, 0));
15989      return;
15990    }
15991    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
15992    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
15993      EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15994              rm.Encode(5, 0));
15995      return;
15996    }
15997  }
15998  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
15999}
16000
16001void Assembler::vcvtr(
16002    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16003  VIXL_ASSERT(AllowAssembler());
16004  CheckIT(cond);
16005  if (IsUsingT32()) {
16006    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16007    if (dt1.Is(U32) && dt2.Is(F64)) {
16008      EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16009      AdvanceIT();
16010      return;
16011    }
16012    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16013    if (dt1.Is(S32) && dt2.Is(F64)) {
16014      EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16015      AdvanceIT();
16016      return;
16017    }
16018  } else {
16019    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16020    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16021      EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16022              rm.Encode(5, 0));
16023      return;
16024    }
16025    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16026    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16027      EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16028              rm.Encode(5, 0));
16029      return;
16030    }
16031  }
16032  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
16033}
16034
16035void Assembler::vcvtt(
16036    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16037  VIXL_ASSERT(AllowAssembler());
16038  CheckIT(cond);
16039  if (IsUsingT32()) {
16040    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16041    if (dt1.Is(F32) && dt2.Is(F16)) {
16042      EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16043      AdvanceIT();
16044      return;
16045    }
16046    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16047    if (dt1.Is(F16) && dt2.Is(F32)) {
16048      EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16049      AdvanceIT();
16050      return;
16051    }
16052  } else {
16053    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16054    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16055      EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16056              rm.Encode(5, 0));
16057      return;
16058    }
16059    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16060    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16061      EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16062              rm.Encode(5, 0));
16063      return;
16064    }
16065  }
16066  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16067}
16068
16069void Assembler::vcvtt(
16070    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
16071  VIXL_ASSERT(AllowAssembler());
16072  CheckIT(cond);
16073  if (IsUsingT32()) {
16074    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16075    if (dt1.Is(F64) && dt2.Is(F16)) {
16076      EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16077      AdvanceIT();
16078      return;
16079    }
16080  } else {
16081    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16082    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16083      EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16084              rm.Encode(5, 0));
16085      return;
16086    }
16087  }
16088  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16089}
16090
16091void Assembler::vcvtt(
16092    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16093  VIXL_ASSERT(AllowAssembler());
16094  CheckIT(cond);
16095  if (IsUsingT32()) {
16096    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16097    if (dt1.Is(F16) && dt2.Is(F64)) {
16098      EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16099      AdvanceIT();
16100      return;
16101    }
16102  } else {
16103    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16104    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16105      EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16106              rm.Encode(5, 0));
16107      return;
16108    }
16109  }
16110  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16111}
16112
16113void Assembler::vdiv(
16114    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16115  VIXL_ASSERT(AllowAssembler());
16116  CheckIT(cond);
16117  if (IsUsingT32()) {
16118    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
16119    if (dt.Is(F32)) {
16120      EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16121                 rm.Encode(5, 0));
16122      AdvanceIT();
16123      return;
16124    }
16125  } else {
16126    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
16127    if (dt.Is(F32) && cond.IsNotNever()) {
16128      EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16129              rn.Encode(7, 16) | rm.Encode(5, 0));
16130      return;
16131    }
16132  }
16133  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
16134}
16135
16136void Assembler::vdiv(
16137    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16138  VIXL_ASSERT(AllowAssembler());
16139  CheckIT(cond);
16140  if (IsUsingT32()) {
16141    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
16142    if (dt.Is(F64)) {
16143      EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16144                 rm.Encode(5, 0));
16145      AdvanceIT();
16146      return;
16147    }
16148  } else {
16149    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
16150    if (dt.Is(F64) && cond.IsNotNever()) {
16151      EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16152              rn.Encode(7, 16) | rm.Encode(5, 0));
16153      return;
16154    }
16155  }
16156  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
16157}
16158
16159void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
16160  VIXL_ASSERT(AllowAssembler());
16161  CheckIT(cond);
16162  Dt_B_E_1 encoded_dt(dt);
16163  if (IsUsingT32()) {
16164    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
16165    if (encoded_dt.IsValid()) {
16166      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16167        EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16168                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16169                   rd.Encode(7, 16) | (rt.GetCode() << 12));
16170        AdvanceIT();
16171        return;
16172      }
16173    }
16174  } else {
16175    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
16176    if (encoded_dt.IsValid() && cond.IsNotNever()) {
16177      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16178        EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
16179                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16180                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16181                rd.Encode(7, 16) | (rt.GetCode() << 12));
16182        return;
16183      }
16184    }
16185  }
16186  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
16187}
16188
16189void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
16190  VIXL_ASSERT(AllowAssembler());
16191  CheckIT(cond);
16192  Dt_B_E_1 encoded_dt(dt);
16193  if (IsUsingT32()) {
16194    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
16195    if (encoded_dt.IsValid()) {
16196      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16197        EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16198                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16199                   rd.Encode(7, 16) | (rt.GetCode() << 12));
16200        AdvanceIT();
16201        return;
16202      }
16203    }
16204  } else {
16205    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
16206    if (encoded_dt.IsValid() && cond.IsNotNever()) {
16207      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16208        EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
16209                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16210                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16211                rd.Encode(7, 16) | (rt.GetCode() << 12));
16212        return;
16213      }
16214    }
16215  }
16216  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
16217}
16218
16219void Assembler::vdup(Condition cond,
16220                     DataType dt,
16221                     DRegister rd,
16222                     DRegisterLane rm) {
16223  VIXL_ASSERT(AllowAssembler());
16224  CheckIT(cond);
16225  Dt_imm4_1 encoded_dt(dt, rm);
16226  if (IsUsingT32()) {
16227    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
16228    if (encoded_dt.IsValid()) {
16229      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16230        EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
16231                   rd.Encode(22, 12) | rm.Encode(5, 0));
16232        AdvanceIT();
16233        return;
16234      }
16235    }
16236  } else {
16237    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
16238    if (encoded_dt.IsValid()) {
16239      if (cond.Is(al)) {
16240        EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
16241                rd.Encode(22, 12) | rm.Encode(5, 0));
16242        return;
16243      }
16244    }
16245  }
16246  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
16247}
16248
16249void Assembler::vdup(Condition cond,
16250                     DataType dt,
16251                     QRegister rd,
16252                     DRegisterLane rm) {
16253  VIXL_ASSERT(AllowAssembler());
16254  CheckIT(cond);
16255  Dt_imm4_1 encoded_dt(dt, rm);
16256  if (IsUsingT32()) {
16257    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
16258    if (encoded_dt.IsValid()) {
16259      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16260        EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
16261                   rd.Encode(22, 12) | rm.Encode(5, 0));
16262        AdvanceIT();
16263        return;
16264      }
16265    }
16266  } else {
16267    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
16268    if (encoded_dt.IsValid()) {
16269      if (cond.Is(al)) {
16270        EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
16271                rd.Encode(22, 12) | rm.Encode(5, 0));
16272        return;
16273      }
16274    }
16275  }
16276  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
16277}
16278
16279void Assembler::veor(
16280    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16281  VIXL_ASSERT(AllowAssembler());
16282  CheckIT(cond);
16283  USE(dt);
16284  if (IsUsingT32()) {
16285    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
16286    if (cond.Is(al) || AllowStronglyDiscouraged()) {
16287      EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16288                 rm.Encode(5, 0));
16289      AdvanceIT();
16290      return;
16291    }
16292  } else {
16293    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
16294    if (cond.Is(al)) {
16295      EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16296              rm.Encode(5, 0));
16297      return;
16298    }
16299  }
16300  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
16301}
16302
16303void Assembler::veor(
16304    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16305  VIXL_ASSERT(AllowAssembler());
16306  CheckIT(cond);
16307  USE(dt);
16308  if (IsUsingT32()) {
16309    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
16310    if (cond.Is(al) || AllowStronglyDiscouraged()) {
16311      EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16312                 rm.Encode(5, 0));
16313      AdvanceIT();
16314      return;
16315    }
16316  } else {
16317    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
16318    if (cond.Is(al)) {
16319      EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16320              rm.Encode(5, 0));
16321      return;
16322    }
16323  }
16324  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
16325}
16326
16327void Assembler::vext(Condition cond,
16328                     DataType dt,
16329                     DRegister rd,
16330                     DRegister rn,
16331                     DRegister rm,
16332                     const DOperand& operand) {
16333  VIXL_ASSERT(AllowAssembler());
16334  CheckIT(cond);
16335  if (operand.IsImmediate()) {
16336    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
16337      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
16338      if (IsUsingT32()) {
16339        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
16340        if (dt.Is(Untyped8) && (imm <= 7)) {
16341          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16342            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16343                       rm.Encode(5, 0) | (imm << 8));
16344            AdvanceIT();
16345            return;
16346          }
16347        }
16348        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
16349        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
16350            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16351          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16352            uint32_t imm4 = imm / dt.GetSize();
16353            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16354                       rm.Encode(5, 0) | (imm4 << 8));
16355            AdvanceIT();
16356            return;
16357          }
16358        }
16359      } else {
16360        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
16361        if (dt.Is(Untyped8) && (imm <= 7)) {
16362          if (cond.Is(al)) {
16363            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16364                    rm.Encode(5, 0) | (imm << 8));
16365            return;
16366          }
16367        }
16368        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
16369        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
16370            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16371          if (cond.Is(al)) {
16372            uint32_t imm4 = imm / dt.GetSize();
16373            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16374                    rm.Encode(5, 0) | (imm4 << 8));
16375            return;
16376          }
16377        }
16378      }
16379    }
16380  }
16381  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
16382}
16383
16384void Assembler::vext(Condition cond,
16385                     DataType dt,
16386                     QRegister rd,
16387                     QRegister rn,
16388                     QRegister rm,
16389                     const QOperand& operand) {
16390  VIXL_ASSERT(AllowAssembler());
16391  CheckIT(cond);
16392  if (operand.IsImmediate()) {
16393    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
16394      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
16395      if (IsUsingT32()) {
16396        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
16397        if (dt.Is(Untyped8) && (imm <= 15)) {
16398          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16399            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16400                       rm.Encode(5, 0) | (imm << 8));
16401            AdvanceIT();
16402            return;
16403          }
16404        }
16405        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
16406        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
16407            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16408          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16409            uint32_t imm4 = imm / dt.GetSize();
16410            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16411                       rm.Encode(5, 0) | (imm4 << 8));
16412            AdvanceIT();
16413            return;
16414          }
16415        }
16416      } else {
16417        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
16418        if (dt.Is(Untyped8) && (imm <= 15)) {
16419          if (cond.Is(al)) {
16420            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16421                    rm.Encode(5, 0) | (imm << 8));
16422            return;
16423          }
16424        }
16425        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
16426        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
16427            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16428          if (cond.Is(al)) {
16429            uint32_t imm4 = imm / dt.GetSize();
16430            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16431                    rm.Encode(5, 0) | (imm4 << 8));
16432            return;
16433          }
16434        }
16435      }
16436    }
16437  }
16438  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
16439}
16440
16441void Assembler::vfma(
16442    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16443  VIXL_ASSERT(AllowAssembler());
16444  CheckIT(cond);
16445  if (IsUsingT32()) {
16446    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
16447    if (dt.Is(F32)) {
16448      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16449        EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16450                   rm.Encode(5, 0));
16451        AdvanceIT();
16452        return;
16453      }
16454    }
16455    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
16456    if (dt.Is(F64)) {
16457      EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16458                 rm.Encode(5, 0));
16459      AdvanceIT();
16460      return;
16461    }
16462  } else {
16463    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
16464    if (dt.Is(F32)) {
16465      if (cond.Is(al)) {
16466        EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16467                rm.Encode(5, 0));
16468        return;
16469      }
16470    }
16471    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
16472    if (dt.Is(F64) && cond.IsNotNever()) {
16473      EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16474              rn.Encode(7, 16) | rm.Encode(5, 0));
16475      return;
16476    }
16477  }
16478  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16479}
16480
16481void Assembler::vfma(
16482    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16483  VIXL_ASSERT(AllowAssembler());
16484  CheckIT(cond);
16485  if (IsUsingT32()) {
16486    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
16487    if (dt.Is(F32)) {
16488      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16489        EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16490                   rm.Encode(5, 0));
16491        AdvanceIT();
16492        return;
16493      }
16494    }
16495  } else {
16496    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
16497    if (dt.Is(F32)) {
16498      if (cond.Is(al)) {
16499        EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16500                rm.Encode(5, 0));
16501        return;
16502      }
16503    }
16504  }
16505  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16506}
16507
16508void Assembler::vfma(
16509    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16510  VIXL_ASSERT(AllowAssembler());
16511  CheckIT(cond);
16512  if (IsUsingT32()) {
16513    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
16514    if (dt.Is(F32)) {
16515      EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16516                 rm.Encode(5, 0));
16517      AdvanceIT();
16518      return;
16519    }
16520  } else {
16521    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
16522    if (dt.Is(F32) && cond.IsNotNever()) {
16523      EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16524              rn.Encode(7, 16) | rm.Encode(5, 0));
16525      return;
16526    }
16527  }
16528  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16529}
16530
16531void Assembler::vfms(
16532    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16533  VIXL_ASSERT(AllowAssembler());
16534  CheckIT(cond);
16535  if (IsUsingT32()) {
16536    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
16537    if (dt.Is(F32)) {
16538      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16539        EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16540                   rm.Encode(5, 0));
16541        AdvanceIT();
16542        return;
16543      }
16544    }
16545    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
16546    if (dt.Is(F64)) {
16547      EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16548                 rm.Encode(5, 0));
16549      AdvanceIT();
16550      return;
16551    }
16552  } else {
16553    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
16554    if (dt.Is(F32)) {
16555      if (cond.Is(al)) {
16556        EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16557                rm.Encode(5, 0));
16558        return;
16559      }
16560    }
16561    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
16562    if (dt.Is(F64) && cond.IsNotNever()) {
16563      EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16564              rn.Encode(7, 16) | rm.Encode(5, 0));
16565      return;
16566    }
16567  }
16568  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16569}
16570
16571void Assembler::vfms(
16572    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16573  VIXL_ASSERT(AllowAssembler());
16574  CheckIT(cond);
16575  if (IsUsingT32()) {
16576    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
16577    if (dt.Is(F32)) {
16578      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16579        EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16580                   rm.Encode(5, 0));
16581        AdvanceIT();
16582        return;
16583      }
16584    }
16585  } else {
16586    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
16587    if (dt.Is(F32)) {
16588      if (cond.Is(al)) {
16589        EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16590                rm.Encode(5, 0));
16591        return;
16592      }
16593    }
16594  }
16595  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16596}
16597
16598void Assembler::vfms(
16599    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16600  VIXL_ASSERT(AllowAssembler());
16601  CheckIT(cond);
16602  if (IsUsingT32()) {
16603    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
16604    if (dt.Is(F32)) {
16605      EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16606                 rm.Encode(5, 0));
16607      AdvanceIT();
16608      return;
16609    }
16610  } else {
16611    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
16612    if (dt.Is(F32) && cond.IsNotNever()) {
16613      EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16614              rn.Encode(7, 16) | rm.Encode(5, 0));
16615      return;
16616    }
16617  }
16618  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16619}
16620
16621void Assembler::vfnma(
16622    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16623  VIXL_ASSERT(AllowAssembler());
16624  CheckIT(cond);
16625  if (IsUsingT32()) {
16626    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
16627    if (dt.Is(F32)) {
16628      EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16629                 rm.Encode(5, 0));
16630      AdvanceIT();
16631      return;
16632    }
16633  } else {
16634    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
16635    if (dt.Is(F32) && cond.IsNotNever()) {
16636      EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16637              rn.Encode(7, 16) | rm.Encode(5, 0));
16638      return;
16639    }
16640  }
16641  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
16642}
16643
16644void Assembler::vfnma(
16645    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16646  VIXL_ASSERT(AllowAssembler());
16647  CheckIT(cond);
16648  if (IsUsingT32()) {
16649    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
16650    if (dt.Is(F64)) {
16651      EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16652                 rm.Encode(5, 0));
16653      AdvanceIT();
16654      return;
16655    }
16656  } else {
16657    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
16658    if (dt.Is(F64) && cond.IsNotNever()) {
16659      EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16660              rn.Encode(7, 16) | rm.Encode(5, 0));
16661      return;
16662    }
16663  }
16664  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
16665}
16666
16667void Assembler::vfnms(
16668    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16669  VIXL_ASSERT(AllowAssembler());
16670  CheckIT(cond);
16671  if (IsUsingT32()) {
16672    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
16673    if (dt.Is(F32)) {
16674      EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16675                 rm.Encode(5, 0));
16676      AdvanceIT();
16677      return;
16678    }
16679  } else {
16680    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
16681    if (dt.Is(F32) && cond.IsNotNever()) {
16682      EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16683              rn.Encode(7, 16) | rm.Encode(5, 0));
16684      return;
16685    }
16686  }
16687  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
16688}
16689
16690void Assembler::vfnms(
16691    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16692  VIXL_ASSERT(AllowAssembler());
16693  CheckIT(cond);
16694  if (IsUsingT32()) {
16695    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
16696    if (dt.Is(F64)) {
16697      EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16698                 rm.Encode(5, 0));
16699      AdvanceIT();
16700      return;
16701    }
16702  } else {
16703    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
16704    if (dt.Is(F64) && cond.IsNotNever()) {
16705      EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16706              rn.Encode(7, 16) | rm.Encode(5, 0));
16707      return;
16708    }
16709  }
16710  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
16711}
16712
16713void Assembler::vhadd(
16714    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16715  VIXL_ASSERT(AllowAssembler());
16716  CheckIT(cond);
16717  Dt_U_size_1 encoded_dt(dt);
16718  if (IsUsingT32()) {
16719    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
16720    if (encoded_dt.IsValid()) {
16721      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16722        EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16723                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16724                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16725        AdvanceIT();
16726        return;
16727      }
16728    }
16729  } else {
16730    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
16731    if (encoded_dt.IsValid()) {
16732      if (cond.Is(al)) {
16733        EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16734                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16735                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16736        return;
16737      }
16738    }
16739  }
16740  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
16741}
16742
16743void Assembler::vhadd(
16744    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16745  VIXL_ASSERT(AllowAssembler());
16746  CheckIT(cond);
16747  Dt_U_size_1 encoded_dt(dt);
16748  if (IsUsingT32()) {
16749    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
16750    if (encoded_dt.IsValid()) {
16751      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16752        EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16753                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16754                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16755        AdvanceIT();
16756        return;
16757      }
16758    }
16759  } else {
16760    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
16761    if (encoded_dt.IsValid()) {
16762      if (cond.Is(al)) {
16763        EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16764                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16765                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16766        return;
16767      }
16768    }
16769  }
16770  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
16771}
16772
16773void Assembler::vhsub(
16774    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16775  VIXL_ASSERT(AllowAssembler());
16776  CheckIT(cond);
16777  Dt_U_size_1 encoded_dt(dt);
16778  if (IsUsingT32()) {
16779    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
16780    if (encoded_dt.IsValid()) {
16781      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16782        EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16783                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16784                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16785        AdvanceIT();
16786        return;
16787      }
16788    }
16789  } else {
16790    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
16791    if (encoded_dt.IsValid()) {
16792      if (cond.Is(al)) {
16793        EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16794                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16795                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16796        return;
16797      }
16798    }
16799  }
16800  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
16801}
16802
16803void Assembler::vhsub(
16804    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16805  VIXL_ASSERT(AllowAssembler());
16806  CheckIT(cond);
16807  Dt_U_size_1 encoded_dt(dt);
16808  if (IsUsingT32()) {
16809    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
16810    if (encoded_dt.IsValid()) {
16811      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16812        EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16813                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16814                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16815        AdvanceIT();
16816        return;
16817      }
16818    }
16819  } else {
16820    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
16821    if (encoded_dt.IsValid()) {
16822      if (cond.Is(al)) {
16823        EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16824                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16825                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16826        return;
16827      }
16828    }
16829  }
16830  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
16831}
16832
16833void Assembler::vld1(Condition cond,
16834                     DataType dt,
16835                     const NeonRegisterList& nreglist,
16836                     const AlignedMemOperand& operand) {
16837  VIXL_ASSERT(AllowAssembler());
16838  CheckIT(cond);
16839  if (operand.IsImmediateZero()) {
16840    Register rn = operand.GetBaseRegister();
16841    Alignment align = operand.GetAlignment();
16842    Dt_size_6 encoded_dt(dt);
16843    Dt_size_7 encoded_dt_2(dt);
16844    Align_align_1 encoded_align_1(align, nreglist);
16845    Align_a_1 encoded_align_2(align, dt);
16846    Align_index_align_1 encoded_align_3(align, nreglist, dt);
16847    if (IsUsingT32()) {
16848      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16849      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16850          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16851          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
16852          ((!rn.IsPC()) || AllowUnpredictable())) {
16853        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16854          const DRegister& first = nreglist.GetFirstDRegister();
16855          uint32_t len_encoding;
16856          switch (nreglist.GetLength()) {
16857            default:
16858              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16859            case 1:
16860              len_encoding = 0x7;
16861              break;
16862            case 2:
16863              len_encoding = 0xa;
16864              break;
16865            case 3:
16866              len_encoding = 0x6;
16867              break;
16868            case 4:
16869              len_encoding = 0x2;
16870              break;
16871          }
16872          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
16873                     (encoded_align_1.GetEncodingValue() << 4) |
16874                     first.Encode(22, 12) | (len_encoding << 8) |
16875                     (rn.GetCode() << 16));
16876          AdvanceIT();
16877          return;
16878        }
16879      }
16880      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16881      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16882          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16883          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
16884          ((!rn.IsPC()) || AllowUnpredictable())) {
16885        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16886          const DRegister& first = nreglist.GetFirstDRegister();
16887          uint32_t len_encoding;
16888          switch (nreglist.GetLength()) {
16889            default:
16890              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16891            case 1:
16892              len_encoding = 0x7;
16893              break;
16894            case 2:
16895              len_encoding = 0xa;
16896              break;
16897            case 3:
16898              len_encoding = 0x6;
16899              break;
16900            case 4:
16901              len_encoding = 0x2;
16902              break;
16903          }
16904          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
16905                     (encoded_align_1.GetEncodingValue() << 4) |
16906                     first.Encode(22, 12) | (len_encoding << 8) |
16907                     (rn.GetCode() << 16));
16908          AdvanceIT();
16909          return;
16910        }
16911      }
16912      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16913      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
16914          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
16915          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
16916          ((!rn.IsPC()) || AllowUnpredictable())) {
16917        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16918          const DRegister& first = nreglist.GetFirstDRegister();
16919          uint32_t len_encoding = nreglist.GetLength() - 1;
16920          EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
16921                     (encoded_align_2.GetEncodingValue() << 4) |
16922                     first.Encode(22, 12) | (len_encoding << 5) |
16923                     (rn.GetCode() << 16));
16924          AdvanceIT();
16925          return;
16926        }
16927      }
16928      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16929      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
16930          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
16931          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
16932          ((!rn.IsPC()) || AllowUnpredictable())) {
16933        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16934          const DRegister& first = nreglist.GetFirstDRegister();
16935          uint32_t len_encoding = nreglist.GetLength() - 1;
16936          EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
16937                     (encoded_align_2.GetEncodingValue() << 4) |
16938                     first.Encode(22, 12) | (len_encoding << 5) |
16939                     (rn.GetCode() << 16));
16940          AdvanceIT();
16941          return;
16942        }
16943      }
16944      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16945      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
16946          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
16947          encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
16948        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16949          const DRegister& first = nreglist.GetFirstDRegister();
16950          EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
16951                     (encoded_align_3.GetEncodingValue() << 4) |
16952                     first.Encode(22, 12) | (rn.GetCode() << 16));
16953          AdvanceIT();
16954          return;
16955        }
16956      }
16957      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16958      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
16959          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
16960          encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
16961        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16962          const DRegister& first = nreglist.GetFirstDRegister();
16963          EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
16964                     (encoded_align_3.GetEncodingValue() << 4) |
16965                     first.Encode(22, 12) | (rn.GetCode() << 16));
16966          AdvanceIT();
16967          return;
16968        }
16969      }
16970    } else {
16971      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
16972      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16973          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16974          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
16975          ((!rn.IsPC()) || AllowUnpredictable())) {
16976        if (cond.Is(al)) {
16977          const DRegister& first = nreglist.GetFirstDRegister();
16978          uint32_t len_encoding;
16979          switch (nreglist.GetLength()) {
16980            default:
16981              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16982            case 1:
16983              len_encoding = 0x7;
16984              break;
16985            case 2:
16986              len_encoding = 0xa;
16987              break;
16988            case 3:
16989              len_encoding = 0x6;
16990              break;
16991            case 4:
16992              len_encoding = 0x2;
16993              break;
16994          }
16995          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
16996                  (encoded_align_1.GetEncodingValue() << 4) |
16997                  first.Encode(22, 12) | (len_encoding << 8) |
16998                  (rn.GetCode() << 16));
16999          return;
17000        }
17001      }
17002      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17003      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17004          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17005          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17006          ((!rn.IsPC()) || AllowUnpredictable())) {
17007        if (cond.Is(al)) {
17008          const DRegister& first = nreglist.GetFirstDRegister();
17009          uint32_t len_encoding;
17010          switch (nreglist.GetLength()) {
17011            default:
17012              VIXL_UNREACHABLE_OR_FALLTHROUGH();
17013            case 1:
17014              len_encoding = 0x7;
17015              break;
17016            case 2:
17017              len_encoding = 0xa;
17018              break;
17019            case 3:
17020              len_encoding = 0x6;
17021              break;
17022            case 4:
17023              len_encoding = 0x2;
17024              break;
17025          }
17026          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17027                  (encoded_align_1.GetEncodingValue() << 4) |
17028                  first.Encode(22, 12) | (len_encoding << 8) |
17029                  (rn.GetCode() << 16));
17030          return;
17031        }
17032      }
17033      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17034      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17035          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17036          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17037          ((!rn.IsPC()) || AllowUnpredictable())) {
17038        if (cond.Is(al)) {
17039          const DRegister& first = nreglist.GetFirstDRegister();
17040          uint32_t len_encoding = nreglist.GetLength() - 1;
17041          EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
17042                  (encoded_align_2.GetEncodingValue() << 4) |
17043                  first.Encode(22, 12) | (len_encoding << 5) |
17044                  (rn.GetCode() << 16));
17045          return;
17046        }
17047      }
17048      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17049      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17050          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17051          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17052          ((!rn.IsPC()) || AllowUnpredictable())) {
17053        if (cond.Is(al)) {
17054          const DRegister& first = nreglist.GetFirstDRegister();
17055          uint32_t len_encoding = nreglist.GetLength() - 1;
17056          EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
17057                  (encoded_align_2.GetEncodingValue() << 4) |
17058                  first.Encode(22, 12) | (len_encoding << 5) |
17059                  (rn.GetCode() << 16));
17060          return;
17061        }
17062      }
17063      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17064      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17065          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
17066          encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
17067        if (cond.Is(al)) {
17068          const DRegister& first = nreglist.GetFirstDRegister();
17069          EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
17070                  (encoded_align_3.GetEncodingValue() << 4) |
17071                  first.Encode(22, 12) | (rn.GetCode() << 16));
17072          return;
17073        }
17074      }
17075      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17076      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17077          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
17078          encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
17079        if (cond.Is(al)) {
17080          const DRegister& first = nreglist.GetFirstDRegister();
17081          EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
17082                  (encoded_align_3.GetEncodingValue() << 4) |
17083                  first.Encode(22, 12) | (rn.GetCode() << 16));
17084          return;
17085        }
17086      }
17087    }
17088  }
17089  if (operand.IsPlainRegister()) {
17090    Register rn = operand.GetBaseRegister();
17091    Alignment align = operand.GetAlignment();
17092    Register rm = operand.GetOffsetRegister();
17093    Dt_size_6 encoded_dt(dt);
17094    Dt_size_7 encoded_dt_2(dt);
17095    Align_align_1 encoded_align_1(align, nreglist);
17096    Align_a_1 encoded_align_2(align, dt);
17097    Align_index_align_1 encoded_align_3(align, nreglist, dt);
17098    if (IsUsingT32()) {
17099      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17100      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17101          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17102          !rm.IsPC() && !rm.IsSP()) {
17103        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17104          const DRegister& first = nreglist.GetFirstDRegister();
17105          uint32_t len_encoding;
17106          switch (nreglist.GetLength()) {
17107            default:
17108              VIXL_UNREACHABLE_OR_FALLTHROUGH();
17109            case 1:
17110              len_encoding = 0x7;
17111              break;
17112            case 2:
17113              len_encoding = 0xa;
17114              break;
17115            case 3:
17116              len_encoding = 0x6;
17117              break;
17118            case 4:
17119              len_encoding = 0x2;
17120              break;
17121          }
17122          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17123                     (encoded_align_1.GetEncodingValue() << 4) |
17124                     first.Encode(22, 12) | (len_encoding << 8) |
17125                     (rn.GetCode() << 16) | rm.GetCode());
17126          AdvanceIT();
17127          return;
17128        }
17129      }
17130      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17131      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17132          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17133          !rm.IsPC() && !rm.IsSP()) {
17134        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17135          const DRegister& first = nreglist.GetFirstDRegister();
17136          uint32_t len_encoding = nreglist.GetLength() - 1;
17137          EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
17138                     (encoded_align_2.GetEncodingValue() << 4) |
17139                     first.Encode(22, 12) | (len_encoding << 5) |
17140                     (rn.GetCode() << 16) | rm.GetCode());
17141          AdvanceIT();
17142          return;
17143        }
17144      }
17145      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17146      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17147          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
17148        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17149          const DRegister& first = nreglist.GetFirstDRegister();
17150          EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
17151                     (encoded_align_3.GetEncodingValue() << 4) |
17152                     first.Encode(22, 12) | (rn.GetCode() << 16) |
17153                     rm.GetCode());
17154          AdvanceIT();
17155          return;
17156        }
17157      }
17158    } else {
17159      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17160      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17161          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17162          !rm.IsPC() && !rm.IsSP()) {
17163        if (cond.Is(al)) {
17164          const DRegister& first = nreglist.GetFirstDRegister();
17165          uint32_t len_encoding;
17166          switch (nreglist.GetLength()) {
17167            default:
17168              VIXL_UNREACHABLE_OR_FALLTHROUGH();
17169            case 1:
17170              len_encoding = 0x7;
17171              break;
17172            case 2:
17173              len_encoding = 0xa;
17174              break;
17175            case 3:
17176              len_encoding = 0x6;
17177              break;
17178            case 4:
17179              len_encoding = 0x2;
17180              break;
17181          }
17182          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17183                  (encoded_align_1.GetEncodingValue() << 4) |
17184                  first.Encode(22, 12) | (len_encoding << 8) |
17185                  (rn.GetCode() << 16) | rm.GetCode());
17186          return;
17187        }
17188      }
17189      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17190      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17191          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17192          !rm.IsPC() && !rm.IsSP()) {
17193        if (cond.Is(al)) {
17194          const DRegister& first = nreglist.GetFirstDRegister();
17195          uint32_t len_encoding = nreglist.GetLength() - 1;
17196          EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
17197                  (encoded_align_2.GetEncodingValue() << 4) |
17198                  first.Encode(22, 12) | (len_encoding << 5) |
17199                  (rn.GetCode() << 16) | rm.GetCode());
17200          return;
17201        }
17202      }
17203      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17204      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17205          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
17206        if (cond.Is(al)) {
17207          const DRegister& first = nreglist.GetFirstDRegister();
17208          EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
17209                  (encoded_align_3.GetEncodingValue() << 4) |
17210                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17211          return;
17212        }
17213      }
17214    }
17215  }
17216  Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
17217}
17218
17219void Assembler::vld2(Condition cond,
17220                     DataType dt,
17221                     const NeonRegisterList& nreglist,
17222                     const AlignedMemOperand& operand) {
17223  VIXL_ASSERT(AllowAssembler());
17224  CheckIT(cond);
17225  if (operand.IsImmediateZero()) {
17226    Register rn = operand.GetBaseRegister();
17227    Alignment align = operand.GetAlignment();
17228    Dt_size_7 encoded_dt(dt);
17229    Align_align_2 encoded_align_1(align, nreglist);
17230    Align_a_2 encoded_align_2(align, dt);
17231    Align_index_align_2 encoded_align_3(align, nreglist, dt);
17232    if (IsUsingT32()) {
17233      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17234      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17235          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17236           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17237           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17238          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17239          ((!rn.IsPC()) || AllowUnpredictable())) {
17240        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17241          const DRegister& first = nreglist.GetFirstDRegister();
17242          uint32_t len_encoding;
17243          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17244            len_encoding = 0x8;
17245          }
17246          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17247            len_encoding = 0x9;
17248          }
17249          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17250            len_encoding = 0x3;
17251          }
17252          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17253                     (encoded_align_1.GetEncodingValue() << 4) |
17254                     first.Encode(22, 12) | (len_encoding << 8) |
17255                     (rn.GetCode() << 16));
17256          AdvanceIT();
17257          return;
17258        }
17259      }
17260      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17261      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17262          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17263           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17264           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17265          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17266          ((!rn.IsPC()) || AllowUnpredictable())) {
17267        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17268          const DRegister& first = nreglist.GetFirstDRegister();
17269          uint32_t len_encoding;
17270          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17271            len_encoding = 0x8;
17272          }
17273          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17274            len_encoding = 0x9;
17275          }
17276          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17277            len_encoding = 0x3;
17278          }
17279          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17280                     (encoded_align_1.GetEncodingValue() << 4) |
17281                     first.Encode(22, 12) | (len_encoding << 8) |
17282                     (rn.GetCode() << 16));
17283          AdvanceIT();
17284          return;
17285        }
17286      }
17287      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17288      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17289          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17290           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17291          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17292          ((!rn.IsPC()) || AllowUnpredictable())) {
17293        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17294          const DRegister& first = nreglist.GetFirstDRegister();
17295          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17296          EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
17297                     (encoded_align_2.GetEncodingValue() << 4) |
17298                     first.Encode(22, 12) | (len_encoding << 5) |
17299                     (rn.GetCode() << 16));
17300          AdvanceIT();
17301          return;
17302        }
17303      }
17304      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17305      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17306          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17307           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17308          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17309          ((!rn.IsPC()) || AllowUnpredictable())) {
17310        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17311          const DRegister& first = nreglist.GetFirstDRegister();
17312          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17313          EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
17314                     (encoded_align_2.GetEncodingValue() << 4) |
17315                     first.Encode(22, 12) | (len_encoding << 5) |
17316                     (rn.GetCode() << 16));
17317          AdvanceIT();
17318          return;
17319        }
17320      }
17321      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17322      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17323          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17324           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17325          (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
17326          ((!rn.IsPC()) || AllowUnpredictable())) {
17327        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17328          const DRegister& first = nreglist.GetFirstDRegister();
17329          EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
17330                     (encoded_align_3.GetEncodingValue() << 4) |
17331                     first.Encode(22, 12) | (rn.GetCode() << 16));
17332          AdvanceIT();
17333          return;
17334        }
17335      }
17336      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17337      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17338          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17339           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17340          (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
17341          ((!rn.IsPC()) || AllowUnpredictable())) {
17342        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17343          const DRegister& first = nreglist.GetFirstDRegister();
17344          EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
17345                     (encoded_align_3.GetEncodingValue() << 4) |
17346                     first.Encode(22, 12) | (rn.GetCode() << 16));
17347          AdvanceIT();
17348          return;
17349        }
17350      }
17351    } else {
17352      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17353      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17354          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17355           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17356           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17357          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17358          ((!rn.IsPC()) || AllowUnpredictable())) {
17359        if (cond.Is(al)) {
17360          const DRegister& first = nreglist.GetFirstDRegister();
17361          uint32_t len_encoding;
17362          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17363            len_encoding = 0x8;
17364          }
17365          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17366            len_encoding = 0x9;
17367          }
17368          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17369            len_encoding = 0x3;
17370          }
17371          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
17372                  (encoded_align_1.GetEncodingValue() << 4) |
17373                  first.Encode(22, 12) | (len_encoding << 8) |
17374                  (rn.GetCode() << 16));
17375          return;
17376        }
17377      }
17378      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17379      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17380          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17381           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17382           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17383          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17384          ((!rn.IsPC()) || AllowUnpredictable())) {
17385        if (cond.Is(al)) {
17386          const DRegister& first = nreglist.GetFirstDRegister();
17387          uint32_t len_encoding;
17388          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17389            len_encoding = 0x8;
17390          }
17391          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17392            len_encoding = 0x9;
17393          }
17394          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17395            len_encoding = 0x3;
17396          }
17397          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17398                  (encoded_align_1.GetEncodingValue() << 4) |
17399                  first.Encode(22, 12) | (len_encoding << 8) |
17400                  (rn.GetCode() << 16));
17401          return;
17402        }
17403      }
17404      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17405      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17406          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17407           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17408          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17409          ((!rn.IsPC()) || AllowUnpredictable())) {
17410        if (cond.Is(al)) {
17411          const DRegister& first = nreglist.GetFirstDRegister();
17412          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17413          EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
17414                  (encoded_align_2.GetEncodingValue() << 4) |
17415                  first.Encode(22, 12) | (len_encoding << 5) |
17416                  (rn.GetCode() << 16));
17417          return;
17418        }
17419      }
17420      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17421      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17422          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17423           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17424          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17425          ((!rn.IsPC()) || AllowUnpredictable())) {
17426        if (cond.Is(al)) {
17427          const DRegister& first = nreglist.GetFirstDRegister();
17428          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17429          EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
17430                  (encoded_align_2.GetEncodingValue() << 4) |
17431                  first.Encode(22, 12) | (len_encoding << 5) |
17432                  (rn.GetCode() << 16));
17433          return;
17434        }
17435      }
17436      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17437      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17438          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17439           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17440          (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
17441          ((!rn.IsPC()) || AllowUnpredictable())) {
17442        if (cond.Is(al)) {
17443          const DRegister& first = nreglist.GetFirstDRegister();
17444          EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
17445                  (encoded_align_3.GetEncodingValue() << 4) |
17446                  first.Encode(22, 12) | (rn.GetCode() << 16));
17447          return;
17448        }
17449      }
17450      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17451      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17452          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17453           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17454          (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
17455          ((!rn.IsPC()) || AllowUnpredictable())) {
17456        if (cond.Is(al)) {
17457          const DRegister& first = nreglist.GetFirstDRegister();
17458          EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
17459                  (encoded_align_3.GetEncodingValue() << 4) |
17460                  first.Encode(22, 12) | (rn.GetCode() << 16));
17461          return;
17462        }
17463      }
17464    }
17465  }
17466  if (operand.IsPlainRegister()) {
17467    Register rn = operand.GetBaseRegister();
17468    Alignment align = operand.GetAlignment();
17469    Register rm = operand.GetOffsetRegister();
17470    Dt_size_7 encoded_dt(dt);
17471    Align_align_2 encoded_align_1(align, nreglist);
17472    Align_a_2 encoded_align_2(align, dt);
17473    Align_index_align_2 encoded_align_3(align, nreglist, dt);
17474    if (IsUsingT32()) {
17475      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17476      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17477          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17478           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17479           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17480          !rm.IsPC() && !rm.IsSP()) {
17481        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17482          const DRegister& first = nreglist.GetFirstDRegister();
17483          uint32_t len_encoding;
17484          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17485            len_encoding = 0x8;
17486          }
17487          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17488            len_encoding = 0x9;
17489          }
17490          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17491            len_encoding = 0x3;
17492          }
17493          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17494                     (encoded_align_1.GetEncodingValue() << 4) |
17495                     first.Encode(22, 12) | (len_encoding << 8) |
17496                     (rn.GetCode() << 16) | rm.GetCode());
17497          AdvanceIT();
17498          return;
17499        }
17500      }
17501      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17502      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17503          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17504           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17505          !rm.IsPC() && !rm.IsSP()) {
17506        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17507          const DRegister& first = nreglist.GetFirstDRegister();
17508          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17509          EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
17510                     (encoded_align_2.GetEncodingValue() << 4) |
17511                     first.Encode(22, 12) | (len_encoding << 5) |
17512                     (rn.GetCode() << 16) | rm.GetCode());
17513          AdvanceIT();
17514          return;
17515        }
17516      }
17517      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17518      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17519          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17520           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17521          !rm.IsPC() && !rm.IsSP()) {
17522        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17523          const DRegister& first = nreglist.GetFirstDRegister();
17524          EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
17525                     (encoded_align_3.GetEncodingValue() << 4) |
17526                     first.Encode(22, 12) | (rn.GetCode() << 16) |
17527                     rm.GetCode());
17528          AdvanceIT();
17529          return;
17530        }
17531      }
17532    } else {
17533      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17534      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17535          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17536           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17537           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17538          !rm.IsPC() && !rm.IsSP()) {
17539        if (cond.Is(al)) {
17540          const DRegister& first = nreglist.GetFirstDRegister();
17541          uint32_t len_encoding;
17542          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17543            len_encoding = 0x8;
17544          }
17545          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17546            len_encoding = 0x9;
17547          }
17548          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17549            len_encoding = 0x3;
17550          }
17551          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17552                  (encoded_align_1.GetEncodingValue() << 4) |
17553                  first.Encode(22, 12) | (len_encoding << 8) |
17554                  (rn.GetCode() << 16) | rm.GetCode());
17555          return;
17556        }
17557      }
17558      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17559      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17560          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17561           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17562          !rm.IsPC() && !rm.IsSP()) {
17563        if (cond.Is(al)) {
17564          const DRegister& first = nreglist.GetFirstDRegister();
17565          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17566          EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
17567                  (encoded_align_2.GetEncodingValue() << 4) |
17568                  first.Encode(22, 12) | (len_encoding << 5) |
17569                  (rn.GetCode() << 16) | rm.GetCode());
17570          return;
17571        }
17572      }
17573      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17574      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17575          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17576           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17577          !rm.IsPC() && !rm.IsSP()) {
17578        if (cond.Is(al)) {
17579          const DRegister& first = nreglist.GetFirstDRegister();
17580          EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
17581                  (encoded_align_3.GetEncodingValue() << 4) |
17582                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17583          return;
17584        }
17585      }
17586    }
17587  }
17588  Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
17589}
17590
17591void Assembler::vld3(Condition cond,
17592                     DataType dt,
17593                     const NeonRegisterList& nreglist,
17594                     const AlignedMemOperand& operand) {
17595  VIXL_ASSERT(AllowAssembler());
17596  CheckIT(cond);
17597  if (operand.IsImmediateZero()) {
17598    Register rn = operand.GetBaseRegister();
17599    Alignment align = operand.GetAlignment();
17600    Dt_size_7 encoded_dt(dt);
17601    Align_align_3 encoded_align_1(align);
17602    if (IsUsingT32()) {
17603      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17604      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17605          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17606           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17607          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17608          ((!rn.IsPC()) || AllowUnpredictable())) {
17609        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17610          const DRegister& first = nreglist.GetFirstDRegister();
17611          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17612          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17613                     (encoded_align_1.GetEncodingValue() << 4) |
17614                     first.Encode(22, 12) | (len_encoding << 8) |
17615                     (rn.GetCode() << 16));
17616          AdvanceIT();
17617          return;
17618        }
17619      }
17620      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17621      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17622          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17623           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17624          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17625          ((!rn.IsPC()) || AllowUnpredictable())) {
17626        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17627          const DRegister& first = nreglist.GetFirstDRegister();
17628          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17629          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17630                     (encoded_align_1.GetEncodingValue() << 4) |
17631                     first.Encode(22, 12) | (len_encoding << 8) |
17632                     (rn.GetCode() << 16));
17633          AdvanceIT();
17634          return;
17635        }
17636      }
17637    } else {
17638      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17639      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17640          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17641           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17642          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17643          ((!rn.IsPC()) || AllowUnpredictable())) {
17644        if (cond.Is(al)) {
17645          const DRegister& first = nreglist.GetFirstDRegister();
17646          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17647          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
17648                  (encoded_align_1.GetEncodingValue() << 4) |
17649                  first.Encode(22, 12) | (len_encoding << 8) |
17650                  (rn.GetCode() << 16));
17651          return;
17652        }
17653      }
17654      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17655      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17656          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17657           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17658          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17659          ((!rn.IsPC()) || AllowUnpredictable())) {
17660        if (cond.Is(al)) {
17661          const DRegister& first = nreglist.GetFirstDRegister();
17662          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17663          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17664                  (encoded_align_1.GetEncodingValue() << 4) |
17665                  first.Encode(22, 12) | (len_encoding << 8) |
17666                  (rn.GetCode() << 16));
17667          return;
17668        }
17669      }
17670    }
17671  }
17672  if (operand.IsPlainRegister()) {
17673    Register rn = operand.GetBaseRegister();
17674    Alignment align = operand.GetAlignment();
17675    Register rm = operand.GetOffsetRegister();
17676    Dt_size_7 encoded_dt(dt);
17677    Align_align_3 encoded_align_1(align);
17678    if (IsUsingT32()) {
17679      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17680      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17681          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17682           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17683          !rm.IsPC() && !rm.IsSP()) {
17684        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17685          const DRegister& first = nreglist.GetFirstDRegister();
17686          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17687          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17688                     (encoded_align_1.GetEncodingValue() << 4) |
17689                     first.Encode(22, 12) | (len_encoding << 8) |
17690                     (rn.GetCode() << 16) | rm.GetCode());
17691          AdvanceIT();
17692          return;
17693        }
17694      }
17695    } else {
17696      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17697      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17698          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17699           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17700          !rm.IsPC() && !rm.IsSP()) {
17701        if (cond.Is(al)) {
17702          const DRegister& first = nreglist.GetFirstDRegister();
17703          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17704          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17705                  (encoded_align_1.GetEncodingValue() << 4) |
17706                  first.Encode(22, 12) | (len_encoding << 8) |
17707                  (rn.GetCode() << 16) | rm.GetCode());
17708          return;
17709        }
17710      }
17711    }
17712  }
17713  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
17714}
17715
17716void Assembler::vld3(Condition cond,
17717                     DataType dt,
17718                     const NeonRegisterList& nreglist,
17719                     const MemOperand& operand) {
17720  VIXL_ASSERT(AllowAssembler());
17721  CheckIT(cond);
17722  if (operand.IsImmediateZero()) {
17723    Register rn = operand.GetBaseRegister();
17724    Dt_size_7 encoded_dt(dt);
17725    Index_1 encoded_align_1(nreglist, dt);
17726    if (IsUsingT32()) {
17727      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
17728      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17729          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17730           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17731          (operand.GetAddrMode() == Offset) &&
17732          ((!rn.IsPC()) || AllowUnpredictable())) {
17733        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17734          const DRegister& first = nreglist.GetFirstDRegister();
17735          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17736          EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
17737                     first.Encode(22, 12) | (len_encoding << 5) |
17738                     (rn.GetCode() << 16));
17739          AdvanceIT();
17740          return;
17741        }
17742      }
17743      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
17744      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17745          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17746           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17747          (operand.GetAddrMode() == PreIndex) &&
17748          ((!rn.IsPC()) || AllowUnpredictable())) {
17749        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17750          const DRegister& first = nreglist.GetFirstDRegister();
17751          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17752          EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
17753                     first.Encode(22, 12) | (len_encoding << 5) |
17754                     (rn.GetCode() << 16));
17755          AdvanceIT();
17756          return;
17757        }
17758      }
17759      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
17760      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17761          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17762           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17763          (operand.GetAddrMode() == Offset) &&
17764          ((!rn.IsPC()) || AllowUnpredictable())) {
17765        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17766          const DRegister& first = nreglist.GetFirstDRegister();
17767          EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
17768                     (encoded_align_1.GetEncodingValue() << 4) |
17769                     first.Encode(22, 12) | (rn.GetCode() << 16));
17770          AdvanceIT();
17771          return;
17772        }
17773      }
17774      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
17775      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17776          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17777           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17778          (operand.GetAddrMode() == PreIndex) &&
17779          ((!rn.IsPC()) || AllowUnpredictable())) {
17780        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17781          const DRegister& first = nreglist.GetFirstDRegister();
17782          EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
17783                     (encoded_align_1.GetEncodingValue() << 4) |
17784                     first.Encode(22, 12) | (rn.GetCode() << 16));
17785          AdvanceIT();
17786          return;
17787        }
17788      }
17789    } else {
17790      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
17791      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17792          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17793           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17794          (operand.GetAddrMode() == Offset) &&
17795          ((!rn.IsPC()) || AllowUnpredictable())) {
17796        if (cond.Is(al)) {
17797          const DRegister& first = nreglist.GetFirstDRegister();
17798          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17799          EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
17800                  first.Encode(22, 12) | (len_encoding << 5) |
17801                  (rn.GetCode() << 16));
17802          return;
17803        }
17804      }
17805      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
17806      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17807          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17808           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17809          (operand.GetAddrMode() == PreIndex) &&
17810          ((!rn.IsPC()) || AllowUnpredictable())) {
17811        if (cond.Is(al)) {
17812          const DRegister& first = nreglist.GetFirstDRegister();
17813          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17814          EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
17815                  first.Encode(22, 12) | (len_encoding << 5) |
17816                  (rn.GetCode() << 16));
17817          return;
17818        }
17819      }
17820      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
17821      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17822          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17823           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17824          (operand.GetAddrMode() == Offset) &&
17825          ((!rn.IsPC()) || AllowUnpredictable())) {
17826        if (cond.Is(al)) {
17827          const DRegister& first = nreglist.GetFirstDRegister();
17828          EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
17829                  (encoded_align_1.GetEncodingValue() << 4) |
17830                  first.Encode(22, 12) | (rn.GetCode() << 16));
17831          return;
17832        }
17833      }
17834      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
17835      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17836          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17837           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17838          (operand.GetAddrMode() == PreIndex) &&
17839          ((!rn.IsPC()) || AllowUnpredictable())) {
17840        if (cond.Is(al)) {
17841          const DRegister& first = nreglist.GetFirstDRegister();
17842          EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
17843                  (encoded_align_1.GetEncodingValue() << 4) |
17844                  first.Encode(22, 12) | (rn.GetCode() << 16));
17845          return;
17846        }
17847      }
17848    }
17849  }
17850  if (operand.IsPlainRegister()) {
17851    Register rn = operand.GetBaseRegister();
17852    Sign sign = operand.GetSign();
17853    Register rm = operand.GetOffsetRegister();
17854    Dt_size_7 encoded_dt(dt);
17855    Index_1 encoded_align_1(nreglist, dt);
17856    if (IsUsingT32()) {
17857      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
17858      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17859          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17860           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17861          sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17862        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17863          const DRegister& first = nreglist.GetFirstDRegister();
17864          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17865          EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
17866                     first.Encode(22, 12) | (len_encoding << 5) |
17867                     (rn.GetCode() << 16) | rm.GetCode());
17868          AdvanceIT();
17869          return;
17870        }
17871      }
17872      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
17873      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17874          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17875           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17876          sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17877        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17878          const DRegister& first = nreglist.GetFirstDRegister();
17879          EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
17880                     (encoded_align_1.GetEncodingValue() << 4) |
17881                     first.Encode(22, 12) | (rn.GetCode() << 16) |
17882                     rm.GetCode());
17883          AdvanceIT();
17884          return;
17885        }
17886      }
17887    } else {
17888      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
17889      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17890          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17891           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17892          sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17893        if (cond.Is(al)) {
17894          const DRegister& first = nreglist.GetFirstDRegister();
17895          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17896          EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
17897                  first.Encode(22, 12) | (len_encoding << 5) |
17898                  (rn.GetCode() << 16) | rm.GetCode());
17899          return;
17900        }
17901      }
17902      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
17903      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17904          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17905           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17906          sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17907        if (cond.Is(al)) {
17908          const DRegister& first = nreglist.GetFirstDRegister();
17909          EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
17910                  (encoded_align_1.GetEncodingValue() << 4) |
17911                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17912          return;
17913        }
17914      }
17915    }
17916  }
17917  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
17918}
17919
17920void Assembler::vld4(Condition cond,
17921                     DataType dt,
17922                     const NeonRegisterList& nreglist,
17923                     const AlignedMemOperand& operand) {
17924  VIXL_ASSERT(AllowAssembler());
17925  CheckIT(cond);
17926  if (operand.IsImmediateZero()) {
17927    Register rn = operand.GetBaseRegister();
17928    Alignment align = operand.GetAlignment();
17929    Dt_size_7 encoded_dt(dt);
17930    Dt_size_8 encoded_dt_2(dt, align);
17931    Align_align_4 encoded_align_1(align);
17932    Align_a_3 encoded_align_2(align, dt);
17933    Align_index_align_3 encoded_align_3(align, nreglist, dt);
17934    if (IsUsingT32()) {
17935      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17936      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17937          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17938           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17939          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17940          ((!rn.IsPC()) || AllowUnpredictable())) {
17941        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17942          const DRegister& first = nreglist.GetFirstDRegister();
17943          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17944          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17945                     (encoded_align_1.GetEncodingValue() << 4) |
17946                     first.Encode(22, 12) | (len_encoding << 8) |
17947                     (rn.GetCode() << 16));
17948          AdvanceIT();
17949          return;
17950        }
17951      }
17952      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17953      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17954          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17955           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17956          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17957          ((!rn.IsPC()) || AllowUnpredictable())) {
17958        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17959          const DRegister& first = nreglist.GetFirstDRegister();
17960          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17961          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17962                     (encoded_align_1.GetEncodingValue() << 4) |
17963                     first.Encode(22, 12) | (len_encoding << 8) |
17964                     (rn.GetCode() << 16));
17965          AdvanceIT();
17966          return;
17967        }
17968      }
17969      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17970      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17971          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17972           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17973          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17974          ((!rn.IsPC()) || AllowUnpredictable())) {
17975        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17976          const DRegister& first = nreglist.GetFirstDRegister();
17977          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17978          EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
17979                     (encoded_align_2.GetEncodingValue() << 4) |
17980                     first.Encode(22, 12) | (len_encoding << 5) |
17981                     (rn.GetCode() << 16));
17982          AdvanceIT();
17983          return;
17984        }
17985      }
17986      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17987      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17988          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17989           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17990          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17991          ((!rn.IsPC()) || AllowUnpredictable())) {
17992        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17993          const DRegister& first = nreglist.GetFirstDRegister();
17994          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17995          EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
17996                     (encoded_align_2.GetEncodingValue() << 4) |
17997                     first.Encode(22, 12) | (len_encoding << 5) |
17998                     (rn.GetCode() << 16));
17999          AdvanceIT();
18000          return;
18001        }
18002      }
18003      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18004      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18005          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18006           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18007          (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
18008          ((!rn.IsPC()) || AllowUnpredictable())) {
18009        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18010          const DRegister& first = nreglist.GetFirstDRegister();
18011          EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
18012                     (encoded_align_3.GetEncodingValue() << 4) |
18013                     first.Encode(22, 12) | (rn.GetCode() << 16));
18014          AdvanceIT();
18015          return;
18016        }
18017      }
18018      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18019      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18020          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18021           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18022          (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
18023          ((!rn.IsPC()) || AllowUnpredictable())) {
18024        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18025          const DRegister& first = nreglist.GetFirstDRegister();
18026          EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
18027                     (encoded_align_3.GetEncodingValue() << 4) |
18028                     first.Encode(22, 12) | (rn.GetCode() << 16));
18029          AdvanceIT();
18030          return;
18031        }
18032      }
18033    } else {
18034      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18035      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18036          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18037           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18038          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
18039          ((!rn.IsPC()) || AllowUnpredictable())) {
18040        if (cond.Is(al)) {
18041          const DRegister& first = nreglist.GetFirstDRegister();
18042          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18043          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18044                  (encoded_align_1.GetEncodingValue() << 4) |
18045                  first.Encode(22, 12) | (len_encoding << 8) |
18046                  (rn.GetCode() << 16));
18047          return;
18048        }
18049      }
18050      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18051      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18052          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18053           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18054          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
18055          ((!rn.IsPC()) || AllowUnpredictable())) {
18056        if (cond.Is(al)) {
18057          const DRegister& first = nreglist.GetFirstDRegister();
18058          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18059          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18060                  (encoded_align_1.GetEncodingValue() << 4) |
18061                  first.Encode(22, 12) | (len_encoding << 8) |
18062                  (rn.GetCode() << 16));
18063          return;
18064        }
18065      }
18066      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18067      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18068          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18069           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18070          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
18071          ((!rn.IsPC()) || AllowUnpredictable())) {
18072        if (cond.Is(al)) {
18073          const DRegister& first = nreglist.GetFirstDRegister();
18074          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18075          EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18076                  (encoded_align_2.GetEncodingValue() << 4) |
18077                  first.Encode(22, 12) | (len_encoding << 5) |
18078                  (rn.GetCode() << 16));
18079          return;
18080        }
18081      }
18082      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18083      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18084          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18085           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18086          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
18087          ((!rn.IsPC()) || AllowUnpredictable())) {
18088        if (cond.Is(al)) {
18089          const DRegister& first = nreglist.GetFirstDRegister();
18090          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18091          EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18092                  (encoded_align_2.GetEncodingValue() << 4) |
18093                  first.Encode(22, 12) | (len_encoding << 5) |
18094                  (rn.GetCode() << 16));
18095          return;
18096        }
18097      }
18098      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18099      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18100          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18101           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18102          (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
18103          ((!rn.IsPC()) || AllowUnpredictable())) {
18104        if (cond.Is(al)) {
18105          const DRegister& first = nreglist.GetFirstDRegister();
18106          EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
18107                  (encoded_align_3.GetEncodingValue() << 4) |
18108                  first.Encode(22, 12) | (rn.GetCode() << 16));
18109          return;
18110        }
18111      }
18112      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18113      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18114          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18115           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18116          (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
18117          ((!rn.IsPC()) || AllowUnpredictable())) {
18118        if (cond.Is(al)) {
18119          const DRegister& first = nreglist.GetFirstDRegister();
18120          EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
18121                  (encoded_align_3.GetEncodingValue() << 4) |
18122                  first.Encode(22, 12) | (rn.GetCode() << 16));
18123          return;
18124        }
18125      }
18126    }
18127  }
18128  if (operand.IsPlainRegister()) {
18129    Register rn = operand.GetBaseRegister();
18130    Alignment align = operand.GetAlignment();
18131    Register rm = operand.GetOffsetRegister();
18132    Dt_size_7 encoded_dt(dt);
18133    Dt_size_8 encoded_dt_2(dt, align);
18134    Align_align_4 encoded_align_1(align);
18135    Align_a_3 encoded_align_2(align, dt);
18136    Align_index_align_3 encoded_align_3(align, nreglist, dt);
18137    if (IsUsingT32()) {
18138      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18139      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18140          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18141           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18142          !rm.IsPC() && !rm.IsSP()) {
18143        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18144          const DRegister& first = nreglist.GetFirstDRegister();
18145          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18146          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18147                     (encoded_align_1.GetEncodingValue() << 4) |
18148                     first.Encode(22, 12) | (len_encoding << 8) |
18149                     (rn.GetCode() << 16) | rm.GetCode());
18150          AdvanceIT();
18151          return;
18152        }
18153      }
18154      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18155      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18156          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18157           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18158          !rm.IsPC() && !rm.IsSP()) {
18159        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18160          const DRegister& first = nreglist.GetFirstDRegister();
18161          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18162          EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
18163                     (encoded_align_2.GetEncodingValue() << 4) |
18164                     first.Encode(22, 12) | (len_encoding << 5) |
18165                     (rn.GetCode() << 16) | rm.GetCode());
18166          AdvanceIT();
18167          return;
18168        }
18169      }
18170      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18171      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18172          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18173           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18174          !rm.IsPC() && !rm.IsSP()) {
18175        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18176          const DRegister& first = nreglist.GetFirstDRegister();
18177          EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
18178                     (encoded_align_3.GetEncodingValue() << 4) |
18179                     first.Encode(22, 12) | (rn.GetCode() << 16) |
18180                     rm.GetCode());
18181          AdvanceIT();
18182          return;
18183        }
18184      }
18185    } else {
18186      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18187      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18188          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18189           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18190          !rm.IsPC() && !rm.IsSP()) {
18191        if (cond.Is(al)) {
18192          const DRegister& first = nreglist.GetFirstDRegister();
18193          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18194          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18195                  (encoded_align_1.GetEncodingValue() << 4) |
18196                  first.Encode(22, 12) | (len_encoding << 8) |
18197                  (rn.GetCode() << 16) | rm.GetCode());
18198          return;
18199        }
18200      }
18201      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18202      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18203          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18204           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18205          !rm.IsPC() && !rm.IsSP()) {
18206        if (cond.Is(al)) {
18207          const DRegister& first = nreglist.GetFirstDRegister();
18208          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18209          EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
18210                  (encoded_align_2.GetEncodingValue() << 4) |
18211                  first.Encode(22, 12) | (len_encoding << 5) |
18212                  (rn.GetCode() << 16) | rm.GetCode());
18213          return;
18214        }
18215      }
18216      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18217      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18218          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18219           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18220          !rm.IsPC() && !rm.IsSP()) {
18221        if (cond.Is(al)) {
18222          const DRegister& first = nreglist.GetFirstDRegister();
18223          EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
18224                  (encoded_align_3.GetEncodingValue() << 4) |
18225                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18226          return;
18227        }
18228      }
18229    }
18230  }
18231  Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
18232}
18233
18234void Assembler::vldm(Condition cond,
18235                     DataType dt,
18236                     Register rn,
18237                     WriteBack write_back,
18238                     DRegisterList dreglist) {
18239  VIXL_ASSERT(AllowAssembler());
18240  CheckIT(cond);
18241  USE(dt);
18242  if (IsUsingT32()) {
18243    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
18244    if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18245      const DRegister& dreg = dreglist.GetFirstDRegister();
18246      unsigned len = dreglist.GetLength() * 2;
18247      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
18248                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18249                 (len & 0xff));
18250      AdvanceIT();
18251      return;
18252    }
18253  } else {
18254    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
18255    if (cond.IsNotNever() &&
18256        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18257      const DRegister& dreg = dreglist.GetFirstDRegister();
18258      unsigned len = dreglist.GetLength() * 2;
18259      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18260              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18261              (len & 0xff));
18262      return;
18263    }
18264  }
18265  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
18266}
18267
18268void Assembler::vldm(Condition cond,
18269                     DataType dt,
18270                     Register rn,
18271                     WriteBack write_back,
18272                     SRegisterList sreglist) {
18273  VIXL_ASSERT(AllowAssembler());
18274  CheckIT(cond);
18275  USE(dt);
18276  if (IsUsingT32()) {
18277    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
18278    const SRegister& sreg = sreglist.GetFirstSRegister();
18279    unsigned len = sreglist.GetLength();
18280    EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
18281               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18282               (len & 0xff));
18283    AdvanceIT();
18284    return;
18285  } else {
18286    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
18287    if (cond.IsNotNever()) {
18288      const SRegister& sreg = sreglist.GetFirstSRegister();
18289      unsigned len = sreglist.GetLength();
18290      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18291              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18292              (len & 0xff));
18293      return;
18294    }
18295  }
18296  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
18297}
18298
18299void Assembler::vldmdb(Condition cond,
18300                       DataType dt,
18301                       Register rn,
18302                       WriteBack write_back,
18303                       DRegisterList dreglist) {
18304  VIXL_ASSERT(AllowAssembler());
18305  CheckIT(cond);
18306  USE(dt);
18307  if (IsUsingT32()) {
18308    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
18309    if (write_back.DoesWriteBack() &&
18310        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18311      const DRegister& dreg = dreglist.GetFirstDRegister();
18312      unsigned len = dreglist.GetLength() * 2;
18313      EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
18314                 (len & 0xff));
18315      AdvanceIT();
18316      return;
18317    }
18318  } else {
18319    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
18320    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
18321        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18322      const DRegister& dreg = dreglist.GetFirstDRegister();
18323      unsigned len = dreglist.GetLength() * 2;
18324      EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18325              dreg.Encode(22, 12) | (len & 0xff));
18326      return;
18327    }
18328  }
18329  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
18330}
18331
18332void Assembler::vldmdb(Condition cond,
18333                       DataType dt,
18334                       Register rn,
18335                       WriteBack write_back,
18336                       SRegisterList sreglist) {
18337  VIXL_ASSERT(AllowAssembler());
18338  CheckIT(cond);
18339  USE(dt);
18340  if (IsUsingT32()) {
18341    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
18342    if (write_back.DoesWriteBack()) {
18343      const SRegister& sreg = sreglist.GetFirstSRegister();
18344      unsigned len = sreglist.GetLength();
18345      EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
18346                 (len & 0xff));
18347      AdvanceIT();
18348      return;
18349    }
18350  } else {
18351    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
18352    if (write_back.DoesWriteBack() && cond.IsNotNever()) {
18353      const SRegister& sreg = sreglist.GetFirstSRegister();
18354      unsigned len = sreglist.GetLength();
18355      EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18356              sreg.Encode(22, 12) | (len & 0xff));
18357      return;
18358    }
18359  }
18360  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
18361}
18362
18363void Assembler::vldmia(Condition cond,
18364                       DataType dt,
18365                       Register rn,
18366                       WriteBack write_back,
18367                       DRegisterList dreglist) {
18368  VIXL_ASSERT(AllowAssembler());
18369  CheckIT(cond);
18370  USE(dt);
18371  if (IsUsingT32()) {
18372    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
18373    if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18374      const DRegister& dreg = dreglist.GetFirstDRegister();
18375      unsigned len = dreglist.GetLength() * 2;
18376      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
18377                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18378                 (len & 0xff));
18379      AdvanceIT();
18380      return;
18381    }
18382  } else {
18383    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
18384    if (cond.IsNotNever() &&
18385        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18386      const DRegister& dreg = dreglist.GetFirstDRegister();
18387      unsigned len = dreglist.GetLength() * 2;
18388      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18389              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18390              (len & 0xff));
18391      return;
18392    }
18393  }
18394  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
18395}
18396
18397void Assembler::vldmia(Condition cond,
18398                       DataType dt,
18399                       Register rn,
18400                       WriteBack write_back,
18401                       SRegisterList sreglist) {
18402  VIXL_ASSERT(AllowAssembler());
18403  CheckIT(cond);
18404  USE(dt);
18405  if (IsUsingT32()) {
18406    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
18407    const SRegister& sreg = sreglist.GetFirstSRegister();
18408    unsigned len = sreglist.GetLength();
18409    EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
18410               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18411               (len & 0xff));
18412    AdvanceIT();
18413    return;
18414  } else {
18415    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
18416    if (cond.IsNotNever()) {
18417      const SRegister& sreg = sreglist.GetFirstSRegister();
18418      unsigned len = sreglist.GetLength();
18419      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18420              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18421              (len & 0xff));
18422      return;
18423    }
18424  }
18425  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
18426}
18427
18428void Assembler::vldr(Condition cond, DataType dt, DRegister rd, Label* label) {
18429  VIXL_ASSERT(AllowAssembler());
18430  CheckIT(cond);
18431  Label::Offset offset =
18432      label->IsBound()
18433          ? label->GetLocation() -
18434                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
18435          : 0;
18436  if (IsUsingT32()) {
18437    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
18438    if (dt.IsNoneOr(Untyped64) &&
18439        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18440          ((offset & 0x3) == 0)) ||
18441         !label->IsBound())) {
18442      static class EmitOp : public Label::LabelEmitOperator {
18443       public:
18444        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18445        uint32_t Encode(uint32_t instr,
18446                        Label::Offset pc,
18447                        const Label* label) const {
18448          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18449          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18450                      ((offset & 0x3) == 0));
18451          int32_t target = offset >> 2;
18452          uint32_t U = (target >= 0) && !label->IsMinusZero();
18453          target = abs(target) | (U << 8);
18454          return instr | (target & 0xff) | ((target & 0x100) << 15);
18455        }
18456      } immop;
18457      EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12), label, immop));
18458      AdvanceIT();
18459      return;
18460    }
18461  } else {
18462    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
18463    if (dt.IsNoneOr(Untyped64) &&
18464        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18465          ((offset & 0x3) == 0)) ||
18466         !label->IsBound()) &&
18467        cond.IsNotNever()) {
18468      static class EmitOp : public Label::LabelEmitOperator {
18469       public:
18470        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18471        uint32_t Encode(uint32_t instr,
18472                        Label::Offset pc,
18473                        const Label* label) const {
18474          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18475          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18476                      ((offset & 0x3) == 0));
18477          int32_t target = offset >> 2;
18478          uint32_t U = (target >= 0) && !label->IsMinusZero();
18479          target = abs(target) | (U << 8);
18480          return instr | (target & 0xff) | ((target & 0x100) << 15);
18481        }
18482      } immop;
18483      EmitA32(
18484          Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
18485               label,
18486               immop));
18487      return;
18488    }
18489  }
18490  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, label);
18491}
18492
18493void Assembler::vldr(Condition cond,
18494                     DataType dt,
18495                     DRegister rd,
18496                     const MemOperand& operand) {
18497  VIXL_ASSERT(AllowAssembler());
18498  CheckIT(cond);
18499  if (operand.IsImmediate()) {
18500    Register rn = operand.GetBaseRegister();
18501    int32_t offset = operand.GetOffsetImmediate();
18502    if (IsUsingT32()) {
18503      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
18504      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18505          ((offset % 4) == 0) && rn.Is(pc) &&
18506          (operand.GetAddrMode() == Offset)) {
18507        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18508        uint32_t offset_ = abs(offset) >> 2;
18509        EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
18510        AdvanceIT();
18511        return;
18512      }
18513      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
18514      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18515          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18516          ((rn.GetCode() & 0xf) != 0xf)) {
18517        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18518        uint32_t offset_ = abs(offset) >> 2;
18519        EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
18520                   offset_ | (sign << 23));
18521        AdvanceIT();
18522        return;
18523      }
18524    } else {
18525      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
18526      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18527          ((offset % 4) == 0) && rn.Is(pc) &&
18528          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
18529        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18530        uint32_t offset_ = abs(offset) >> 2;
18531        EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18532                offset_ | (sign << 23));
18533        return;
18534      }
18535      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
18536      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18537          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18538          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
18539        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18540        uint32_t offset_ = abs(offset) >> 2;
18541        EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18542                (rn.GetCode() << 16) | offset_ | (sign << 23));
18543        return;
18544      }
18545    }
18546  }
18547  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
18548}
18549
18550void Assembler::vldr(Condition cond, DataType dt, SRegister rd, Label* label) {
18551  VIXL_ASSERT(AllowAssembler());
18552  CheckIT(cond);
18553  Label::Offset offset =
18554      label->IsBound()
18555          ? label->GetLocation() -
18556                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
18557          : 0;
18558  if (IsUsingT32()) {
18559    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
18560    if (dt.IsNoneOr(Untyped32) &&
18561        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18562          ((offset & 0x3) == 0)) ||
18563         !label->IsBound())) {
18564      static class EmitOp : public Label::LabelEmitOperator {
18565       public:
18566        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18567        uint32_t Encode(uint32_t instr,
18568                        Label::Offset pc,
18569                        const Label* label) const {
18570          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18571          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18572                      ((offset & 0x3) == 0));
18573          int32_t target = offset >> 2;
18574          uint32_t U = (target >= 0) && !label->IsMinusZero();
18575          target = abs(target) | (U << 8);
18576          return instr | (target & 0xff) | ((target & 0x100) << 15);
18577        }
18578      } immop;
18579      EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12), label, immop));
18580      AdvanceIT();
18581      return;
18582    }
18583  } else {
18584    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
18585    if (dt.IsNoneOr(Untyped32) &&
18586        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18587          ((offset & 0x3) == 0)) ||
18588         !label->IsBound()) &&
18589        cond.IsNotNever()) {
18590      static class EmitOp : public Label::LabelEmitOperator {
18591       public:
18592        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18593        uint32_t Encode(uint32_t instr,
18594                        Label::Offset pc,
18595                        const Label* label) const {
18596          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18597          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18598                      ((offset & 0x3) == 0));
18599          int32_t target = offset >> 2;
18600          uint32_t U = (target >= 0) && !label->IsMinusZero();
18601          target = abs(target) | (U << 8);
18602          return instr | (target & 0xff) | ((target & 0x100) << 15);
18603        }
18604      } immop;
18605      EmitA32(
18606          Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
18607               label,
18608               immop));
18609      return;
18610    }
18611  }
18612  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, label);
18613}
18614
18615void Assembler::vldr(Condition cond,
18616                     DataType dt,
18617                     SRegister rd,
18618                     const MemOperand& operand) {
18619  VIXL_ASSERT(AllowAssembler());
18620  CheckIT(cond);
18621  if (operand.IsImmediate()) {
18622    Register rn = operand.GetBaseRegister();
18623    int32_t offset = operand.GetOffsetImmediate();
18624    if (IsUsingT32()) {
18625      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
18626      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18627          ((offset % 4) == 0) && rn.Is(pc) &&
18628          (operand.GetAddrMode() == Offset)) {
18629        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18630        uint32_t offset_ = abs(offset) >> 2;
18631        EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
18632        AdvanceIT();
18633        return;
18634      }
18635      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
18636      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18637          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18638          ((rn.GetCode() & 0xf) != 0xf)) {
18639        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18640        uint32_t offset_ = abs(offset) >> 2;
18641        EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
18642                   offset_ | (sign << 23));
18643        AdvanceIT();
18644        return;
18645      }
18646    } else {
18647      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
18648      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18649          ((offset % 4) == 0) && rn.Is(pc) &&
18650          (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
18651        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18652        uint32_t offset_ = abs(offset) >> 2;
18653        EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18654                offset_ | (sign << 23));
18655        return;
18656      }
18657      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
18658      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18659          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18660          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
18661        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18662        uint32_t offset_ = abs(offset) >> 2;
18663        EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18664                (rn.GetCode() << 16) | offset_ | (sign << 23));
18665        return;
18666      }
18667    }
18668  }
18669  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
18670}
18671
18672void Assembler::vmax(
18673    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18674  VIXL_ASSERT(AllowAssembler());
18675  CheckIT(cond);
18676  Dt_U_size_1 encoded_dt(dt);
18677  if (IsUsingT32()) {
18678    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
18679    if (dt.Is(F32)) {
18680      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18681        EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18682                   rm.Encode(5, 0));
18683        AdvanceIT();
18684        return;
18685      }
18686    }
18687    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
18688    if (encoded_dt.IsValid()) {
18689      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18690        EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18691                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18692                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18693        AdvanceIT();
18694        return;
18695      }
18696    }
18697  } else {
18698    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
18699    if (dt.Is(F32)) {
18700      if (cond.Is(al)) {
18701        EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18702                rm.Encode(5, 0));
18703        return;
18704      }
18705    }
18706    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
18707    if (encoded_dt.IsValid()) {
18708      if (cond.Is(al)) {
18709        EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18710                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18711                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18712        return;
18713      }
18714    }
18715  }
18716  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
18717}
18718
18719void Assembler::vmax(
18720    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18721  VIXL_ASSERT(AllowAssembler());
18722  CheckIT(cond);
18723  Dt_U_size_1 encoded_dt(dt);
18724  if (IsUsingT32()) {
18725    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
18726    if (dt.Is(F32)) {
18727      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18728        EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18729                   rm.Encode(5, 0));
18730        AdvanceIT();
18731        return;
18732      }
18733    }
18734    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
18735    if (encoded_dt.IsValid()) {
18736      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18737        EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18738                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18739                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18740        AdvanceIT();
18741        return;
18742      }
18743    }
18744  } else {
18745    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
18746    if (dt.Is(F32)) {
18747      if (cond.Is(al)) {
18748        EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18749                rm.Encode(5, 0));
18750        return;
18751      }
18752    }
18753    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
18754    if (encoded_dt.IsValid()) {
18755      if (cond.Is(al)) {
18756        EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18757                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18758                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18759        return;
18760      }
18761    }
18762  }
18763  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
18764}
18765
18766void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18767  VIXL_ASSERT(AllowAssembler());
18768  CheckIT(al);
18769  if (IsUsingT32()) {
18770    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
18771    if (OutsideITBlock() && dt.Is(F32)) {
18772      EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18773                 rm.Encode(5, 0));
18774      AdvanceIT();
18775      return;
18776    }
18777    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
18778    if (OutsideITBlock() && dt.Is(F64)) {
18779      EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18780                 rm.Encode(5, 0));
18781      AdvanceIT();
18782      return;
18783    }
18784  } else {
18785    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
18786    if (dt.Is(F32)) {
18787      EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18788              rm.Encode(5, 0));
18789      return;
18790    }
18791    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
18792    if (dt.Is(F64)) {
18793      EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18794              rm.Encode(5, 0));
18795      return;
18796    }
18797  }
18798  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18799}
18800
18801void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18802  VIXL_ASSERT(AllowAssembler());
18803  CheckIT(al);
18804  if (IsUsingT32()) {
18805    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
18806    if (OutsideITBlock() && dt.Is(F32)) {
18807      EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18808                 rm.Encode(5, 0));
18809      AdvanceIT();
18810      return;
18811    }
18812  } else {
18813    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
18814    if (dt.Is(F32)) {
18815      EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18816              rm.Encode(5, 0));
18817      return;
18818    }
18819  }
18820  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18821}
18822
18823void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
18824  VIXL_ASSERT(AllowAssembler());
18825  CheckIT(al);
18826  if (IsUsingT32()) {
18827    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
18828    if (OutsideITBlock() && dt.Is(F32)) {
18829      EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18830                 rm.Encode(5, 0));
18831      AdvanceIT();
18832      return;
18833    }
18834  } else {
18835    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
18836    if (dt.Is(F32)) {
18837      EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18838              rm.Encode(5, 0));
18839      return;
18840    }
18841  }
18842  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18843}
18844
18845void Assembler::vmin(
18846    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18847  VIXL_ASSERT(AllowAssembler());
18848  CheckIT(cond);
18849  Dt_U_size_1 encoded_dt(dt);
18850  if (IsUsingT32()) {
18851    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
18852    if (dt.Is(F32)) {
18853      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18854        EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18855                   rm.Encode(5, 0));
18856        AdvanceIT();
18857        return;
18858      }
18859    }
18860    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
18861    if (encoded_dt.IsValid()) {
18862      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18863        EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18864                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18865                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18866        AdvanceIT();
18867        return;
18868      }
18869    }
18870  } else {
18871    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
18872    if (dt.Is(F32)) {
18873      if (cond.Is(al)) {
18874        EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18875                rm.Encode(5, 0));
18876        return;
18877      }
18878    }
18879    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
18880    if (encoded_dt.IsValid()) {
18881      if (cond.Is(al)) {
18882        EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18883                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18884                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18885        return;
18886      }
18887    }
18888  }
18889  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
18890}
18891
18892void Assembler::vmin(
18893    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18894  VIXL_ASSERT(AllowAssembler());
18895  CheckIT(cond);
18896  Dt_U_size_1 encoded_dt(dt);
18897  if (IsUsingT32()) {
18898    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
18899    if (dt.Is(F32)) {
18900      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18901        EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18902                   rm.Encode(5, 0));
18903        AdvanceIT();
18904        return;
18905      }
18906    }
18907    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
18908    if (encoded_dt.IsValid()) {
18909      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18910        EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18911                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18912                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18913        AdvanceIT();
18914        return;
18915      }
18916    }
18917  } else {
18918    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
18919    if (dt.Is(F32)) {
18920      if (cond.Is(al)) {
18921        EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18922                rm.Encode(5, 0));
18923        return;
18924      }
18925    }
18926    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
18927    if (encoded_dt.IsValid()) {
18928      if (cond.Is(al)) {
18929        EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18930                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18931                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18932        return;
18933      }
18934    }
18935  }
18936  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
18937}
18938
18939void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18940  VIXL_ASSERT(AllowAssembler());
18941  CheckIT(al);
18942  if (IsUsingT32()) {
18943    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
18944    if (OutsideITBlock() && dt.Is(F32)) {
18945      EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18946                 rm.Encode(5, 0));
18947      AdvanceIT();
18948      return;
18949    }
18950    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
18951    if (OutsideITBlock() && dt.Is(F64)) {
18952      EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18953                 rm.Encode(5, 0));
18954      AdvanceIT();
18955      return;
18956    }
18957  } else {
18958    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
18959    if (dt.Is(F32)) {
18960      EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18961              rm.Encode(5, 0));
18962      return;
18963    }
18964    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
18965    if (dt.Is(F64)) {
18966      EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18967              rm.Encode(5, 0));
18968      return;
18969    }
18970  }
18971  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18972}
18973
18974void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18975  VIXL_ASSERT(AllowAssembler());
18976  CheckIT(al);
18977  if (IsUsingT32()) {
18978    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
18979    if (OutsideITBlock() && dt.Is(F32)) {
18980      EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18981                 rm.Encode(5, 0));
18982      AdvanceIT();
18983      return;
18984    }
18985  } else {
18986    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
18987    if (dt.Is(F32)) {
18988      EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18989              rm.Encode(5, 0));
18990      return;
18991    }
18992  }
18993  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18994}
18995
18996void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
18997  VIXL_ASSERT(AllowAssembler());
18998  CheckIT(al);
18999  if (IsUsingT32()) {
19000    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19001    if (OutsideITBlock() && dt.Is(F32)) {
19002      EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19003                 rm.Encode(5, 0));
19004      AdvanceIT();
19005      return;
19006    }
19007  } else {
19008    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19009    if (dt.Is(F32)) {
19010      EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19011              rm.Encode(5, 0));
19012      return;
19013    }
19014  }
19015  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
19016}
19017
19018void Assembler::vmla(
19019    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
19020  VIXL_ASSERT(AllowAssembler());
19021  CheckIT(cond);
19022  Dt_size_9 encoded_dt(dt);
19023  if (IsUsingT32()) {
19024    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
19025    if (encoded_dt.IsValid() &&
19026        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19027         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19028          (rm.GetLane() <= 1)))) {
19029      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19030        EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19031                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19032                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19033        AdvanceIT();
19034        return;
19035      }
19036    }
19037  } else {
19038    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
19039    if (encoded_dt.IsValid() &&
19040        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19041         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19042          (rm.GetLane() <= 1)))) {
19043      if (cond.Is(al)) {
19044        EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19045                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19046                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19047        return;
19048      }
19049    }
19050  }
19051  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19052}
19053
19054void Assembler::vmla(
19055    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
19056  VIXL_ASSERT(AllowAssembler());
19057  CheckIT(cond);
19058  Dt_size_9 encoded_dt(dt);
19059  if (IsUsingT32()) {
19060    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
19061    if (encoded_dt.IsValid() &&
19062        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19063         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19064          (rm.GetLane() <= 1)))) {
19065      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19066        EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19067                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19068                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19069        AdvanceIT();
19070        return;
19071      }
19072    }
19073  } else {
19074    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
19075    if (encoded_dt.IsValid() &&
19076        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19077         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19078          (rm.GetLane() <= 1)))) {
19079      if (cond.Is(al)) {
19080        EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19081                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19082                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19083        return;
19084      }
19085    }
19086  }
19087  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19088}
19089
19090void Assembler::vmla(
19091    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19092  VIXL_ASSERT(AllowAssembler());
19093  CheckIT(cond);
19094  Dt_size_10 encoded_dt(dt);
19095  if (IsUsingT32()) {
19096    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19097    if (dt.Is(F32)) {
19098      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19099        EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19100                   rm.Encode(5, 0));
19101        AdvanceIT();
19102        return;
19103      }
19104    }
19105    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19106    if (dt.Is(F64)) {
19107      EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19108                 rm.Encode(5, 0));
19109      AdvanceIT();
19110      return;
19111    }
19112    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
19113    if (encoded_dt.IsValid()) {
19114      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19115        EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
19116                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19117        AdvanceIT();
19118        return;
19119      }
19120    }
19121  } else {
19122    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19123    if (dt.Is(F32)) {
19124      if (cond.Is(al)) {
19125        EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19126                rm.Encode(5, 0));
19127        return;
19128      }
19129    }
19130    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19131    if (dt.Is(F64) && cond.IsNotNever()) {
19132      EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19133              rn.Encode(7, 16) | rm.Encode(5, 0));
19134      return;
19135    }
19136    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
19137    if (encoded_dt.IsValid()) {
19138      if (cond.Is(al)) {
19139        EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
19140                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19141        return;
19142      }
19143    }
19144  }
19145  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19146}
19147
19148void Assembler::vmla(
19149    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19150  VIXL_ASSERT(AllowAssembler());
19151  CheckIT(cond);
19152  Dt_size_10 encoded_dt(dt);
19153  if (IsUsingT32()) {
19154    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19155    if (dt.Is(F32)) {
19156      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19157        EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19158                   rm.Encode(5, 0));
19159        AdvanceIT();
19160        return;
19161      }
19162    }
19163    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
19164    if (encoded_dt.IsValid()) {
19165      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19166        EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
19167                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19168        AdvanceIT();
19169        return;
19170      }
19171    }
19172  } else {
19173    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19174    if (dt.Is(F32)) {
19175      if (cond.Is(al)) {
19176        EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19177                rm.Encode(5, 0));
19178        return;
19179      }
19180    }
19181    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
19182    if (encoded_dt.IsValid()) {
19183      if (cond.Is(al)) {
19184        EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
19185                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19186        return;
19187      }
19188    }
19189  }
19190  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19191}
19192
19193void Assembler::vmla(
19194    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
19195  VIXL_ASSERT(AllowAssembler());
19196  CheckIT(cond);
19197  if (IsUsingT32()) {
19198    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19199    if (dt.Is(F32)) {
19200      EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19201                 rm.Encode(5, 0));
19202      AdvanceIT();
19203      return;
19204    }
19205  } else {
19206    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19207    if (dt.Is(F32) && cond.IsNotNever()) {
19208      EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19209              rn.Encode(7, 16) | rm.Encode(5, 0));
19210      return;
19211    }
19212  }
19213  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19214}
19215
19216void Assembler::vmlal(
19217    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
19218  VIXL_ASSERT(AllowAssembler());
19219  CheckIT(cond);
19220  Dt_size_11 encoded_dt(dt);
19221  if (IsUsingT32()) {
19222    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
19223    if (encoded_dt.IsValid() &&
19224        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19225         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19226          (rm.GetLane() <= 1)))) {
19227      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19228        EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
19229                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19230                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19231        AdvanceIT();
19232        return;
19233      }
19234    }
19235  } else {
19236    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
19237    if (encoded_dt.IsValid() &&
19238        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19239         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19240          (rm.GetLane() <= 1)))) {
19241      if (cond.Is(al)) {
19242        EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
19243                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19244                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19245        return;
19246      }
19247    }
19248  }
19249  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
19250}
19251
19252void Assembler::vmlal(
19253    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
19254  VIXL_ASSERT(AllowAssembler());
19255  CheckIT(cond);
19256  Dt_size_12 encoded_dt(dt);
19257  if (IsUsingT32()) {
19258    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
19259    if (encoded_dt.IsValid()) {
19260      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19261        EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
19262                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19263                   rn.Encode(7, 16) | rm.Encode(5, 0));
19264        AdvanceIT();
19265        return;
19266      }
19267    }
19268  } else {
19269    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
19270    if (encoded_dt.IsValid()) {
19271      if (cond.Is(al)) {
19272        EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
19273                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19274                rn.Encode(7, 16) | rm.Encode(5, 0));
19275        return;
19276      }
19277    }
19278  }
19279  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
19280}
19281
19282void Assembler::vmls(
19283    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
19284  VIXL_ASSERT(AllowAssembler());
19285  CheckIT(cond);
19286  Dt_size_9 encoded_dt(dt);
19287  if (IsUsingT32()) {
19288    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
19289    if (encoded_dt.IsValid() &&
19290        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19291         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19292          (rm.GetLane() <= 1)))) {
19293      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19294        EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19295                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19296                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19297        AdvanceIT();
19298        return;
19299      }
19300    }
19301  } else {
19302    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
19303    if (encoded_dt.IsValid() &&
19304        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19305         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19306          (rm.GetLane() <= 1)))) {
19307      if (cond.Is(al)) {
19308        EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19309                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19310                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19311        return;
19312      }
19313    }
19314  }
19315  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19316}
19317
19318void Assembler::vmls(
19319    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
19320  VIXL_ASSERT(AllowAssembler());
19321  CheckIT(cond);
19322  Dt_size_9 encoded_dt(dt);
19323  if (IsUsingT32()) {
19324    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
19325    if (encoded_dt.IsValid() &&
19326        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19327         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19328          (rm.GetLane() <= 1)))) {
19329      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19330        EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19331                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19332                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19333        AdvanceIT();
19334        return;
19335      }
19336    }
19337  } else {
19338    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
19339    if (encoded_dt.IsValid() &&
19340        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19341         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19342          (rm.GetLane() <= 1)))) {
19343      if (cond.Is(al)) {
19344        EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19345                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19346                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19347        return;
19348      }
19349    }
19350  }
19351  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19352}
19353
19354void Assembler::vmls(
19355    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19356  VIXL_ASSERT(AllowAssembler());
19357  CheckIT(cond);
19358  Dt_size_10 encoded_dt(dt);
19359  if (IsUsingT32()) {
19360    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19361    if (dt.Is(F32)) {
19362      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19363        EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19364                   rm.Encode(5, 0));
19365        AdvanceIT();
19366        return;
19367      }
19368    }
19369    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19370    if (dt.Is(F64)) {
19371      EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19372                 rm.Encode(5, 0));
19373      AdvanceIT();
19374      return;
19375    }
19376    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
19377    if (encoded_dt.IsValid()) {
19378      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19379        EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
19380                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19381        AdvanceIT();
19382        return;
19383      }
19384    }
19385  } else {
19386    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19387    if (dt.Is(F32)) {
19388      if (cond.Is(al)) {
19389        EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19390                rm.Encode(5, 0));
19391        return;
19392      }
19393    }
19394    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19395    if (dt.Is(F64) && cond.IsNotNever()) {
19396      EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19397              rn.Encode(7, 16) | rm.Encode(5, 0));
19398      return;
19399    }
19400    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
19401    if (encoded_dt.IsValid()) {
19402      if (cond.Is(al)) {
19403        EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
19404                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19405        return;
19406      }
19407    }
19408  }
19409  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19410}
19411
19412void Assembler::vmls(
19413    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19414  VIXL_ASSERT(AllowAssembler());
19415  CheckIT(cond);
19416  Dt_size_10 encoded_dt(dt);
19417  if (IsUsingT32()) {
19418    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19419    if (dt.Is(F32)) {
19420      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19421        EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19422                   rm.Encode(5, 0));
19423        AdvanceIT();
19424        return;
19425      }
19426    }
19427    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
19428    if (encoded_dt.IsValid()) {
19429      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19430        EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
19431                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19432        AdvanceIT();
19433        return;
19434      }
19435    }
19436  } else {
19437    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19438    if (dt.Is(F32)) {
19439      if (cond.Is(al)) {
19440        EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19441                rm.Encode(5, 0));
19442        return;
19443      }
19444    }
19445    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
19446    if (encoded_dt.IsValid()) {
19447      if (cond.Is(al)) {
19448        EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
19449                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19450        return;
19451      }
19452    }
19453  }
19454  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19455}
19456
19457void Assembler::vmls(
19458    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
19459  VIXL_ASSERT(AllowAssembler());
19460  CheckIT(cond);
19461  if (IsUsingT32()) {
19462    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19463    if (dt.Is(F32)) {
19464      EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19465                 rm.Encode(5, 0));
19466      AdvanceIT();
19467      return;
19468    }
19469  } else {
19470    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19471    if (dt.Is(F32) && cond.IsNotNever()) {
19472      EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19473              rn.Encode(7, 16) | rm.Encode(5, 0));
19474      return;
19475    }
19476  }
19477  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19478}
19479
19480void Assembler::vmlsl(
19481    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
19482  VIXL_ASSERT(AllowAssembler());
19483  CheckIT(cond);
19484  Dt_size_11 encoded_dt(dt);
19485  if (IsUsingT32()) {
19486    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
19487    if (encoded_dt.IsValid() &&
19488        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19489         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19490          (rm.GetLane() <= 1)))) {
19491      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19492        EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
19493                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19494                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19495        AdvanceIT();
19496        return;
19497      }
19498    }
19499  } else {
19500    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
19501    if (encoded_dt.IsValid() &&
19502        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19503         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19504          (rm.GetLane() <= 1)))) {
19505      if (cond.Is(al)) {
19506        EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
19507                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19508                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19509        return;
19510      }
19511    }
19512  }
19513  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
19514}
19515
19516void Assembler::vmlsl(
19517    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
19518  VIXL_ASSERT(AllowAssembler());
19519  CheckIT(cond);
19520  Dt_size_12 encoded_dt(dt);
19521  if (IsUsingT32()) {
19522    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
19523    if (encoded_dt.IsValid()) {
19524      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19525        EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
19526                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19527                   rn.Encode(7, 16) | rm.Encode(5, 0));
19528        AdvanceIT();
19529        return;
19530      }
19531    }
19532  } else {
19533    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
19534    if (encoded_dt.IsValid()) {
19535      if (cond.Is(al)) {
19536        EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
19537                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19538                rn.Encode(7, 16) | rm.Encode(5, 0));
19539        return;
19540      }
19541    }
19542  }
19543  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
19544}
19545
19546void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
19547  VIXL_ASSERT(AllowAssembler());
19548  CheckIT(cond);
19549  if (IsUsingT32()) {
19550    // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
19551    EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
19552    AdvanceIT();
19553    return;
19554  } else {
19555    // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
19556    if (cond.IsNotNever()) {
19557      EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19558              rn.Encode(7, 16));
19559      return;
19560    }
19561  }
19562  Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
19563}
19564
19565void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
19566  VIXL_ASSERT(AllowAssembler());
19567  CheckIT(cond);
19568  if (IsUsingT32()) {
19569    // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
19570    EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
19571    AdvanceIT();
19572    return;
19573  } else {
19574    // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
19575    if (cond.IsNotNever()) {
19576      EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
19577              (rt.GetCode() << 12));
19578      return;
19579    }
19580  }
19581  Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
19582}
19583
19584void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
19585  VIXL_ASSERT(AllowAssembler());
19586  CheckIT(cond);
19587  if (IsUsingT32()) {
19588    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
19589    EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
19590               rm.Encode(5, 0));
19591    AdvanceIT();
19592    return;
19593  } else {
19594    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
19595    if (cond.IsNotNever()) {
19596      EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19597              (rt2.GetCode() << 16) | rm.Encode(5, 0));
19598      return;
19599    }
19600  }
19601  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
19602}
19603
19604void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
19605  VIXL_ASSERT(AllowAssembler());
19606  CheckIT(cond);
19607  if (IsUsingT32()) {
19608    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
19609    EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
19610               (rt2.GetCode() << 16));
19611    AdvanceIT();
19612    return;
19613  } else {
19614    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
19615    if (cond.IsNotNever()) {
19616      EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
19617              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
19618      return;
19619    }
19620  }
19621  Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
19622}
19623
19624void Assembler::vmov(
19625    Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
19626  VIXL_ASSERT(AllowAssembler());
19627  CheckIT(cond);
19628  if (IsUsingT32()) {
19629    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
19630    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode())) {
19631      EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
19632                 rm.Encode(5, 0));
19633      AdvanceIT();
19634      return;
19635    }
19636  } else {
19637    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
19638    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
19639        cond.IsNotNever()) {
19640      EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19641              (rt2.GetCode() << 16) | rm.Encode(5, 0));
19642      return;
19643    }
19644  }
19645  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
19646}
19647
19648void Assembler::vmov(
19649    Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
19650  VIXL_ASSERT(AllowAssembler());
19651  CheckIT(cond);
19652  if (IsUsingT32()) {
19653    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
19654    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode())) {
19655      EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
19656                 (rt2.GetCode() << 16));
19657      AdvanceIT();
19658      return;
19659    }
19660  } else {
19661    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
19662    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
19663        cond.IsNotNever()) {
19664      EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
19665              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
19666      return;
19667    }
19668  }
19669  Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
19670}
19671
19672void Assembler::vmov(Condition cond,
19673                     DataType dt,
19674                     DRegisterLane rd,
19675                     Register rt) {
19676  VIXL_ASSERT(AllowAssembler());
19677  CheckIT(cond);
19678  Dt_opc1_opc2_1 encoded_dt(dt, rd);
19679  if (IsUsingT32()) {
19680    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
19681    if (encoded_dt.IsValid()) {
19682      EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19683                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19684                 rd.Encode(7, 16) | (rt.GetCode() << 12));
19685      AdvanceIT();
19686      return;
19687    }
19688  } else {
19689    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
19690    if (encoded_dt.IsValid() && cond.IsNotNever()) {
19691      EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
19692              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19693              ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
19694              (rt.GetCode() << 12));
19695      return;
19696    }
19697  }
19698  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
19699}
19700
19701void Assembler::vmov(Condition cond,
19702                     DataType dt,
19703                     DRegister rd,
19704                     const DOperand& operand) {
19705  VIXL_ASSERT(AllowAssembler());
19706  CheckIT(cond);
19707  if (operand.IsImmediate()) {
19708    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
19709    ImmediateVFP vfp(operand.GetNeonImmediate());
19710    if (IsUsingT32()) {
19711      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
19712      if (encoded_dt.IsValid()) {
19713        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19714          EmitT32_32(
19715              0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19716              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19717              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19718              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19719              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
19720          AdvanceIT();
19721          return;
19722        }
19723      }
19724      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
19725      if (dt.Is(F64) && vfp.IsValid()) {
19726        EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
19727                   (vfp.GetEncodingValue() & 0xf) |
19728                   ((vfp.GetEncodingValue() & 0xf0) << 12));
19729        AdvanceIT();
19730        return;
19731      }
19732    } else {
19733      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
19734      if (encoded_dt.IsValid()) {
19735        if (cond.Is(al)) {
19736          EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19737                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19738                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19739                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19740                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
19741          return;
19742        }
19743      }
19744      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
19745      if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
19746        EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19747                (vfp.GetEncodingValue() & 0xf) |
19748                ((vfp.GetEncodingValue() & 0xf0) << 12));
19749        return;
19750      }
19751    }
19752  }
19753  if (operand.IsRegister()) {
19754    DRegister rm = operand.GetRegister();
19755    if (IsUsingT32()) {
19756      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
19757      if (dt.Is(F64)) {
19758        EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
19759        AdvanceIT();
19760        return;
19761      }
19762      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
19763      if (!dt.Is(F64)) {
19764        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19765          EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19766                     rm.Encode(5, 0));
19767          AdvanceIT();
19768          return;
19769        }
19770      }
19771    } else {
19772      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
19773      if (dt.Is(F64) && cond.IsNotNever()) {
19774        EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19775                rm.Encode(5, 0));
19776        return;
19777      }
19778      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
19779      if (!dt.Is(F64)) {
19780        if (cond.Is(al)) {
19781          EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19782                  rm.Encode(5, 0));
19783          return;
19784        }
19785      }
19786    }
19787  }
19788  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19789}
19790
19791void Assembler::vmov(Condition cond,
19792                     DataType dt,
19793                     QRegister rd,
19794                     const QOperand& operand) {
19795  VIXL_ASSERT(AllowAssembler());
19796  CheckIT(cond);
19797  if (operand.IsImmediate()) {
19798    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
19799    if (IsUsingT32()) {
19800      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
19801      if (encoded_dt.IsValid()) {
19802        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19803          EmitT32_32(
19804              0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19805              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19806              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19807              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19808              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
19809          AdvanceIT();
19810          return;
19811        }
19812      }
19813    } else {
19814      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
19815      if (encoded_dt.IsValid()) {
19816        if (cond.Is(al)) {
19817          EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19818                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19819                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19820                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19821                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
19822          return;
19823        }
19824      }
19825    }
19826  }
19827  if (operand.IsRegister()) {
19828    QRegister rm = operand.GetRegister();
19829    if (IsUsingT32()) {
19830      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
19831      if (!dt.Is(F64)) {
19832        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19833          EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19834                     rm.Encode(5, 0));
19835          AdvanceIT();
19836          return;
19837        }
19838      }
19839    } else {
19840      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
19841      if (!dt.Is(F64)) {
19842        if (cond.Is(al)) {
19843          EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19844                  rm.Encode(5, 0));
19845          return;
19846        }
19847      }
19848    }
19849  }
19850  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19851}
19852
19853void Assembler::vmov(Condition cond,
19854                     DataType dt,
19855                     SRegister rd,
19856                     const SOperand& operand) {
19857  VIXL_ASSERT(AllowAssembler());
19858  CheckIT(cond);
19859  if (operand.IsImmediate()) {
19860    ImmediateVFP vfp(operand.GetNeonImmediate());
19861    if (IsUsingT32()) {
19862      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
19863      if (dt.Is(F32) && vfp.IsValid()) {
19864        EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
19865                   (vfp.GetEncodingValue() & 0xf) |
19866                   ((vfp.GetEncodingValue() & 0xf0) << 12));
19867        AdvanceIT();
19868        return;
19869      }
19870    } else {
19871      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
19872      if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
19873        EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19874                (vfp.GetEncodingValue() & 0xf) |
19875                ((vfp.GetEncodingValue() & 0xf0) << 12));
19876        return;
19877      }
19878    }
19879  }
19880  if (operand.IsRegister()) {
19881    SRegister rm = operand.GetRegister();
19882    if (IsUsingT32()) {
19883      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
19884      if (dt.Is(F32)) {
19885        EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
19886        AdvanceIT();
19887        return;
19888      }
19889    } else {
19890      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
19891      if (dt.Is(F32) && cond.IsNotNever()) {
19892        EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19893                rm.Encode(5, 0));
19894        return;
19895      }
19896    }
19897  }
19898  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19899}
19900
19901void Assembler::vmov(Condition cond,
19902                     DataType dt,
19903                     Register rt,
19904                     DRegisterLane rn) {
19905  VIXL_ASSERT(AllowAssembler());
19906  CheckIT(cond);
19907  Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
19908  if (IsUsingT32()) {
19909    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
19910    if (encoded_dt.IsValid()) {
19911      EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19912                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19913                 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
19914                 (rt.GetCode() << 12) | rn.Encode(7, 16));
19915      AdvanceIT();
19916      return;
19917    }
19918  } else {
19919    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
19920    if (encoded_dt.IsValid() && cond.IsNotNever()) {
19921      EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
19922              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19923              ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19924              ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
19925              (rt.GetCode() << 12) | rn.Encode(7, 16));
19926      return;
19927    }
19928  }
19929  Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
19930}
19931
19932void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
19933  VIXL_ASSERT(AllowAssembler());
19934  CheckIT(cond);
19935  Dt_U_imm3H_1 encoded_dt(dt);
19936  if (IsUsingT32()) {
19937    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
19938    if (encoded_dt.IsValid()) {
19939      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19940        EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
19941                   ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
19942                   rd.Encode(22, 12) | rm.Encode(5, 0));
19943        AdvanceIT();
19944        return;
19945      }
19946    }
19947  } else {
19948    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
19949    if (encoded_dt.IsValid()) {
19950      if (cond.Is(al)) {
19951        EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
19952                ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
19953                rd.Encode(22, 12) | rm.Encode(5, 0));
19954        return;
19955      }
19956    }
19957  }
19958  Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
19959}
19960
19961void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
19962  VIXL_ASSERT(AllowAssembler());
19963  CheckIT(cond);
19964  Dt_size_3 encoded_dt(dt);
19965  if (IsUsingT32()) {
19966    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
19967    if (encoded_dt.IsValid()) {
19968      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19969        EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
19970                   rd.Encode(22, 12) | rm.Encode(5, 0));
19971        AdvanceIT();
19972        return;
19973      }
19974    }
19975  } else {
19976    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
19977    if (encoded_dt.IsValid()) {
19978      if (cond.Is(al)) {
19979        EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
19980                rd.Encode(22, 12) | rm.Encode(5, 0));
19981        return;
19982      }
19983    }
19984  }
19985  Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
19986}
19987
19988void Assembler::vmrs(Condition cond,
19989                     RegisterOrAPSR_nzcv rt,
19990                     SpecialFPRegister spec_reg) {
19991  VIXL_ASSERT(AllowAssembler());
19992  CheckIT(cond);
19993  if (IsUsingT32()) {
19994    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
19995    EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
19996    AdvanceIT();
19997    return;
19998  } else {
19999    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
20000    if (cond.IsNotNever()) {
20001      EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20002              (spec_reg.GetReg() << 16));
20003      return;
20004    }
20005  }
20006  Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
20007}
20008
20009void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
20010  VIXL_ASSERT(AllowAssembler());
20011  CheckIT(cond);
20012  if (IsUsingT32()) {
20013    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
20014    EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
20015    AdvanceIT();
20016    return;
20017  } else {
20018    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
20019    if (cond.IsNotNever()) {
20020      EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
20021              (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
20022      return;
20023    }
20024  }
20025  Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
20026}
20027
20028void Assembler::vmul(Condition cond,
20029                     DataType dt,
20030                     DRegister rd,
20031                     DRegister rn,
20032                     DRegister dm,
20033                     unsigned index) {
20034  VIXL_ASSERT(AllowAssembler());
20035  CheckIT(cond);
20036  Dt_F_size_3 encoded_dt(dt);
20037  if (IsUsingT32()) {
20038    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
20039    if (encoded_dt.IsValid() &&
20040        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20041         (!dt.Is(I16) && (index <= 1)))) {
20042      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20043        uint32_t shift = 4;
20044        if (dt.Is(I16)) {
20045          shift = 3;
20046        }
20047        uint32_t mvm = dm.GetCode() | index << shift;
20048        EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20049                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20050                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20051                   ((mvm & 0x10) << 1));
20052        AdvanceIT();
20053        return;
20054      }
20055    }
20056  } else {
20057    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
20058    if (encoded_dt.IsValid() &&
20059        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20060         (!dt.Is(I16) && (index <= 1)))) {
20061      if (cond.Is(al)) {
20062        uint32_t shift = 4;
20063        if (dt.Is(I16)) {
20064          shift = 3;
20065        }
20066        uint32_t mvm = dm.GetCode() | index << shift;
20067        EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20068                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20069                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20070                ((mvm & 0x10) << 1));
20071        return;
20072      }
20073    }
20074  }
20075  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
20076}
20077
20078void Assembler::vmul(Condition cond,
20079                     DataType dt,
20080                     QRegister rd,
20081                     QRegister rn,
20082                     DRegister dm,
20083                     unsigned index) {
20084  VIXL_ASSERT(AllowAssembler());
20085  CheckIT(cond);
20086  Dt_F_size_3 encoded_dt(dt);
20087  if (IsUsingT32()) {
20088    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
20089    if (encoded_dt.IsValid() &&
20090        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20091         (!dt.Is(I16) && (index <= 1)))) {
20092      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20093        uint32_t shift = 4;
20094        if (dt.Is(I16)) {
20095          shift = 3;
20096        }
20097        uint32_t mvm = dm.GetCode() | index << shift;
20098        EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20099                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20100                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20101                   ((mvm & 0x10) << 1));
20102        AdvanceIT();
20103        return;
20104      }
20105    }
20106  } else {
20107    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
20108    if (encoded_dt.IsValid() &&
20109        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20110         (!dt.Is(I16) && (index <= 1)))) {
20111      if (cond.Is(al)) {
20112        uint32_t shift = 4;
20113        if (dt.Is(I16)) {
20114          shift = 3;
20115        }
20116        uint32_t mvm = dm.GetCode() | index << shift;
20117        EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20118                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20119                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20120                ((mvm & 0x10) << 1));
20121        return;
20122      }
20123    }
20124  }
20125  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
20126}
20127
20128void Assembler::vmul(
20129    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20130  VIXL_ASSERT(AllowAssembler());
20131  CheckIT(cond);
20132  Dt_op_size_1 encoded_dt(dt);
20133  if (IsUsingT32()) {
20134    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20135    if (dt.Is(F32)) {
20136      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20137        EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20138                   rm.Encode(5, 0));
20139        AdvanceIT();
20140        return;
20141      }
20142    }
20143    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
20144    if (dt.Is(F64)) {
20145      EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20146                 rm.Encode(5, 0));
20147      AdvanceIT();
20148      return;
20149    }
20150    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20151    if (encoded_dt.IsValid()) {
20152      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20153        EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20154                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20155                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20156        AdvanceIT();
20157        return;
20158      }
20159    }
20160  } else {
20161    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20162    if (dt.Is(F32)) {
20163      if (cond.Is(al)) {
20164        EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20165                rm.Encode(5, 0));
20166        return;
20167      }
20168    }
20169    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
20170    if (dt.Is(F64) && cond.IsNotNever()) {
20171      EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20172              rn.Encode(7, 16) | rm.Encode(5, 0));
20173      return;
20174    }
20175    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20176    if (encoded_dt.IsValid()) {
20177      if (cond.Is(al)) {
20178        EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20179                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20180                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20181        return;
20182      }
20183    }
20184  }
20185  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20186}
20187
20188void Assembler::vmul(
20189    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20190  VIXL_ASSERT(AllowAssembler());
20191  CheckIT(cond);
20192  Dt_op_size_1 encoded_dt(dt);
20193  if (IsUsingT32()) {
20194    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20195    if (dt.Is(F32)) {
20196      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20197        EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20198                   rm.Encode(5, 0));
20199        AdvanceIT();
20200        return;
20201      }
20202    }
20203    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20204    if (encoded_dt.IsValid()) {
20205      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20206        EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20207                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20208                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20209        AdvanceIT();
20210        return;
20211      }
20212    }
20213  } else {
20214    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20215    if (dt.Is(F32)) {
20216      if (cond.Is(al)) {
20217        EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20218                rm.Encode(5, 0));
20219        return;
20220      }
20221    }
20222    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20223    if (encoded_dt.IsValid()) {
20224      if (cond.Is(al)) {
20225        EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20226                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20227                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20228        return;
20229      }
20230    }
20231  }
20232  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20233}
20234
20235void Assembler::vmul(
20236    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20237  VIXL_ASSERT(AllowAssembler());
20238  CheckIT(cond);
20239  if (IsUsingT32()) {
20240    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
20241    if (dt.Is(F32)) {
20242      EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20243                 rm.Encode(5, 0));
20244      AdvanceIT();
20245      return;
20246    }
20247  } else {
20248    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
20249    if (dt.Is(F32) && cond.IsNotNever()) {
20250      EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20251              rn.Encode(7, 16) | rm.Encode(5, 0));
20252      return;
20253    }
20254  }
20255  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20256}
20257
20258void Assembler::vmull(Condition cond,
20259                      DataType dt,
20260                      QRegister rd,
20261                      DRegister rn,
20262                      DRegister dm,
20263                      unsigned index) {
20264  VIXL_ASSERT(AllowAssembler());
20265  CheckIT(cond);
20266  Dt_U_size_2 encoded_dt(dt);
20267  if (IsUsingT32()) {
20268    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
20269    if (encoded_dt.IsValid() &&
20270        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
20271         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
20272      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20273        uint32_t shift = 4;
20274        if (dt.Is(S16) || dt.Is(U16)) {
20275          shift = 3;
20276        }
20277        uint32_t mvm = dm.GetCode() | index << shift;
20278        EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20279                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20280                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20281                   ((mvm & 0x10) << 1));
20282        AdvanceIT();
20283        return;
20284      }
20285    }
20286  } else {
20287    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
20288    if (encoded_dt.IsValid() &&
20289        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
20290         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
20291      if (cond.Is(al)) {
20292        uint32_t shift = 4;
20293        if (dt.Is(S16) || dt.Is(U16)) {
20294          shift = 3;
20295        }
20296        uint32_t mvm = dm.GetCode() | index << shift;
20297        EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20298                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20299                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20300                ((mvm & 0x10) << 1));
20301        return;
20302      }
20303    }
20304  }
20305  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
20306}
20307
20308void Assembler::vmull(
20309    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
20310  VIXL_ASSERT(AllowAssembler());
20311  CheckIT(cond);
20312  Dt_op_U_size_1 encoded_dt(dt);
20313  if (IsUsingT32()) {
20314    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
20315    if (encoded_dt.IsValid()) {
20316      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20317        EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20318                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20319                   ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
20320                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20321        AdvanceIT();
20322        return;
20323      }
20324    }
20325  } else {
20326    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
20327    if (encoded_dt.IsValid()) {
20328      if (cond.Is(al)) {
20329        EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20330                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20331                ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
20332                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20333        return;
20334      }
20335    }
20336  }
20337  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
20338}
20339
20340void Assembler::vmvn(Condition cond,
20341                     DataType dt,
20342                     DRegister rd,
20343                     const DOperand& operand) {
20344  VIXL_ASSERT(AllowAssembler());
20345  CheckIT(cond);
20346  if (operand.IsImmediate()) {
20347    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
20348    if (IsUsingT32()) {
20349      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20350      if (encoded_dt.IsValid()) {
20351        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20352          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
20353                     rd.Encode(22, 12) |
20354                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20355                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20356                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20357          AdvanceIT();
20358          return;
20359        }
20360      }
20361    } else {
20362      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20363      if (encoded_dt.IsValid()) {
20364        if (cond.Is(al)) {
20365          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
20366                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20367                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20368                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20369          return;
20370        }
20371      }
20372    }
20373  }
20374  if (operand.IsRegister()) {
20375    DRegister rm = operand.GetRegister();
20376    USE(dt);
20377    if (IsUsingT32()) {
20378      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
20379      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20380        EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
20381        AdvanceIT();
20382        return;
20383      }
20384    } else {
20385      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
20386      if (cond.Is(al)) {
20387        EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
20388        return;
20389      }
20390    }
20391  }
20392  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
20393}
20394
20395void Assembler::vmvn(Condition cond,
20396                     DataType dt,
20397                     QRegister rd,
20398                     const QOperand& operand) {
20399  VIXL_ASSERT(AllowAssembler());
20400  CheckIT(cond);
20401  if (operand.IsImmediate()) {
20402    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
20403    if (IsUsingT32()) {
20404      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
20405      if (encoded_dt.IsValid()) {
20406        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20407          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
20408                     rd.Encode(22, 12) |
20409                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20410                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20411                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20412          AdvanceIT();
20413          return;
20414        }
20415      }
20416    } else {
20417      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
20418      if (encoded_dt.IsValid()) {
20419        if (cond.Is(al)) {
20420          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
20421                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20422                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20423                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20424          return;
20425        }
20426      }
20427    }
20428  }
20429  if (operand.IsRegister()) {
20430    QRegister rm = operand.GetRegister();
20431    USE(dt);
20432    if (IsUsingT32()) {
20433      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
20434      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20435        EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
20436        AdvanceIT();
20437        return;
20438      }
20439    } else {
20440      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
20441      if (cond.Is(al)) {
20442        EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
20443        return;
20444      }
20445    }
20446  }
20447  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
20448}
20449
20450void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
20451  VIXL_ASSERT(AllowAssembler());
20452  CheckIT(cond);
20453  Dt_F_size_1 encoded_dt(dt);
20454  if (IsUsingT32()) {
20455    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20456    if (encoded_dt.IsValid()) {
20457      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20458        EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20459                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20460                   rd.Encode(22, 12) | rm.Encode(5, 0));
20461        AdvanceIT();
20462        return;
20463      }
20464    }
20465    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
20466    if (dt.Is(F64)) {
20467      EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20468      AdvanceIT();
20469      return;
20470    }
20471  } else {
20472    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
20473    if (encoded_dt.IsValid()) {
20474      if (cond.Is(al)) {
20475        EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20476                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20477                rd.Encode(22, 12) | rm.Encode(5, 0));
20478        return;
20479      }
20480    }
20481    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
20482    if (dt.Is(F64) && cond.IsNotNever()) {
20483      EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20484              rm.Encode(5, 0));
20485      return;
20486    }
20487  }
20488  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20489}
20490
20491void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
20492  VIXL_ASSERT(AllowAssembler());
20493  CheckIT(cond);
20494  Dt_F_size_1 encoded_dt(dt);
20495  if (IsUsingT32()) {
20496    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
20497    if (encoded_dt.IsValid()) {
20498      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20499        EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20500                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20501                   rd.Encode(22, 12) | rm.Encode(5, 0));
20502        AdvanceIT();
20503        return;
20504      }
20505    }
20506  } else {
20507    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
20508    if (encoded_dt.IsValid()) {
20509      if (cond.Is(al)) {
20510        EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20511                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20512                rd.Encode(22, 12) | rm.Encode(5, 0));
20513        return;
20514      }
20515    }
20516  }
20517  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20518}
20519
20520void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
20521  VIXL_ASSERT(AllowAssembler());
20522  CheckIT(cond);
20523  if (IsUsingT32()) {
20524    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
20525    if (dt.Is(F32)) {
20526      EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20527      AdvanceIT();
20528      return;
20529    }
20530  } else {
20531    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
20532    if (dt.Is(F32) && cond.IsNotNever()) {
20533      EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20534              rm.Encode(5, 0));
20535      return;
20536    }
20537  }
20538  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20539}
20540
20541void Assembler::vnmla(
20542    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20543  VIXL_ASSERT(AllowAssembler());
20544  CheckIT(cond);
20545  if (IsUsingT32()) {
20546    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
20547    if (dt.Is(F32)) {
20548      EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20549                 rm.Encode(5, 0));
20550      AdvanceIT();
20551      return;
20552    }
20553  } else {
20554    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
20555    if (dt.Is(F32) && cond.IsNotNever()) {
20556      EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20557              rn.Encode(7, 16) | rm.Encode(5, 0));
20558      return;
20559    }
20560  }
20561  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
20562}
20563
20564void Assembler::vnmla(
20565    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20566  VIXL_ASSERT(AllowAssembler());
20567  CheckIT(cond);
20568  if (IsUsingT32()) {
20569    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
20570    if (dt.Is(F64)) {
20571      EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20572                 rm.Encode(5, 0));
20573      AdvanceIT();
20574      return;
20575    }
20576  } else {
20577    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
20578    if (dt.Is(F64) && cond.IsNotNever()) {
20579      EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20580              rn.Encode(7, 16) | rm.Encode(5, 0));
20581      return;
20582    }
20583  }
20584  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
20585}
20586
20587void Assembler::vnmls(
20588    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20589  VIXL_ASSERT(AllowAssembler());
20590  CheckIT(cond);
20591  if (IsUsingT32()) {
20592    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
20593    if (dt.Is(F32)) {
20594      EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20595                 rm.Encode(5, 0));
20596      AdvanceIT();
20597      return;
20598    }
20599  } else {
20600    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
20601    if (dt.Is(F32) && cond.IsNotNever()) {
20602      EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20603              rn.Encode(7, 16) | rm.Encode(5, 0));
20604      return;
20605    }
20606  }
20607  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
20608}
20609
20610void Assembler::vnmls(
20611    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20612  VIXL_ASSERT(AllowAssembler());
20613  CheckIT(cond);
20614  if (IsUsingT32()) {
20615    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
20616    if (dt.Is(F64)) {
20617      EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20618                 rm.Encode(5, 0));
20619      AdvanceIT();
20620      return;
20621    }
20622  } else {
20623    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
20624    if (dt.Is(F64) && cond.IsNotNever()) {
20625      EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20626              rn.Encode(7, 16) | rm.Encode(5, 0));
20627      return;
20628    }
20629  }
20630  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
20631}
20632
20633void Assembler::vnmul(
20634    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20635  VIXL_ASSERT(AllowAssembler());
20636  CheckIT(cond);
20637  if (IsUsingT32()) {
20638    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
20639    if (dt.Is(F32)) {
20640      EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20641                 rm.Encode(5, 0));
20642      AdvanceIT();
20643      return;
20644    }
20645  } else {
20646    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
20647    if (dt.Is(F32) && cond.IsNotNever()) {
20648      EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20649              rn.Encode(7, 16) | rm.Encode(5, 0));
20650      return;
20651    }
20652  }
20653  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
20654}
20655
20656void Assembler::vnmul(
20657    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20658  VIXL_ASSERT(AllowAssembler());
20659  CheckIT(cond);
20660  if (IsUsingT32()) {
20661    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
20662    if (dt.Is(F64)) {
20663      EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20664                 rm.Encode(5, 0));
20665      AdvanceIT();
20666      return;
20667    }
20668  } else {
20669    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
20670    if (dt.Is(F64) && cond.IsNotNever()) {
20671      EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20672              rn.Encode(7, 16) | rm.Encode(5, 0));
20673      return;
20674    }
20675  }
20676  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
20677}
20678
20679void Assembler::vorn(Condition cond,
20680                     DataType dt,
20681                     DRegister rd,
20682                     DRegister rn,
20683                     const DOperand& operand) {
20684  VIXL_ASSERT(AllowAssembler());
20685  CheckIT(cond);
20686  if (operand.IsImmediate()) {
20687    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
20688    if (IsUsingT32()) {
20689      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
20690      if (encoded_dt.IsValid() && rd.Is(rn)) {
20691        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20692          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
20693                     rd.Encode(22, 12) |
20694                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20695                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20696                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20697          AdvanceIT();
20698          return;
20699        }
20700      }
20701    } else {
20702      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
20703      if (encoded_dt.IsValid() && rd.Is(rn)) {
20704        if (cond.Is(al)) {
20705          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
20706                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20707                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20708                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20709          return;
20710        }
20711      }
20712    }
20713  }
20714  if (operand.IsRegister()) {
20715    DRegister rm = operand.GetRegister();
20716    USE(dt);
20717    if (IsUsingT32()) {
20718      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
20719      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20720        EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20721                   rm.Encode(5, 0));
20722        AdvanceIT();
20723        return;
20724      }
20725    } else {
20726      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
20727      if (cond.Is(al)) {
20728        EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20729                rm.Encode(5, 0));
20730        return;
20731      }
20732    }
20733  }
20734  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
20735}
20736
20737void Assembler::vorn(Condition cond,
20738                     DataType dt,
20739                     QRegister rd,
20740                     QRegister rn,
20741                     const QOperand& operand) {
20742  VIXL_ASSERT(AllowAssembler());
20743  CheckIT(cond);
20744  if (operand.IsImmediate()) {
20745    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
20746    if (IsUsingT32()) {
20747      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
20748      if (encoded_dt.IsValid() && rd.Is(rn)) {
20749        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20750          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
20751                     rd.Encode(22, 12) |
20752                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20753                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20754                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20755          AdvanceIT();
20756          return;
20757        }
20758      }
20759    } else {
20760      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
20761      if (encoded_dt.IsValid() && rd.Is(rn)) {
20762        if (cond.Is(al)) {
20763          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
20764                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20765                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20766                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20767          return;
20768        }
20769      }
20770    }
20771  }
20772  if (operand.IsRegister()) {
20773    QRegister rm = operand.GetRegister();
20774    USE(dt);
20775    if (IsUsingT32()) {
20776      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
20777      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20778        EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20779                   rm.Encode(5, 0));
20780        AdvanceIT();
20781        return;
20782      }
20783    } else {
20784      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
20785      if (cond.Is(al)) {
20786        EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20787                rm.Encode(5, 0));
20788        return;
20789      }
20790    }
20791  }
20792  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
20793}
20794
20795void Assembler::vorr(Condition cond,
20796                     DataType dt,
20797                     DRegister rd,
20798                     DRegister rn,
20799                     const DOperand& operand) {
20800  VIXL_ASSERT(AllowAssembler());
20801  CheckIT(cond);
20802  if (operand.IsRegister()) {
20803    DRegister rm = operand.GetRegister();
20804    USE(dt);
20805    if (IsUsingT32()) {
20806      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
20807      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20808        EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20809                   rm.Encode(5, 0));
20810        AdvanceIT();
20811        return;
20812      }
20813    } else {
20814      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
20815      if (cond.Is(al)) {
20816        EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20817                rm.Encode(5, 0));
20818        return;
20819      }
20820    }
20821  }
20822  if (operand.IsImmediate()) {
20823    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
20824    if (IsUsingT32()) {
20825      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
20826      if (encoded_dt.IsValid() && rd.Is(rn)) {
20827        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20828          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
20829                     rd.Encode(22, 12) |
20830                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20831                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20832                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20833          AdvanceIT();
20834          return;
20835        }
20836      }
20837    } else {
20838      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
20839      if (encoded_dt.IsValid() && rd.Is(rn)) {
20840        if (cond.Is(al)) {
20841          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
20842                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20843                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20844                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20845          return;
20846        }
20847      }
20848    }
20849  }
20850  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
20851}
20852
20853void Assembler::vorr(Condition cond,
20854                     DataType dt,
20855                     QRegister rd,
20856                     QRegister rn,
20857                     const QOperand& operand) {
20858  VIXL_ASSERT(AllowAssembler());
20859  CheckIT(cond);
20860  if (operand.IsRegister()) {
20861    QRegister rm = operand.GetRegister();
20862    USE(dt);
20863    if (IsUsingT32()) {
20864      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
20865      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20866        EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20867                   rm.Encode(5, 0));
20868        AdvanceIT();
20869        return;
20870      }
20871    } else {
20872      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
20873      if (cond.Is(al)) {
20874        EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20875                rm.Encode(5, 0));
20876        return;
20877      }
20878    }
20879  }
20880  if (operand.IsImmediate()) {
20881    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
20882    if (IsUsingT32()) {
20883      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
20884      if (encoded_dt.IsValid() && rd.Is(rn)) {
20885        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20886          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
20887                     rd.Encode(22, 12) |
20888                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20889                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20890                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20891          AdvanceIT();
20892          return;
20893        }
20894      }
20895    } else {
20896      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
20897      if (encoded_dt.IsValid() && rd.Is(rn)) {
20898        if (cond.Is(al)) {
20899          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
20900                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20901                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20902                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20903          return;
20904        }
20905      }
20906    }
20907  }
20908  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
20909}
20910
20911void Assembler::vpadal(Condition cond,
20912                       DataType dt,
20913                       DRegister rd,
20914                       DRegister rm) {
20915  VIXL_ASSERT(AllowAssembler());
20916  CheckIT(cond);
20917  Dt_op_size_2 encoded_dt(dt);
20918  if (IsUsingT32()) {
20919    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20920    if (encoded_dt.IsValid()) {
20921      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20922        EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20923                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20924                   rd.Encode(22, 12) | rm.Encode(5, 0));
20925        AdvanceIT();
20926        return;
20927      }
20928    }
20929  } else {
20930    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
20931    if (encoded_dt.IsValid()) {
20932      if (cond.Is(al)) {
20933        EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20934                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20935                rd.Encode(22, 12) | rm.Encode(5, 0));
20936        return;
20937      }
20938    }
20939  }
20940  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
20941}
20942
20943void Assembler::vpadal(Condition cond,
20944                       DataType dt,
20945                       QRegister rd,
20946                       QRegister rm) {
20947  VIXL_ASSERT(AllowAssembler());
20948  CheckIT(cond);
20949  Dt_op_size_2 encoded_dt(dt);
20950  if (IsUsingT32()) {
20951    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
20952    if (encoded_dt.IsValid()) {
20953      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20954        EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20955                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20956                   rd.Encode(22, 12) | rm.Encode(5, 0));
20957        AdvanceIT();
20958        return;
20959      }
20960    }
20961  } else {
20962    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
20963    if (encoded_dt.IsValid()) {
20964      if (cond.Is(al)) {
20965        EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20966                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20967                rd.Encode(22, 12) | rm.Encode(5, 0));
20968        return;
20969      }
20970    }
20971  }
20972  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
20973}
20974
20975void Assembler::vpadd(
20976    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20977  VIXL_ASSERT(AllowAssembler());
20978  CheckIT(cond);
20979  Dt_size_4 encoded_dt(dt);
20980  if (IsUsingT32()) {
20981    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20982    if (dt.Is(F32)) {
20983      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20984        EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20985                   rm.Encode(5, 0));
20986        AdvanceIT();
20987        return;
20988      }
20989    }
20990    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20991    if (encoded_dt.IsValid()) {
20992      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20993        EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
20994                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20995        AdvanceIT();
20996        return;
20997      }
20998    }
20999  } else {
21000    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21001    if (dt.Is(F32)) {
21002      if (cond.Is(al)) {
21003        EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21004                rm.Encode(5, 0));
21005        return;
21006      }
21007    }
21008    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21009    if (encoded_dt.IsValid()) {
21010      if (cond.Is(al)) {
21011        EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
21012                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21013        return;
21014      }
21015    }
21016  }
21017  Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
21018}
21019
21020void Assembler::vpaddl(Condition cond,
21021                       DataType dt,
21022                       DRegister rd,
21023                       DRegister rm) {
21024  VIXL_ASSERT(AllowAssembler());
21025  CheckIT(cond);
21026  Dt_op_size_2 encoded_dt(dt);
21027  if (IsUsingT32()) {
21028    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21029    if (encoded_dt.IsValid()) {
21030      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21031        EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21032                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21033                   rd.Encode(22, 12) | rm.Encode(5, 0));
21034        AdvanceIT();
21035        return;
21036      }
21037    }
21038  } else {
21039    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21040    if (encoded_dt.IsValid()) {
21041      if (cond.Is(al)) {
21042        EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21043                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21044                rd.Encode(22, 12) | rm.Encode(5, 0));
21045        return;
21046      }
21047    }
21048  }
21049  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
21050}
21051
21052void Assembler::vpaddl(Condition cond,
21053                       DataType dt,
21054                       QRegister rd,
21055                       QRegister rm) {
21056  VIXL_ASSERT(AllowAssembler());
21057  CheckIT(cond);
21058  Dt_op_size_2 encoded_dt(dt);
21059  if (IsUsingT32()) {
21060    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21061    if (encoded_dt.IsValid()) {
21062      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21063        EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21064                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21065                   rd.Encode(22, 12) | rm.Encode(5, 0));
21066        AdvanceIT();
21067        return;
21068      }
21069    }
21070  } else {
21071    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21072    if (encoded_dt.IsValid()) {
21073      if (cond.Is(al)) {
21074        EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21075                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21076                rd.Encode(22, 12) | rm.Encode(5, 0));
21077        return;
21078      }
21079    }
21080  }
21081  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
21082}
21083
21084void Assembler::vpmax(
21085    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21086  VIXL_ASSERT(AllowAssembler());
21087  CheckIT(cond);
21088  Dt_U_size_1 encoded_dt(dt);
21089  if (IsUsingT32()) {
21090    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21091    if (dt.Is(F32)) {
21092      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21093        EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21094                   rm.Encode(5, 0));
21095        AdvanceIT();
21096        return;
21097      }
21098    }
21099    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21100    if (encoded_dt.IsValid()) {
21101      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21102        EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21103                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21104                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21105        AdvanceIT();
21106        return;
21107      }
21108    }
21109  } else {
21110    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21111    if (dt.Is(F32)) {
21112      if (cond.Is(al)) {
21113        EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21114                rm.Encode(5, 0));
21115        return;
21116      }
21117    }
21118    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21119    if (encoded_dt.IsValid()) {
21120      if (cond.Is(al)) {
21121        EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21122                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21123                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21124        return;
21125      }
21126    }
21127  }
21128  Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
21129}
21130
21131void Assembler::vpmin(
21132    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21133  VIXL_ASSERT(AllowAssembler());
21134  CheckIT(cond);
21135  Dt_U_size_1 encoded_dt(dt);
21136  if (IsUsingT32()) {
21137    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21138    if (dt.Is(F32)) {
21139      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21140        EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21141                   rm.Encode(5, 0));
21142        AdvanceIT();
21143        return;
21144      }
21145    }
21146    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21147    if (encoded_dt.IsValid()) {
21148      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21149        EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21150                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21151                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21152        AdvanceIT();
21153        return;
21154      }
21155    }
21156  } else {
21157    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21158    if (dt.Is(F32)) {
21159      if (cond.Is(al)) {
21160        EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21161                rm.Encode(5, 0));
21162        return;
21163      }
21164    }
21165    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21166    if (encoded_dt.IsValid()) {
21167      if (cond.Is(al)) {
21168        EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21169                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21170                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21171        return;
21172      }
21173    }
21174  }
21175  Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
21176}
21177
21178void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
21179  VIXL_ASSERT(AllowAssembler());
21180  CheckIT(cond);
21181  USE(dt);
21182  if (IsUsingT32()) {
21183    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
21184    if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21185      const DRegister& dreg = dreglist.GetFirstDRegister();
21186      unsigned len = dreglist.GetLength() * 2;
21187      EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
21188      AdvanceIT();
21189      return;
21190    }
21191  } else {
21192    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
21193    if (cond.IsNotNever() &&
21194        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21195      const DRegister& dreg = dreglist.GetFirstDRegister();
21196      unsigned len = dreglist.GetLength() * 2;
21197      EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
21198              (len & 0xff));
21199      return;
21200    }
21201  }
21202  Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
21203}
21204
21205void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
21206  VIXL_ASSERT(AllowAssembler());
21207  CheckIT(cond);
21208  USE(dt);
21209  if (IsUsingT32()) {
21210    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
21211    const SRegister& sreg = sreglist.GetFirstSRegister();
21212    unsigned len = sreglist.GetLength();
21213    EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
21214    AdvanceIT();
21215    return;
21216  } else {
21217    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
21218    if (cond.IsNotNever()) {
21219      const SRegister& sreg = sreglist.GetFirstSRegister();
21220      unsigned len = sreglist.GetLength();
21221      EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
21222              (len & 0xff));
21223      return;
21224    }
21225  }
21226  Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
21227}
21228
21229void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
21230  VIXL_ASSERT(AllowAssembler());
21231  CheckIT(cond);
21232  USE(dt);
21233  if (IsUsingT32()) {
21234    // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
21235    if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21236      const DRegister& dreg = dreglist.GetFirstDRegister();
21237      unsigned len = dreglist.GetLength() * 2;
21238      EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
21239      AdvanceIT();
21240      return;
21241    }
21242  } else {
21243    // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
21244    if (cond.IsNotNever() &&
21245        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21246      const DRegister& dreg = dreglist.GetFirstDRegister();
21247      unsigned len = dreglist.GetLength() * 2;
21248      EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
21249              (len & 0xff));
21250      return;
21251    }
21252  }
21253  Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
21254}
21255
21256void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
21257  VIXL_ASSERT(AllowAssembler());
21258  CheckIT(cond);
21259  USE(dt);
21260  if (IsUsingT32()) {
21261    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
21262    const SRegister& sreg = sreglist.GetFirstSRegister();
21263    unsigned len = sreglist.GetLength();
21264    EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
21265    AdvanceIT();
21266    return;
21267  } else {
21268    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
21269    if (cond.IsNotNever()) {
21270      const SRegister& sreg = sreglist.GetFirstSRegister();
21271      unsigned len = sreglist.GetLength();
21272      EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
21273              (len & 0xff));
21274      return;
21275    }
21276  }
21277  Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
21278}
21279
21280void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
21281  VIXL_ASSERT(AllowAssembler());
21282  CheckIT(cond);
21283  Dt_size_5 encoded_dt(dt);
21284  if (IsUsingT32()) {
21285    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21286    if (encoded_dt.IsValid()) {
21287      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21288        EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
21289                   rd.Encode(22, 12) | rm.Encode(5, 0));
21290        AdvanceIT();
21291        return;
21292      }
21293    }
21294  } else {
21295    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21296    if (encoded_dt.IsValid()) {
21297      if (cond.Is(al)) {
21298        EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
21299                rd.Encode(22, 12) | rm.Encode(5, 0));
21300        return;
21301      }
21302    }
21303  }
21304  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
21305}
21306
21307void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
21308  VIXL_ASSERT(AllowAssembler());
21309  CheckIT(cond);
21310  Dt_size_5 encoded_dt(dt);
21311  if (IsUsingT32()) {
21312    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21313    if (encoded_dt.IsValid()) {
21314      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21315        EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
21316                   rd.Encode(22, 12) | rm.Encode(5, 0));
21317        AdvanceIT();
21318        return;
21319      }
21320    }
21321  } else {
21322    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21323    if (encoded_dt.IsValid()) {
21324      if (cond.Is(al)) {
21325        EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
21326                rd.Encode(22, 12) | rm.Encode(5, 0));
21327        return;
21328      }
21329    }
21330  }
21331  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
21332}
21333
21334void Assembler::vqadd(
21335    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21336  VIXL_ASSERT(AllowAssembler());
21337  CheckIT(cond);
21338  Dt_U_size_3 encoded_dt(dt);
21339  if (IsUsingT32()) {
21340    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21341    if (encoded_dt.IsValid()) {
21342      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21343        EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21344                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21345                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21346        AdvanceIT();
21347        return;
21348      }
21349    }
21350  } else {
21351    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21352    if (encoded_dt.IsValid()) {
21353      if (cond.Is(al)) {
21354        EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21355                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21356                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21357        return;
21358      }
21359    }
21360  }
21361  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
21362}
21363
21364void Assembler::vqadd(
21365    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21366  VIXL_ASSERT(AllowAssembler());
21367  CheckIT(cond);
21368  Dt_U_size_3 encoded_dt(dt);
21369  if (IsUsingT32()) {
21370    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21371    if (encoded_dt.IsValid()) {
21372      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21373        EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21374                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21375                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21376        AdvanceIT();
21377        return;
21378      }
21379    }
21380  } else {
21381    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21382    if (encoded_dt.IsValid()) {
21383      if (cond.Is(al)) {
21384        EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21385                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21386                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21387        return;
21388      }
21389    }
21390  }
21391  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
21392}
21393
21394void Assembler::vqdmlal(
21395    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21396  VIXL_ASSERT(AllowAssembler());
21397  CheckIT(cond);
21398  Dt_size_13 encoded_dt(dt);
21399  if (IsUsingT32()) {
21400    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21401    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21402      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21403        EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
21404                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21405        AdvanceIT();
21406        return;
21407      }
21408    }
21409  } else {
21410    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21411    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21412      if (cond.Is(al)) {
21413        EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
21414                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21415        return;
21416      }
21417    }
21418  }
21419  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
21420}
21421
21422void Assembler::vqdmlal(Condition cond,
21423                        DataType dt,
21424                        QRegister rd,
21425                        DRegister rn,
21426                        DRegister dm,
21427                        unsigned index) {
21428  VIXL_ASSERT(AllowAssembler());
21429  CheckIT(cond);
21430  Dt_size_13 encoded_dt(dt);
21431  if (IsUsingT32()) {
21432    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
21433    if (encoded_dt.IsValid() &&
21434        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21435         (!dt.Is(S16) && (index <= 1))) &&
21436        (dt.Is(S16) || dt.Is(S32))) {
21437      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21438        uint32_t shift = 4;
21439        if (dt.Is(S16)) {
21440          shift = 3;
21441        }
21442        uint32_t mvm = dm.GetCode() | index << shift;
21443        EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
21444                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21445                   ((mvm & 0x10) << 1));
21446        AdvanceIT();
21447        return;
21448      }
21449    }
21450  } else {
21451    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
21452    if (encoded_dt.IsValid() &&
21453        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21454         (!dt.Is(S16) && (index <= 1))) &&
21455        (dt.Is(S16) || dt.Is(S32))) {
21456      if (cond.Is(al)) {
21457        uint32_t shift = 4;
21458        if (dt.Is(S16)) {
21459          shift = 3;
21460        }
21461        uint32_t mvm = dm.GetCode() | index << shift;
21462        EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
21463                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21464                ((mvm & 0x10) << 1));
21465        return;
21466      }
21467    }
21468  }
21469  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
21470}
21471
21472void Assembler::vqdmlsl(
21473    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21474  VIXL_ASSERT(AllowAssembler());
21475  CheckIT(cond);
21476  Dt_size_13 encoded_dt(dt);
21477  if (IsUsingT32()) {
21478    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21479    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21480      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21481        EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
21482                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21483        AdvanceIT();
21484        return;
21485      }
21486    }
21487  } else {
21488    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21489    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21490      if (cond.Is(al)) {
21491        EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
21492                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21493        return;
21494      }
21495    }
21496  }
21497  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
21498}
21499
21500void Assembler::vqdmlsl(Condition cond,
21501                        DataType dt,
21502                        QRegister rd,
21503                        DRegister rn,
21504                        DRegister dm,
21505                        unsigned index) {
21506  VIXL_ASSERT(AllowAssembler());
21507  CheckIT(cond);
21508  Dt_size_13 encoded_dt(dt);
21509  if (IsUsingT32()) {
21510    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
21511    if (encoded_dt.IsValid() &&
21512        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21513         (!dt.Is(S16) && (index <= 1))) &&
21514        (dt.Is(S16) || dt.Is(S32))) {
21515      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21516        uint32_t shift = 4;
21517        if (dt.Is(S16)) {
21518          shift = 3;
21519        }
21520        uint32_t mvm = dm.GetCode() | index << shift;
21521        EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
21522                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21523                   ((mvm & 0x10) << 1));
21524        AdvanceIT();
21525        return;
21526      }
21527    }
21528  } else {
21529    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
21530    if (encoded_dt.IsValid() &&
21531        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21532         (!dt.Is(S16) && (index <= 1))) &&
21533        (dt.Is(S16) || dt.Is(S32))) {
21534      if (cond.Is(al)) {
21535        uint32_t shift = 4;
21536        if (dt.Is(S16)) {
21537          shift = 3;
21538        }
21539        uint32_t mvm = dm.GetCode() | index << shift;
21540        EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
21541                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21542                ((mvm & 0x10) << 1));
21543        return;
21544      }
21545    }
21546  }
21547  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
21548}
21549
21550void Assembler::vqdmulh(
21551    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21552  VIXL_ASSERT(AllowAssembler());
21553  CheckIT(cond);
21554  Dt_size_13 encoded_dt(dt);
21555  if (IsUsingT32()) {
21556    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21557    if (encoded_dt.IsValid()) {
21558      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21559        EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
21560                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21561        AdvanceIT();
21562        return;
21563      }
21564    }
21565  } else {
21566    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21567    if (encoded_dt.IsValid()) {
21568      if (cond.Is(al)) {
21569        EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
21570                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21571        return;
21572      }
21573    }
21574  }
21575  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21576}
21577
21578void Assembler::vqdmulh(
21579    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21580  VIXL_ASSERT(AllowAssembler());
21581  CheckIT(cond);
21582  Dt_size_13 encoded_dt(dt);
21583  if (IsUsingT32()) {
21584    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21585    if (encoded_dt.IsValid()) {
21586      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21587        EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
21588                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21589        AdvanceIT();
21590        return;
21591      }
21592    }
21593  } else {
21594    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21595    if (encoded_dt.IsValid()) {
21596      if (cond.Is(al)) {
21597        EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
21598                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21599        return;
21600      }
21601    }
21602  }
21603  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21604}
21605
21606void Assembler::vqdmulh(
21607    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
21608  VIXL_ASSERT(AllowAssembler());
21609  CheckIT(cond);
21610  Dt_size_13 encoded_dt(dt);
21611  if (IsUsingT32()) {
21612    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
21613    if (encoded_dt.IsValid() &&
21614        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21615         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21616          (rm.GetLane() <= 1))) &&
21617        (dt.Is(S16) || dt.Is(S32))) {
21618      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21619        EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
21620                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21621        AdvanceIT();
21622        return;
21623      }
21624    }
21625  } else {
21626    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
21627    if (encoded_dt.IsValid() &&
21628        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21629         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21630          (rm.GetLane() <= 1))) &&
21631        (dt.Is(S16) || dt.Is(S32))) {
21632      if (cond.Is(al)) {
21633        EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
21634                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21635        return;
21636      }
21637    }
21638  }
21639  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21640}
21641
21642void Assembler::vqdmulh(
21643    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
21644  VIXL_ASSERT(AllowAssembler());
21645  CheckIT(cond);
21646  Dt_size_13 encoded_dt(dt);
21647  if (IsUsingT32()) {
21648    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
21649    if (encoded_dt.IsValid() &&
21650        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21651         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21652          (rm.GetLane() <= 1))) &&
21653        (dt.Is(S16) || dt.Is(S32))) {
21654      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21655        EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
21656                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21657        AdvanceIT();
21658        return;
21659      }
21660    }
21661  } else {
21662    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
21663    if (encoded_dt.IsValid() &&
21664        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21665         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21666          (rm.GetLane() <= 1))) &&
21667        (dt.Is(S16) || dt.Is(S32))) {
21668      if (cond.Is(al)) {
21669        EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
21670                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21671        return;
21672      }
21673    }
21674  }
21675  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21676}
21677
21678void Assembler::vqdmull(
21679    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21680  VIXL_ASSERT(AllowAssembler());
21681  CheckIT(cond);
21682  Dt_size_13 encoded_dt(dt);
21683  if (IsUsingT32()) {
21684    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21685    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21686      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21687        EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
21688                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21689        AdvanceIT();
21690        return;
21691      }
21692    }
21693  } else {
21694    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21695    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21696      if (cond.Is(al)) {
21697        EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
21698                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21699        return;
21700      }
21701    }
21702  }
21703  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
21704}
21705
21706void Assembler::vqdmull(
21707    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
21708  VIXL_ASSERT(AllowAssembler());
21709  CheckIT(cond);
21710  Dt_size_13 encoded_dt(dt);
21711  if (IsUsingT32()) {
21712    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
21713    if (encoded_dt.IsValid() &&
21714        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21715         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21716          (rm.GetLane() <= 1))) &&
21717        (dt.Is(S16) || dt.Is(S32))) {
21718      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21719        EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
21720                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21721        AdvanceIT();
21722        return;
21723      }
21724    }
21725  } else {
21726    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
21727    if (encoded_dt.IsValid() &&
21728        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21729         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21730          (rm.GetLane() <= 1))) &&
21731        (dt.Is(S16) || dt.Is(S32))) {
21732      if (cond.Is(al)) {
21733        EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
21734                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21735        return;
21736      }
21737    }
21738  }
21739  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
21740}
21741
21742void Assembler::vqmovn(Condition cond,
21743                       DataType dt,
21744                       DRegister rd,
21745                       QRegister rm) {
21746  VIXL_ASSERT(AllowAssembler());
21747  CheckIT(cond);
21748  Dt_op_size_3 encoded_dt(dt);
21749  if (IsUsingT32()) {
21750    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21751    if (encoded_dt.IsValid()) {
21752      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21753        EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21754                   ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
21755                   rd.Encode(22, 12) | rm.Encode(5, 0));
21756        AdvanceIT();
21757        return;
21758      }
21759    }
21760  } else {
21761    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21762    if (encoded_dt.IsValid()) {
21763      if (cond.Is(al)) {
21764        EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21765                ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
21766                rd.Encode(22, 12) | rm.Encode(5, 0));
21767        return;
21768      }
21769    }
21770  }
21771  Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
21772}
21773
21774void Assembler::vqmovun(Condition cond,
21775                        DataType dt,
21776                        DRegister rd,
21777                        QRegister rm) {
21778  VIXL_ASSERT(AllowAssembler());
21779  CheckIT(cond);
21780  Dt_size_14 encoded_dt(dt);
21781  if (IsUsingT32()) {
21782    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21783    if (encoded_dt.IsValid()) {
21784      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21785        EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
21786                   rd.Encode(22, 12) | rm.Encode(5, 0));
21787        AdvanceIT();
21788        return;
21789      }
21790    }
21791  } else {
21792    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21793    if (encoded_dt.IsValid()) {
21794      if (cond.Is(al)) {
21795        EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
21796                rd.Encode(22, 12) | rm.Encode(5, 0));
21797        return;
21798      }
21799    }
21800  }
21801  Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
21802}
21803
21804void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
21805  VIXL_ASSERT(AllowAssembler());
21806  CheckIT(cond);
21807  Dt_size_5 encoded_dt(dt);
21808  if (IsUsingT32()) {
21809    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21810    if (encoded_dt.IsValid()) {
21811      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21812        EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
21813                   rd.Encode(22, 12) | rm.Encode(5, 0));
21814        AdvanceIT();
21815        return;
21816      }
21817    }
21818  } else {
21819    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21820    if (encoded_dt.IsValid()) {
21821      if (cond.Is(al)) {
21822        EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
21823                rd.Encode(22, 12) | rm.Encode(5, 0));
21824        return;
21825      }
21826    }
21827  }
21828  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
21829}
21830
21831void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
21832  VIXL_ASSERT(AllowAssembler());
21833  CheckIT(cond);
21834  Dt_size_5 encoded_dt(dt);
21835  if (IsUsingT32()) {
21836    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21837    if (encoded_dt.IsValid()) {
21838      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21839        EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
21840                   rd.Encode(22, 12) | rm.Encode(5, 0));
21841        AdvanceIT();
21842        return;
21843      }
21844    }
21845  } else {
21846    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21847    if (encoded_dt.IsValid()) {
21848      if (cond.Is(al)) {
21849        EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
21850                rd.Encode(22, 12) | rm.Encode(5, 0));
21851        return;
21852      }
21853    }
21854  }
21855  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
21856}
21857
21858void Assembler::vqrdmulh(
21859    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21860  VIXL_ASSERT(AllowAssembler());
21861  CheckIT(cond);
21862  Dt_size_13 encoded_dt(dt);
21863  if (IsUsingT32()) {
21864    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21865    if (encoded_dt.IsValid()) {
21866      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21867        EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
21868                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21869        AdvanceIT();
21870        return;
21871      }
21872    }
21873  } else {
21874    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21875    if (encoded_dt.IsValid()) {
21876      if (cond.Is(al)) {
21877        EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
21878                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21879        return;
21880      }
21881    }
21882  }
21883  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21884}
21885
21886void Assembler::vqrdmulh(
21887    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21888  VIXL_ASSERT(AllowAssembler());
21889  CheckIT(cond);
21890  Dt_size_13 encoded_dt(dt);
21891  if (IsUsingT32()) {
21892    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21893    if (encoded_dt.IsValid()) {
21894      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21895        EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
21896                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21897        AdvanceIT();
21898        return;
21899      }
21900    }
21901  } else {
21902    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21903    if (encoded_dt.IsValid()) {
21904      if (cond.Is(al)) {
21905        EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
21906                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21907        return;
21908      }
21909    }
21910  }
21911  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21912}
21913
21914void Assembler::vqrdmulh(
21915    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
21916  VIXL_ASSERT(AllowAssembler());
21917  CheckIT(cond);
21918  Dt_size_13 encoded_dt(dt);
21919  if (IsUsingT32()) {
21920    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
21921    if (encoded_dt.IsValid() &&
21922        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21923         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21924          (rm.GetLane() <= 1))) &&
21925        (dt.Is(S16) || dt.Is(S32))) {
21926      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21927        EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
21928                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21929        AdvanceIT();
21930        return;
21931      }
21932    }
21933  } else {
21934    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
21935    if (encoded_dt.IsValid() &&
21936        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21937         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21938          (rm.GetLane() <= 1))) &&
21939        (dt.Is(S16) || dt.Is(S32))) {
21940      if (cond.Is(al)) {
21941        EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
21942                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21943        return;
21944      }
21945    }
21946  }
21947  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21948}
21949
21950void Assembler::vqrdmulh(
21951    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
21952  VIXL_ASSERT(AllowAssembler());
21953  CheckIT(cond);
21954  Dt_size_13 encoded_dt(dt);
21955  if (IsUsingT32()) {
21956    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
21957    if (encoded_dt.IsValid() &&
21958        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21959         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21960          (rm.GetLane() <= 1))) &&
21961        (dt.Is(S16) || dt.Is(S32))) {
21962      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21963        EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
21964                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21965        AdvanceIT();
21966        return;
21967      }
21968    }
21969  } else {
21970    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
21971    if (encoded_dt.IsValid() &&
21972        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21973         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21974          (rm.GetLane() <= 1))) &&
21975        (dt.Is(S16) || dt.Is(S32))) {
21976      if (cond.Is(al)) {
21977        EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
21978                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21979        return;
21980      }
21981    }
21982  }
21983  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21984}
21985
21986void Assembler::vqrshl(
21987    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
21988  VIXL_ASSERT(AllowAssembler());
21989  CheckIT(cond);
21990  Dt_U_size_3 encoded_dt(dt);
21991  if (IsUsingT32()) {
21992    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
21993    if (encoded_dt.IsValid()) {
21994      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21995        EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21996                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21997                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
21998        AdvanceIT();
21999        return;
22000      }
22001    }
22002  } else {
22003    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
22004    if (encoded_dt.IsValid()) {
22005      if (cond.Is(al)) {
22006        EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22007                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22008                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22009        return;
22010      }
22011    }
22012  }
22013  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
22014}
22015
22016void Assembler::vqrshl(
22017    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
22018  VIXL_ASSERT(AllowAssembler());
22019  CheckIT(cond);
22020  Dt_U_size_3 encoded_dt(dt);
22021  if (IsUsingT32()) {
22022    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
22023    if (encoded_dt.IsValid()) {
22024      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22025        EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22026                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22027                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22028        AdvanceIT();
22029        return;
22030      }
22031    }
22032  } else {
22033    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
22034    if (encoded_dt.IsValid()) {
22035      if (cond.Is(al)) {
22036        EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22037                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22038                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22039        return;
22040      }
22041    }
22042  }
22043  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
22044}
22045
22046void Assembler::vqrshrn(Condition cond,
22047                        DataType dt,
22048                        DRegister rd,
22049                        QRegister rm,
22050                        const QOperand& operand) {
22051  VIXL_ASSERT(AllowAssembler());
22052  CheckIT(cond);
22053  if (operand.IsImmediate()) {
22054    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22055      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22056      Dt_op_size_3 encoded_dt(dt);
22057      Dt_imm6_1 encoded_dt_2(dt);
22058      if (IsUsingT32()) {
22059        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22060        if (encoded_dt.IsValid() && (imm == 0)) {
22061          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22062            EmitT32_32(0xffb20280U |
22063                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22064                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22065                       rd.Encode(22, 12) | rm.Encode(5, 0));
22066            AdvanceIT();
22067            return;
22068          }
22069        }
22070        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22071        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22072          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22073            uint32_t imm6 = dt.GetSize() / 2 - imm;
22074            EmitT32_32(0xef800950U |
22075                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
22076                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22077                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22078            AdvanceIT();
22079            return;
22080          }
22081        }
22082      } else {
22083        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22084        if (encoded_dt.IsValid() && (imm == 0)) {
22085          if (cond.Is(al)) {
22086            EmitA32(0xf3b20280U |
22087                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22088                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22089                    rd.Encode(22, 12) | rm.Encode(5, 0));
22090            return;
22091          }
22092        }
22093        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22094        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22095          if (cond.Is(al)) {
22096            uint32_t imm6 = dt.GetSize() / 2 - imm;
22097            EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
22098                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22099                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22100            return;
22101          }
22102        }
22103      }
22104    }
22105  }
22106  Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
22107}
22108
22109void Assembler::vqrshrun(Condition cond,
22110                         DataType dt,
22111                         DRegister rd,
22112                         QRegister rm,
22113                         const QOperand& operand) {
22114  VIXL_ASSERT(AllowAssembler());
22115  CheckIT(cond);
22116  if (operand.IsImmediate()) {
22117    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22118      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22119      Dt_imm6_2 encoded_dt(dt);
22120      Dt_size_14 encoded_dt_2(dt);
22121      if (IsUsingT32()) {
22122        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22123        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22124          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22125            uint32_t imm6 = dt.GetSize() / 2 - imm;
22126            EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
22127                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22128                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22129            AdvanceIT();
22130            return;
22131          }
22132        }
22133        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22134        if (encoded_dt_2.IsValid() && (imm == 0)) {
22135          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22136            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22137                       rd.Encode(22, 12) | rm.Encode(5, 0));
22138            AdvanceIT();
22139            return;
22140          }
22141        }
22142      } else {
22143        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22144        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22145          if (cond.Is(al)) {
22146            uint32_t imm6 = dt.GetSize() / 2 - imm;
22147            EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
22148                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22149                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22150            return;
22151          }
22152        }
22153        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22154        if (encoded_dt_2.IsValid() && (imm == 0)) {
22155          if (cond.Is(al)) {
22156            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22157                    rd.Encode(22, 12) | rm.Encode(5, 0));
22158            return;
22159          }
22160        }
22161      }
22162    }
22163  }
22164  Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
22165}
22166
22167void Assembler::vqshl(Condition cond,
22168                      DataType dt,
22169                      DRegister rd,
22170                      DRegister rm,
22171                      const DOperand& operand) {
22172  VIXL_ASSERT(AllowAssembler());
22173  CheckIT(cond);
22174  if (operand.IsRegister()) {
22175    DRegister rn = operand.GetRegister();
22176    Dt_U_size_3 encoded_dt(dt);
22177    if (IsUsingT32()) {
22178      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
22179      if (encoded_dt.IsValid()) {
22180        if (cond.Is(al) || AllowStronglyDiscouraged()) {
22181          EmitT32_32(0xef000410U |
22182                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22183                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22184                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22185          AdvanceIT();
22186          return;
22187        }
22188      }
22189    } else {
22190      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
22191      if (encoded_dt.IsValid()) {
22192        if (cond.Is(al)) {
22193          EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22194                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22195                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22196          return;
22197        }
22198      }
22199    }
22200  }
22201  if (operand.IsImmediate()) {
22202    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22203      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22204      Dt_L_imm6_1 encoded_dt(dt);
22205      if (IsUsingT32()) {
22206        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
22207        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22208          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22209            uint32_t imm6 = imm;
22210            EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
22211                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22212                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22213                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22214            AdvanceIT();
22215            return;
22216          }
22217        }
22218      } else {
22219        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
22220        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22221          if (cond.Is(al)) {
22222            uint32_t imm6 = imm;
22223            EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
22224                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22225                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22226                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22227            return;
22228          }
22229        }
22230      }
22231    }
22232  }
22233  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
22234}
22235
22236void Assembler::vqshl(Condition cond,
22237                      DataType dt,
22238                      QRegister rd,
22239                      QRegister rm,
22240                      const QOperand& operand) {
22241  VIXL_ASSERT(AllowAssembler());
22242  CheckIT(cond);
22243  if (operand.IsRegister()) {
22244    QRegister rn = operand.GetRegister();
22245    Dt_U_size_3 encoded_dt(dt);
22246    if (IsUsingT32()) {
22247      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
22248      if (encoded_dt.IsValid()) {
22249        if (cond.Is(al) || AllowStronglyDiscouraged()) {
22250          EmitT32_32(0xef000450U |
22251                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22252                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22253                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22254          AdvanceIT();
22255          return;
22256        }
22257      }
22258    } else {
22259      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
22260      if (encoded_dt.IsValid()) {
22261        if (cond.Is(al)) {
22262          EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22263                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22264                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22265          return;
22266        }
22267      }
22268    }
22269  }
22270  if (operand.IsImmediate()) {
22271    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22272      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22273      Dt_L_imm6_1 encoded_dt(dt);
22274      if (IsUsingT32()) {
22275        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
22276        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22277          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22278            uint32_t imm6 = imm;
22279            EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
22280                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22281                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22282                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22283            AdvanceIT();
22284            return;
22285          }
22286        }
22287      } else {
22288        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
22289        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22290          if (cond.Is(al)) {
22291            uint32_t imm6 = imm;
22292            EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
22293                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22294                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22295                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22296            return;
22297          }
22298        }
22299      }
22300    }
22301  }
22302  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
22303}
22304
22305void Assembler::vqshlu(Condition cond,
22306                       DataType dt,
22307                       DRegister rd,
22308                       DRegister rm,
22309                       const DOperand& operand) {
22310  VIXL_ASSERT(AllowAssembler());
22311  CheckIT(cond);
22312  if (operand.IsImmediate()) {
22313    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22314      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22315      Dt_L_imm6_2 encoded_dt(dt);
22316      if (IsUsingT32()) {
22317        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
22318        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22319          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22320            uint32_t imm6 = imm;
22321            EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
22322                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22323                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22324                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22325            AdvanceIT();
22326            return;
22327          }
22328        }
22329      } else {
22330        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
22331        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22332          if (cond.Is(al)) {
22333            uint32_t imm6 = imm;
22334            EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
22335                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22336                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22337                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22338            return;
22339          }
22340        }
22341      }
22342    }
22343  }
22344  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
22345}
22346
22347void Assembler::vqshlu(Condition cond,
22348                       DataType dt,
22349                       QRegister rd,
22350                       QRegister rm,
22351                       const QOperand& operand) {
22352  VIXL_ASSERT(AllowAssembler());
22353  CheckIT(cond);
22354  if (operand.IsImmediate()) {
22355    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22356      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22357      Dt_L_imm6_2 encoded_dt(dt);
22358      if (IsUsingT32()) {
22359        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
22360        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22361          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22362            uint32_t imm6 = imm;
22363            EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
22364                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22365                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22366                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22367            AdvanceIT();
22368            return;
22369          }
22370        }
22371      } else {
22372        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
22373        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22374          if (cond.Is(al)) {
22375            uint32_t imm6 = imm;
22376            EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
22377                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22378                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22379                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22380            return;
22381          }
22382        }
22383      }
22384    }
22385  }
22386  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
22387}
22388
22389void Assembler::vqshrn(Condition cond,
22390                       DataType dt,
22391                       DRegister rd,
22392                       QRegister rm,
22393                       const QOperand& operand) {
22394  VIXL_ASSERT(AllowAssembler());
22395  CheckIT(cond);
22396  if (operand.IsImmediate()) {
22397    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22398      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22399      Dt_op_size_3 encoded_dt(dt);
22400      Dt_imm6_1 encoded_dt_2(dt);
22401      if (IsUsingT32()) {
22402        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22403        if (encoded_dt.IsValid() && (imm == 0)) {
22404          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22405            EmitT32_32(0xffb20280U |
22406                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22407                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22408                       rd.Encode(22, 12) | rm.Encode(5, 0));
22409            AdvanceIT();
22410            return;
22411          }
22412        }
22413        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22414        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22415          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22416            uint32_t imm6 = dt.GetSize() / 2 - imm;
22417            EmitT32_32(0xef800910U |
22418                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
22419                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22420                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22421            AdvanceIT();
22422            return;
22423          }
22424        }
22425      } else {
22426        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22427        if (encoded_dt.IsValid() && (imm == 0)) {
22428          if (cond.Is(al)) {
22429            EmitA32(0xf3b20280U |
22430                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22431                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22432                    rd.Encode(22, 12) | rm.Encode(5, 0));
22433            return;
22434          }
22435        }
22436        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22437        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22438          if (cond.Is(al)) {
22439            uint32_t imm6 = dt.GetSize() / 2 - imm;
22440            EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
22441                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22442                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22443            return;
22444          }
22445        }
22446      }
22447    }
22448  }
22449  Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
22450}
22451
22452void Assembler::vqshrun(Condition cond,
22453                        DataType dt,
22454                        DRegister rd,
22455                        QRegister rm,
22456                        const QOperand& operand) {
22457  VIXL_ASSERT(AllowAssembler());
22458  CheckIT(cond);
22459  if (operand.IsImmediate()) {
22460    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22461      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22462      Dt_imm6_2 encoded_dt(dt);
22463      Dt_size_14 encoded_dt_2(dt);
22464      if (IsUsingT32()) {
22465        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22466        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22467          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22468            uint32_t imm6 = dt.GetSize() / 2 - imm;
22469            EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
22470                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22471                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22472            AdvanceIT();
22473            return;
22474          }
22475        }
22476        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22477        if (encoded_dt_2.IsValid() && (imm == 0)) {
22478          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22479            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22480                       rd.Encode(22, 12) | rm.Encode(5, 0));
22481            AdvanceIT();
22482            return;
22483          }
22484        }
22485      } else {
22486        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22487        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22488          if (cond.Is(al)) {
22489            uint32_t imm6 = dt.GetSize() / 2 - imm;
22490            EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
22491                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22492                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22493            return;
22494          }
22495        }
22496        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22497        if (encoded_dt_2.IsValid() && (imm == 0)) {
22498          if (cond.Is(al)) {
22499            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22500                    rd.Encode(22, 12) | rm.Encode(5, 0));
22501            return;
22502          }
22503        }
22504      }
22505    }
22506  }
22507  Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
22508}
22509
22510void Assembler::vqsub(
22511    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22512  VIXL_ASSERT(AllowAssembler());
22513  CheckIT(cond);
22514  Dt_U_size_3 encoded_dt(dt);
22515  if (IsUsingT32()) {
22516    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22517    if (encoded_dt.IsValid()) {
22518      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22519        EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22520                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22521                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22522        AdvanceIT();
22523        return;
22524      }
22525    }
22526  } else {
22527    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22528    if (encoded_dt.IsValid()) {
22529      if (cond.Is(al)) {
22530        EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22531                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22532                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22533        return;
22534      }
22535    }
22536  }
22537  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
22538}
22539
22540void Assembler::vqsub(
22541    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22542  VIXL_ASSERT(AllowAssembler());
22543  CheckIT(cond);
22544  Dt_U_size_3 encoded_dt(dt);
22545  if (IsUsingT32()) {
22546    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22547    if (encoded_dt.IsValid()) {
22548      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22549        EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22550                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22551                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22552        AdvanceIT();
22553        return;
22554      }
22555    }
22556  } else {
22557    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22558    if (encoded_dt.IsValid()) {
22559      if (cond.Is(al)) {
22560        EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22561                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22562                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22563        return;
22564      }
22565    }
22566  }
22567  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
22568}
22569
22570void Assembler::vraddhn(
22571    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
22572  VIXL_ASSERT(AllowAssembler());
22573  CheckIT(cond);
22574  Dt_size_3 encoded_dt(dt);
22575  if (IsUsingT32()) {
22576    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
22577    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
22578      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22579        EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
22580                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22581        AdvanceIT();
22582        return;
22583      }
22584    }
22585  } else {
22586    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
22587    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
22588      if (cond.Is(al)) {
22589        EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
22590                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22591        return;
22592      }
22593    }
22594  }
22595  Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
22596}
22597
22598void Assembler::vrecpe(Condition cond,
22599                       DataType dt,
22600                       DRegister rd,
22601                       DRegister rm) {
22602  VIXL_ASSERT(AllowAssembler());
22603  CheckIT(cond);
22604  Dt_F_size_4 encoded_dt(dt);
22605  if (IsUsingT32()) {
22606    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22607    if (encoded_dt.IsValid()) {
22608      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22609        EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22610                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22611                   rd.Encode(22, 12) | rm.Encode(5, 0));
22612        AdvanceIT();
22613        return;
22614      }
22615    }
22616  } else {
22617    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22618    if (encoded_dt.IsValid()) {
22619      if (cond.Is(al)) {
22620        EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22621                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22622                rd.Encode(22, 12) | rm.Encode(5, 0));
22623        return;
22624      }
22625    }
22626  }
22627  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
22628}
22629
22630void Assembler::vrecpe(Condition cond,
22631                       DataType dt,
22632                       QRegister rd,
22633                       QRegister rm) {
22634  VIXL_ASSERT(AllowAssembler());
22635  CheckIT(cond);
22636  Dt_F_size_4 encoded_dt(dt);
22637  if (IsUsingT32()) {
22638    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22639    if (encoded_dt.IsValid()) {
22640      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22641        EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22642                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22643                   rd.Encode(22, 12) | rm.Encode(5, 0));
22644        AdvanceIT();
22645        return;
22646      }
22647    }
22648  } else {
22649    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22650    if (encoded_dt.IsValid()) {
22651      if (cond.Is(al)) {
22652        EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22653                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22654                rd.Encode(22, 12) | rm.Encode(5, 0));
22655        return;
22656      }
22657    }
22658  }
22659  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
22660}
22661
22662void Assembler::vrecps(
22663    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22664  VIXL_ASSERT(AllowAssembler());
22665  CheckIT(cond);
22666  if (IsUsingT32()) {
22667    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22668    if (dt.Is(F32)) {
22669      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22670        EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22671                   rm.Encode(5, 0));
22672        AdvanceIT();
22673        return;
22674      }
22675    }
22676  } else {
22677    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22678    if (dt.Is(F32)) {
22679      if (cond.Is(al)) {
22680        EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22681                rm.Encode(5, 0));
22682        return;
22683      }
22684    }
22685  }
22686  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
22687}
22688
22689void Assembler::vrecps(
22690    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22691  VIXL_ASSERT(AllowAssembler());
22692  CheckIT(cond);
22693  if (IsUsingT32()) {
22694    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
22695    if (dt.Is(F32)) {
22696      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22697        EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22698                   rm.Encode(5, 0));
22699        AdvanceIT();
22700        return;
22701      }
22702    }
22703  } else {
22704    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
22705    if (dt.Is(F32)) {
22706      if (cond.Is(al)) {
22707        EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22708                rm.Encode(5, 0));
22709        return;
22710      }
22711    }
22712  }
22713  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
22714}
22715
22716void Assembler::vrev16(Condition cond,
22717                       DataType dt,
22718                       DRegister rd,
22719                       DRegister rm) {
22720  VIXL_ASSERT(AllowAssembler());
22721  CheckIT(cond);
22722  Dt_size_1 encoded_dt(dt);
22723  if (IsUsingT32()) {
22724    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22725    if (encoded_dt.IsValid()) {
22726      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22727        EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
22728                   rd.Encode(22, 12) | rm.Encode(5, 0));
22729        AdvanceIT();
22730        return;
22731      }
22732    }
22733  } else {
22734    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22735    if (encoded_dt.IsValid()) {
22736      if (cond.Is(al)) {
22737        EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
22738                rd.Encode(22, 12) | rm.Encode(5, 0));
22739        return;
22740      }
22741    }
22742  }
22743  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
22744}
22745
22746void Assembler::vrev16(Condition cond,
22747                       DataType dt,
22748                       QRegister rd,
22749                       QRegister rm) {
22750  VIXL_ASSERT(AllowAssembler());
22751  CheckIT(cond);
22752  Dt_size_1 encoded_dt(dt);
22753  if (IsUsingT32()) {
22754    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22755    if (encoded_dt.IsValid()) {
22756      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22757        EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
22758                   rd.Encode(22, 12) | rm.Encode(5, 0));
22759        AdvanceIT();
22760        return;
22761      }
22762    }
22763  } else {
22764    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22765    if (encoded_dt.IsValid()) {
22766      if (cond.Is(al)) {
22767        EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
22768                rd.Encode(22, 12) | rm.Encode(5, 0));
22769        return;
22770      }
22771    }
22772  }
22773  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
22774}
22775
22776void Assembler::vrev32(Condition cond,
22777                       DataType dt,
22778                       DRegister rd,
22779                       DRegister rm) {
22780  VIXL_ASSERT(AllowAssembler());
22781  CheckIT(cond);
22782  Dt_size_15 encoded_dt(dt);
22783  if (IsUsingT32()) {
22784    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22785    if (encoded_dt.IsValid()) {
22786      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22787        EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
22788                   rd.Encode(22, 12) | rm.Encode(5, 0));
22789        AdvanceIT();
22790        return;
22791      }
22792    }
22793  } else {
22794    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22795    if (encoded_dt.IsValid()) {
22796      if (cond.Is(al)) {
22797        EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
22798                rd.Encode(22, 12) | rm.Encode(5, 0));
22799        return;
22800      }
22801    }
22802  }
22803  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
22804}
22805
22806void Assembler::vrev32(Condition cond,
22807                       DataType dt,
22808                       QRegister rd,
22809                       QRegister rm) {
22810  VIXL_ASSERT(AllowAssembler());
22811  CheckIT(cond);
22812  Dt_size_15 encoded_dt(dt);
22813  if (IsUsingT32()) {
22814    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22815    if (encoded_dt.IsValid()) {
22816      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22817        EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
22818                   rd.Encode(22, 12) | rm.Encode(5, 0));
22819        AdvanceIT();
22820        return;
22821      }
22822    }
22823  } else {
22824    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22825    if (encoded_dt.IsValid()) {
22826      if (cond.Is(al)) {
22827        EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
22828                rd.Encode(22, 12) | rm.Encode(5, 0));
22829        return;
22830      }
22831    }
22832  }
22833  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
22834}
22835
22836void Assembler::vrev64(Condition cond,
22837                       DataType dt,
22838                       DRegister rd,
22839                       DRegister rm) {
22840  VIXL_ASSERT(AllowAssembler());
22841  CheckIT(cond);
22842  Dt_size_7 encoded_dt(dt);
22843  if (IsUsingT32()) {
22844    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22845    if (encoded_dt.IsValid()) {
22846      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22847        EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
22848                   rd.Encode(22, 12) | rm.Encode(5, 0));
22849        AdvanceIT();
22850        return;
22851      }
22852    }
22853  } else {
22854    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22855    if (encoded_dt.IsValid()) {
22856      if (cond.Is(al)) {
22857        EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
22858                rd.Encode(22, 12) | rm.Encode(5, 0));
22859        return;
22860      }
22861    }
22862  }
22863  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
22864}
22865
22866void Assembler::vrev64(Condition cond,
22867                       DataType dt,
22868                       QRegister rd,
22869                       QRegister rm) {
22870  VIXL_ASSERT(AllowAssembler());
22871  CheckIT(cond);
22872  Dt_size_7 encoded_dt(dt);
22873  if (IsUsingT32()) {
22874    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22875    if (encoded_dt.IsValid()) {
22876      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22877        EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
22878                   rd.Encode(22, 12) | rm.Encode(5, 0));
22879        AdvanceIT();
22880        return;
22881      }
22882    }
22883  } else {
22884    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22885    if (encoded_dt.IsValid()) {
22886      if (cond.Is(al)) {
22887        EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
22888                rd.Encode(22, 12) | rm.Encode(5, 0));
22889        return;
22890      }
22891    }
22892  }
22893  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
22894}
22895
22896void Assembler::vrhadd(
22897    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22898  VIXL_ASSERT(AllowAssembler());
22899  CheckIT(cond);
22900  Dt_U_size_1 encoded_dt(dt);
22901  if (IsUsingT32()) {
22902    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22903    if (encoded_dt.IsValid()) {
22904      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22905        EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22906                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22907                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22908        AdvanceIT();
22909        return;
22910      }
22911    }
22912  } else {
22913    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22914    if (encoded_dt.IsValid()) {
22915      if (cond.Is(al)) {
22916        EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22917                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22918                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22919        return;
22920      }
22921    }
22922  }
22923  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
22924}
22925
22926void Assembler::vrhadd(
22927    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22928  VIXL_ASSERT(AllowAssembler());
22929  CheckIT(cond);
22930  Dt_U_size_1 encoded_dt(dt);
22931  if (IsUsingT32()) {
22932    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22933    if (encoded_dt.IsValid()) {
22934      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22935        EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22936                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22937                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22938        AdvanceIT();
22939        return;
22940      }
22941    }
22942  } else {
22943    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22944    if (encoded_dt.IsValid()) {
22945      if (cond.Is(al)) {
22946        EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22947                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22948                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22949        return;
22950      }
22951    }
22952  }
22953  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
22954}
22955
22956void Assembler::vrinta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
22957  VIXL_ASSERT(AllowAssembler());
22958  CheckIT(al);
22959  if (IsUsingT32()) {
22960    // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; T1
22961    if (dt1.Is(F32) && dt2.Is(F32)) {
22962      EmitT32_32(0xffba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
22963      AdvanceIT();
22964      return;
22965    }
22966    // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; T1
22967    if (dt1.Is(F64) && dt2.Is(F64)) {
22968      EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22969      AdvanceIT();
22970      return;
22971    }
22972  } else {
22973    // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; A1
22974    if (dt1.Is(F32) && dt2.Is(F32)) {
22975      EmitA32(0xf3ba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
22976      return;
22977    }
22978    // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; A1
22979    if (dt1.Is(F64) && dt2.Is(F64)) {
22980      EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22981      return;
22982    }
22983  }
22984  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
22985}
22986
22987void Assembler::vrinta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
22988  VIXL_ASSERT(AllowAssembler());
22989  CheckIT(al);
22990  if (IsUsingT32()) {
22991    // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; T1
22992    if (dt1.Is(F32) && dt2.Is(F32)) {
22993      EmitT32_32(0xffba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
22994      AdvanceIT();
22995      return;
22996    }
22997  } else {
22998    // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; A1
22999    if (dt1.Is(F32) && dt2.Is(F32)) {
23000      EmitA32(0xf3ba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
23001      return;
23002    }
23003  }
23004  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
23005}
23006
23007void Assembler::vrinta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23008  VIXL_ASSERT(AllowAssembler());
23009  CheckIT(al);
23010  if (IsUsingT32()) {
23011    // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; T1
23012    if (dt1.Is(F32) && dt2.Is(F32)) {
23013      EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23014      AdvanceIT();
23015      return;
23016    }
23017  } else {
23018    // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; A1
23019    if (dt1.Is(F32) && dt2.Is(F32)) {
23020      EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23021      return;
23022    }
23023  }
23024  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
23025}
23026
23027void Assembler::vrintm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23028  VIXL_ASSERT(AllowAssembler());
23029  CheckIT(al);
23030  if (IsUsingT32()) {
23031    // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; T1
23032    if (dt1.Is(F32) && dt2.Is(F32)) {
23033      EmitT32_32(0xffba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
23034      AdvanceIT();
23035      return;
23036    }
23037    // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; T1
23038    if (dt1.Is(F64) && dt2.Is(F64)) {
23039      EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23040      AdvanceIT();
23041      return;
23042    }
23043  } else {
23044    // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; A1
23045    if (dt1.Is(F32) && dt2.Is(F32)) {
23046      EmitA32(0xf3ba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
23047      return;
23048    }
23049    // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; A1
23050    if (dt1.Is(F64) && dt2.Is(F64)) {
23051      EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23052      return;
23053    }
23054  }
23055  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23056}
23057
23058void Assembler::vrintm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23059  VIXL_ASSERT(AllowAssembler());
23060  CheckIT(al);
23061  if (IsUsingT32()) {
23062    // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; T1
23063    if (dt1.Is(F32) && dt2.Is(F32)) {
23064      EmitT32_32(0xffba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23065      AdvanceIT();
23066      return;
23067    }
23068  } else {
23069    // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; A1
23070    if (dt1.Is(F32) && dt2.Is(F32)) {
23071      EmitA32(0xf3ba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23072      return;
23073    }
23074  }
23075  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23076}
23077
23078void Assembler::vrintm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23079  VIXL_ASSERT(AllowAssembler());
23080  CheckIT(al);
23081  if (IsUsingT32()) {
23082    // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; T1
23083    if (dt1.Is(F32) && dt2.Is(F32)) {
23084      EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23085      AdvanceIT();
23086      return;
23087    }
23088  } else {
23089    // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; A1
23090    if (dt1.Is(F32) && dt2.Is(F32)) {
23091      EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23092      return;
23093    }
23094  }
23095  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23096}
23097
23098void Assembler::vrintn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23099  VIXL_ASSERT(AllowAssembler());
23100  CheckIT(al);
23101  if (IsUsingT32()) {
23102    // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; T1
23103    if (dt1.Is(F32) && dt2.Is(F32)) {
23104      EmitT32_32(0xffba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
23105      AdvanceIT();
23106      return;
23107    }
23108    // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; T1
23109    if (dt1.Is(F64) && dt2.Is(F64)) {
23110      EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23111      AdvanceIT();
23112      return;
23113    }
23114  } else {
23115    // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; A1
23116    if (dt1.Is(F32) && dt2.Is(F32)) {
23117      EmitA32(0xf3ba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
23118      return;
23119    }
23120    // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; A1
23121    if (dt1.Is(F64) && dt2.Is(F64)) {
23122      EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23123      return;
23124    }
23125  }
23126  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23127}
23128
23129void Assembler::vrintn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23130  VIXL_ASSERT(AllowAssembler());
23131  CheckIT(al);
23132  if (IsUsingT32()) {
23133    // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; T1
23134    if (dt1.Is(F32) && dt2.Is(F32)) {
23135      EmitT32_32(0xffba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
23136      AdvanceIT();
23137      return;
23138    }
23139  } else {
23140    // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; A1
23141    if (dt1.Is(F32) && dt2.Is(F32)) {
23142      EmitA32(0xf3ba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
23143      return;
23144    }
23145  }
23146  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23147}
23148
23149void Assembler::vrintn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23150  VIXL_ASSERT(AllowAssembler());
23151  CheckIT(al);
23152  if (IsUsingT32()) {
23153    // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; T1
23154    if (dt1.Is(F32) && dt2.Is(F32)) {
23155      EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23156      AdvanceIT();
23157      return;
23158    }
23159  } else {
23160    // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; A1
23161    if (dt1.Is(F32) && dt2.Is(F32)) {
23162      EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23163      return;
23164    }
23165  }
23166  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23167}
23168
23169void Assembler::vrintp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23170  VIXL_ASSERT(AllowAssembler());
23171  CheckIT(al);
23172  if (IsUsingT32()) {
23173    // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; T1
23174    if (dt1.Is(F32) && dt2.Is(F32)) {
23175      EmitT32_32(0xffba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
23176      AdvanceIT();
23177      return;
23178    }
23179    // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; T1
23180    if (dt1.Is(F64) && dt2.Is(F64)) {
23181      EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23182      AdvanceIT();
23183      return;
23184    }
23185  } else {
23186    // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; A1
23187    if (dt1.Is(F32) && dt2.Is(F32)) {
23188      EmitA32(0xf3ba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
23189      return;
23190    }
23191    // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; A1
23192    if (dt1.Is(F64) && dt2.Is(F64)) {
23193      EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23194      return;
23195    }
23196  }
23197  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23198}
23199
23200void Assembler::vrintp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23201  VIXL_ASSERT(AllowAssembler());
23202  CheckIT(al);
23203  if (IsUsingT32()) {
23204    // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; T1
23205    if (dt1.Is(F32) && dt2.Is(F32)) {
23206      EmitT32_32(0xffba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23207      AdvanceIT();
23208      return;
23209    }
23210  } else {
23211    // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; A1
23212    if (dt1.Is(F32) && dt2.Is(F32)) {
23213      EmitA32(0xf3ba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23214      return;
23215    }
23216  }
23217  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23218}
23219
23220void Assembler::vrintp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23221  VIXL_ASSERT(AllowAssembler());
23222  CheckIT(al);
23223  if (IsUsingT32()) {
23224    // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; T1
23225    if (dt1.Is(F32) && dt2.Is(F32)) {
23226      EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23227      AdvanceIT();
23228      return;
23229    }
23230  } else {
23231    // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; A1
23232    if (dt1.Is(F32) && dt2.Is(F32)) {
23233      EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23234      return;
23235    }
23236  }
23237  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23238}
23239
23240void Assembler::vrintr(
23241    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23242  VIXL_ASSERT(AllowAssembler());
23243  CheckIT(cond);
23244  if (IsUsingT32()) {
23245    // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23246    if (dt1.Is(F32) && dt2.Is(F32)) {
23247      EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23248      AdvanceIT();
23249      return;
23250    }
23251  } else {
23252    // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23253    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23254      EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23255              rm.Encode(5, 0));
23256      return;
23257    }
23258  }
23259  Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
23260}
23261
23262void Assembler::vrintr(
23263    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23264  VIXL_ASSERT(AllowAssembler());
23265  CheckIT(cond);
23266  if (IsUsingT32()) {
23267    // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23268    if (dt1.Is(F64) && dt2.Is(F64)) {
23269      EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23270      AdvanceIT();
23271      return;
23272    }
23273  } else {
23274    // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23275    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23276      EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23277              rm.Encode(5, 0));
23278      return;
23279    }
23280  }
23281  Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
23282}
23283
23284void Assembler::vrintx(
23285    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23286  VIXL_ASSERT(AllowAssembler());
23287  CheckIT(cond);
23288  if (IsUsingT32()) {
23289    // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; T1
23290    if (dt1.Is(F32) && dt2.Is(F32)) {
23291      EmitT32_32(0xffba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
23292      AdvanceIT();
23293      return;
23294    }
23295    // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23296    if (dt1.Is(F64) && dt2.Is(F64)) {
23297      EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23298      AdvanceIT();
23299      return;
23300    }
23301  } else {
23302    // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; A1
23303    if (dt1.Is(F32) && dt2.Is(F32)) {
23304      EmitA32(0xf3ba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
23305      return;
23306    }
23307    // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23308    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23309      EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23310              rm.Encode(5, 0));
23311      return;
23312    }
23313  }
23314  Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
23315}
23316
23317void Assembler::vrintx(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23318  VIXL_ASSERT(AllowAssembler());
23319  CheckIT(al);
23320  if (IsUsingT32()) {
23321    // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; T1
23322    if (dt1.Is(F32) && dt2.Is(F32)) {
23323      EmitT32_32(0xffba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23324      AdvanceIT();
23325      return;
23326    }
23327  } else {
23328    // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; A1
23329    if (dt1.Is(F32) && dt2.Is(F32)) {
23330      EmitA32(0xf3ba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23331      return;
23332    }
23333  }
23334  Delegate(kVrintx, &Assembler::vrintx, dt1, dt2, rd, rm);
23335}
23336
23337void Assembler::vrintx(
23338    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23339  VIXL_ASSERT(AllowAssembler());
23340  CheckIT(cond);
23341  if (IsUsingT32()) {
23342    // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23343    if (dt1.Is(F32) && dt2.Is(F32)) {
23344      EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23345      AdvanceIT();
23346      return;
23347    }
23348  } else {
23349    // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23350    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23351      EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23352              rm.Encode(5, 0));
23353      return;
23354    }
23355  }
23356  Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
23357}
23358
23359void Assembler::vrintz(
23360    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23361  VIXL_ASSERT(AllowAssembler());
23362  CheckIT(cond);
23363  if (IsUsingT32()) {
23364    // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; T1
23365    if (dt1.Is(F32) && dt2.Is(F32)) {
23366      EmitT32_32(0xffba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
23367      AdvanceIT();
23368      return;
23369    }
23370    // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23371    if (dt1.Is(F64) && dt2.Is(F64)) {
23372      EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23373      AdvanceIT();
23374      return;
23375    }
23376  } else {
23377    // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; A1
23378    if (dt1.Is(F32) && dt2.Is(F32)) {
23379      EmitA32(0xf3ba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
23380      return;
23381    }
23382    // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23383    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23384      EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23385              rm.Encode(5, 0));
23386      return;
23387    }
23388  }
23389  Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
23390}
23391
23392void Assembler::vrintz(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23393  VIXL_ASSERT(AllowAssembler());
23394  CheckIT(al);
23395  if (IsUsingT32()) {
23396    // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; T1
23397    if (dt1.Is(F32) && dt2.Is(F32)) {
23398      EmitT32_32(0xffba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23399      AdvanceIT();
23400      return;
23401    }
23402  } else {
23403    // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; A1
23404    if (dt1.Is(F32) && dt2.Is(F32)) {
23405      EmitA32(0xf3ba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23406      return;
23407    }
23408  }
23409  Delegate(kVrintz, &Assembler::vrintz, dt1, dt2, rd, rm);
23410}
23411
23412void Assembler::vrintz(
23413    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23414  VIXL_ASSERT(AllowAssembler());
23415  CheckIT(cond);
23416  if (IsUsingT32()) {
23417    // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23418    if (dt1.Is(F32) && dt2.Is(F32)) {
23419      EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23420      AdvanceIT();
23421      return;
23422    }
23423  } else {
23424    // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23425    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23426      EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23427              rm.Encode(5, 0));
23428      return;
23429    }
23430  }
23431  Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
23432}
23433
23434void Assembler::vrshl(
23435    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
23436  VIXL_ASSERT(AllowAssembler());
23437  CheckIT(cond);
23438  Dt_U_size_3 encoded_dt(dt);
23439  if (IsUsingT32()) {
23440    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23441    if (encoded_dt.IsValid()) {
23442      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23443        EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23444                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23445                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23446        AdvanceIT();
23447        return;
23448      }
23449    }
23450  } else {
23451    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23452    if (encoded_dt.IsValid()) {
23453      if (cond.Is(al)) {
23454        EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23455                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23456                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23457        return;
23458      }
23459    }
23460  }
23461  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
23462}
23463
23464void Assembler::vrshl(
23465    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
23466  VIXL_ASSERT(AllowAssembler());
23467  CheckIT(cond);
23468  Dt_U_size_3 encoded_dt(dt);
23469  if (IsUsingT32()) {
23470    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23471    if (encoded_dt.IsValid()) {
23472      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23473        EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23474                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23475                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23476        AdvanceIT();
23477        return;
23478      }
23479    }
23480  } else {
23481    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23482    if (encoded_dt.IsValid()) {
23483      if (cond.Is(al)) {
23484        EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23485                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23486                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23487        return;
23488      }
23489    }
23490  }
23491  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
23492}
23493
23494void Assembler::vrshr(Condition cond,
23495                      DataType dt,
23496                      DRegister rd,
23497                      DRegister rm,
23498                      const DOperand& operand) {
23499  VIXL_ASSERT(AllowAssembler());
23500  CheckIT(cond);
23501  if (operand.IsImmediate()) {
23502    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23503      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23504      Dt_L_imm6_1 encoded_dt(dt);
23505      if (IsUsingT32()) {
23506        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23507        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23508          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23509            uint32_t imm6 = dt.GetSize() - imm;
23510            EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
23511                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23512                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23513                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23514            AdvanceIT();
23515            return;
23516          }
23517        }
23518        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
23519        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23520          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23521            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23522                       rm.Encode(5, 0));
23523            AdvanceIT();
23524            return;
23525          }
23526        }
23527      } else {
23528        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23529        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23530          if (cond.Is(al)) {
23531            uint32_t imm6 = dt.GetSize() - imm;
23532            EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
23533                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23534                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23535                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23536            return;
23537          }
23538        }
23539        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
23540        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23541          if (cond.Is(al)) {
23542            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23543                    rm.Encode(5, 0));
23544            return;
23545          }
23546        }
23547      }
23548    }
23549  }
23550  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
23551}
23552
23553void Assembler::vrshr(Condition cond,
23554                      DataType dt,
23555                      QRegister rd,
23556                      QRegister rm,
23557                      const QOperand& operand) {
23558  VIXL_ASSERT(AllowAssembler());
23559  CheckIT(cond);
23560  if (operand.IsImmediate()) {
23561    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23562      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23563      Dt_L_imm6_1 encoded_dt(dt);
23564      if (IsUsingT32()) {
23565        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23566        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23567          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23568            uint32_t imm6 = dt.GetSize() - imm;
23569            EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
23570                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23571                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23572                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23573            AdvanceIT();
23574            return;
23575          }
23576        }
23577        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
23578        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23579          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23580            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23581                       rm.Encode(5, 0));
23582            AdvanceIT();
23583            return;
23584          }
23585        }
23586      } else {
23587        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23588        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23589          if (cond.Is(al)) {
23590            uint32_t imm6 = dt.GetSize() - imm;
23591            EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
23592                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23593                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23594                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23595            return;
23596          }
23597        }
23598        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
23599        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23600          if (cond.Is(al)) {
23601            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23602                    rm.Encode(5, 0));
23603            return;
23604          }
23605        }
23606      }
23607    }
23608  }
23609  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
23610}
23611
23612void Assembler::vrshrn(Condition cond,
23613                       DataType dt,
23614                       DRegister rd,
23615                       QRegister rm,
23616                       const QOperand& operand) {
23617  VIXL_ASSERT(AllowAssembler());
23618  CheckIT(cond);
23619  if (operand.IsImmediate()) {
23620    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23621      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23622      Dt_imm6_3 encoded_dt(dt);
23623      Dt_size_3 encoded_dt_2(dt);
23624      if (IsUsingT32()) {
23625        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
23626        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23627          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23628            uint32_t imm6 = dt.GetSize() / 2 - imm;
23629            EmitT32_32(0xef800850U |
23630                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23631                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23632            AdvanceIT();
23633            return;
23634          }
23635        }
23636        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23637        if (encoded_dt_2.IsValid() && (imm == 0)) {
23638          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23639            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
23640                       rd.Encode(22, 12) | rm.Encode(5, 0));
23641            AdvanceIT();
23642            return;
23643          }
23644        }
23645      } else {
23646        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
23647        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23648          if (cond.Is(al)) {
23649            uint32_t imm6 = dt.GetSize() / 2 - imm;
23650            EmitA32(0xf2800850U |
23651                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23652                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23653            return;
23654          }
23655        }
23656        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23657        if (encoded_dt_2.IsValid() && (imm == 0)) {
23658          if (cond.Is(al)) {
23659            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
23660                    rd.Encode(22, 12) | rm.Encode(5, 0));
23661            return;
23662          }
23663        }
23664      }
23665    }
23666  }
23667  Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
23668}
23669
23670void Assembler::vrsqrte(Condition cond,
23671                        DataType dt,
23672                        DRegister rd,
23673                        DRegister rm) {
23674  VIXL_ASSERT(AllowAssembler());
23675  CheckIT(cond);
23676  Dt_F_size_4 encoded_dt(dt);
23677  if (IsUsingT32()) {
23678    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23679    if (encoded_dt.IsValid()) {
23680      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23681        EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23682                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23683                   rd.Encode(22, 12) | rm.Encode(5, 0));
23684        AdvanceIT();
23685        return;
23686      }
23687    }
23688  } else {
23689    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23690    if (encoded_dt.IsValid()) {
23691      if (cond.Is(al)) {
23692        EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23693                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23694                rd.Encode(22, 12) | rm.Encode(5, 0));
23695        return;
23696      }
23697    }
23698  }
23699  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
23700}
23701
23702void Assembler::vrsqrte(Condition cond,
23703                        DataType dt,
23704                        QRegister rd,
23705                        QRegister rm) {
23706  VIXL_ASSERT(AllowAssembler());
23707  CheckIT(cond);
23708  Dt_F_size_4 encoded_dt(dt);
23709  if (IsUsingT32()) {
23710    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23711    if (encoded_dt.IsValid()) {
23712      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23713        EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23714                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23715                   rd.Encode(22, 12) | rm.Encode(5, 0));
23716        AdvanceIT();
23717        return;
23718      }
23719    }
23720  } else {
23721    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23722    if (encoded_dt.IsValid()) {
23723      if (cond.Is(al)) {
23724        EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23725                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23726                rd.Encode(22, 12) | rm.Encode(5, 0));
23727        return;
23728      }
23729    }
23730  }
23731  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
23732}
23733
23734void Assembler::vrsqrts(
23735    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23736  VIXL_ASSERT(AllowAssembler());
23737  CheckIT(cond);
23738  if (IsUsingT32()) {
23739    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23740    if (dt.Is(F32)) {
23741      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23742        EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23743                   rm.Encode(5, 0));
23744        AdvanceIT();
23745        return;
23746      }
23747    }
23748  } else {
23749    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23750    if (dt.Is(F32)) {
23751      if (cond.Is(al)) {
23752        EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23753                rm.Encode(5, 0));
23754        return;
23755      }
23756    }
23757  }
23758  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
23759}
23760
23761void Assembler::vrsqrts(
23762    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23763  VIXL_ASSERT(AllowAssembler());
23764  CheckIT(cond);
23765  if (IsUsingT32()) {
23766    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23767    if (dt.Is(F32)) {
23768      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23769        EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23770                   rm.Encode(5, 0));
23771        AdvanceIT();
23772        return;
23773      }
23774    }
23775  } else {
23776    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23777    if (dt.Is(F32)) {
23778      if (cond.Is(al)) {
23779        EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23780                rm.Encode(5, 0));
23781        return;
23782      }
23783    }
23784  }
23785  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
23786}
23787
23788void Assembler::vrsra(Condition cond,
23789                      DataType dt,
23790                      DRegister rd,
23791                      DRegister rm,
23792                      const DOperand& operand) {
23793  VIXL_ASSERT(AllowAssembler());
23794  CheckIT(cond);
23795  if (operand.IsImmediate()) {
23796    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23797      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23798      Dt_L_imm6_1 encoded_dt(dt);
23799      if (IsUsingT32()) {
23800        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23801        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23802          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23803            uint32_t imm6 = dt.GetSize() - imm;
23804            EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
23805                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23806                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23807                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23808            AdvanceIT();
23809            return;
23810          }
23811        }
23812      } else {
23813        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23814        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23815          if (cond.Is(al)) {
23816            uint32_t imm6 = dt.GetSize() - imm;
23817            EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
23818                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23819                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23820                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23821            return;
23822          }
23823        }
23824      }
23825    }
23826  }
23827  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
23828}
23829
23830void Assembler::vrsra(Condition cond,
23831                      DataType dt,
23832                      QRegister rd,
23833                      QRegister rm,
23834                      const QOperand& operand) {
23835  VIXL_ASSERT(AllowAssembler());
23836  CheckIT(cond);
23837  if (operand.IsImmediate()) {
23838    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23839      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23840      Dt_L_imm6_1 encoded_dt(dt);
23841      if (IsUsingT32()) {
23842        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23843        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23844          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23845            uint32_t imm6 = dt.GetSize() - imm;
23846            EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
23847                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23848                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23849                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23850            AdvanceIT();
23851            return;
23852          }
23853        }
23854      } else {
23855        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23856        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23857          if (cond.Is(al)) {
23858            uint32_t imm6 = dt.GetSize() - imm;
23859            EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
23860                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23861                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23862                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23863            return;
23864          }
23865        }
23866      }
23867    }
23868  }
23869  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
23870}
23871
23872void Assembler::vrsubhn(
23873    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
23874  VIXL_ASSERT(AllowAssembler());
23875  CheckIT(cond);
23876  Dt_size_3 encoded_dt(dt);
23877  if (IsUsingT32()) {
23878    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23879    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23880      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23881        EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
23882                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23883        AdvanceIT();
23884        return;
23885      }
23886    }
23887  } else {
23888    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23889    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23890      if (cond.Is(al)) {
23891        EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
23892                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23893        return;
23894      }
23895    }
23896  }
23897  Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
23898}
23899
23900void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23901  VIXL_ASSERT(AllowAssembler());
23902  CheckIT(al);
23903  if (IsUsingT32()) {
23904    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
23905    if (OutsideITBlock() && dt.Is(F64)) {
23906      EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23907                 rm.Encode(5, 0));
23908      AdvanceIT();
23909      return;
23910    }
23911  } else {
23912    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
23913    if (dt.Is(F64)) {
23914      EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23915              rm.Encode(5, 0));
23916      return;
23917    }
23918  }
23919  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
23920}
23921
23922void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
23923  VIXL_ASSERT(AllowAssembler());
23924  CheckIT(al);
23925  if (IsUsingT32()) {
23926    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
23927    if (OutsideITBlock() && dt.Is(F32)) {
23928      EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23929                 rm.Encode(5, 0));
23930      AdvanceIT();
23931      return;
23932    }
23933  } else {
23934    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
23935    if (dt.Is(F32)) {
23936      EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23937              rm.Encode(5, 0));
23938      return;
23939    }
23940  }
23941  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
23942}
23943
23944void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23945  VIXL_ASSERT(AllowAssembler());
23946  CheckIT(al);
23947  if (IsUsingT32()) {
23948    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
23949    if (OutsideITBlock() && dt.Is(F64)) {
23950      EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23951                 rm.Encode(5, 0));
23952      AdvanceIT();
23953      return;
23954    }
23955  } else {
23956    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
23957    if (dt.Is(F64)) {
23958      EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23959              rm.Encode(5, 0));
23960      return;
23961    }
23962  }
23963  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
23964}
23965
23966void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
23967  VIXL_ASSERT(AllowAssembler());
23968  CheckIT(al);
23969  if (IsUsingT32()) {
23970    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
23971    if (OutsideITBlock() && dt.Is(F32)) {
23972      EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23973                 rm.Encode(5, 0));
23974      AdvanceIT();
23975      return;
23976    }
23977  } else {
23978    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
23979    if (dt.Is(F32)) {
23980      EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23981              rm.Encode(5, 0));
23982      return;
23983    }
23984  }
23985  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
23986}
23987
23988void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23989  VIXL_ASSERT(AllowAssembler());
23990  CheckIT(al);
23991  if (IsUsingT32()) {
23992    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
23993    if (OutsideITBlock() && dt.Is(F64)) {
23994      EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23995                 rm.Encode(5, 0));
23996      AdvanceIT();
23997      return;
23998    }
23999  } else {
24000    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
24001    if (dt.Is(F64)) {
24002      EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24003              rm.Encode(5, 0));
24004      return;
24005    }
24006  }
24007  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
24008}
24009
24010void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
24011  VIXL_ASSERT(AllowAssembler());
24012  CheckIT(al);
24013  if (IsUsingT32()) {
24014    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
24015    if (OutsideITBlock() && dt.Is(F32)) {
24016      EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24017                 rm.Encode(5, 0));
24018      AdvanceIT();
24019      return;
24020    }
24021  } else {
24022    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
24023    if (dt.Is(F32)) {
24024      EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24025              rm.Encode(5, 0));
24026      return;
24027    }
24028  }
24029  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
24030}
24031
24032void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
24033  VIXL_ASSERT(AllowAssembler());
24034  CheckIT(al);
24035  if (IsUsingT32()) {
24036    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
24037    if (OutsideITBlock() && dt.Is(F64)) {
24038      EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24039                 rm.Encode(5, 0));
24040      AdvanceIT();
24041      return;
24042    }
24043  } else {
24044    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
24045    if (dt.Is(F64)) {
24046      EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24047              rm.Encode(5, 0));
24048      return;
24049    }
24050  }
24051  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
24052}
24053
24054void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
24055  VIXL_ASSERT(AllowAssembler());
24056  CheckIT(al);
24057  if (IsUsingT32()) {
24058    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
24059    if (OutsideITBlock() && dt.Is(F32)) {
24060      EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24061                 rm.Encode(5, 0));
24062      AdvanceIT();
24063      return;
24064    }
24065  } else {
24066    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
24067    if (dt.Is(F32)) {
24068      EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24069              rm.Encode(5, 0));
24070      return;
24071    }
24072  }
24073  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
24074}
24075
24076void Assembler::vshl(Condition cond,
24077                     DataType dt,
24078                     DRegister rd,
24079                     DRegister rm,
24080                     const DOperand& operand) {
24081  VIXL_ASSERT(AllowAssembler());
24082  CheckIT(cond);
24083  if (operand.IsImmediate()) {
24084    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24085      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24086      Dt_L_imm6_3 encoded_dt(dt);
24087      if (IsUsingT32()) {
24088        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
24089        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24090          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24091            uint32_t imm6 = imm;
24092            EmitT32_32(0xef800510U |
24093                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24094                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24095                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24096            AdvanceIT();
24097            return;
24098          }
24099        }
24100      } else {
24101        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
24102        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24103          if (cond.Is(al)) {
24104            uint32_t imm6 = imm;
24105            EmitA32(0xf2800510U |
24106                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24107                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24108                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24109            return;
24110          }
24111        }
24112      }
24113    }
24114  }
24115  if (operand.IsRegister()) {
24116    DRegister rn = operand.GetRegister();
24117    Dt_U_size_3 encoded_dt(dt);
24118    if (IsUsingT32()) {
24119      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24120      if (encoded_dt.IsValid()) {
24121        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24122          EmitT32_32(0xef000400U |
24123                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24124                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24125                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24126          AdvanceIT();
24127          return;
24128        }
24129      }
24130    } else {
24131      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24132      if (encoded_dt.IsValid()) {
24133        if (cond.Is(al)) {
24134          EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24135                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24136                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24137          return;
24138        }
24139      }
24140    }
24141  }
24142  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
24143}
24144
24145void Assembler::vshl(Condition cond,
24146                     DataType dt,
24147                     QRegister rd,
24148                     QRegister rm,
24149                     const QOperand& operand) {
24150  VIXL_ASSERT(AllowAssembler());
24151  CheckIT(cond);
24152  if (operand.IsImmediate()) {
24153    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24154      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24155      Dt_L_imm6_3 encoded_dt(dt);
24156      if (IsUsingT32()) {
24157        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
24158        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24159          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24160            uint32_t imm6 = imm;
24161            EmitT32_32(0xef800550U |
24162                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24163                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24164                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24165            AdvanceIT();
24166            return;
24167          }
24168        }
24169      } else {
24170        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
24171        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24172          if (cond.Is(al)) {
24173            uint32_t imm6 = imm;
24174            EmitA32(0xf2800550U |
24175                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24176                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24177                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24178            return;
24179          }
24180        }
24181      }
24182    }
24183  }
24184  if (operand.IsRegister()) {
24185    QRegister rn = operand.GetRegister();
24186    Dt_U_size_3 encoded_dt(dt);
24187    if (IsUsingT32()) {
24188      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24189      if (encoded_dt.IsValid()) {
24190        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24191          EmitT32_32(0xef000440U |
24192                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24193                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24194                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24195          AdvanceIT();
24196          return;
24197        }
24198      }
24199    } else {
24200      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24201      if (encoded_dt.IsValid()) {
24202        if (cond.Is(al)) {
24203          EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24204                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24205                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24206          return;
24207        }
24208      }
24209    }
24210  }
24211  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
24212}
24213
24214void Assembler::vshll(Condition cond,
24215                      DataType dt,
24216                      QRegister rd,
24217                      DRegister rm,
24218                      const DOperand& operand) {
24219  VIXL_ASSERT(AllowAssembler());
24220  CheckIT(cond);
24221  if (operand.IsImmediate()) {
24222    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24223      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24224      Dt_imm6_4 encoded_dt(dt);
24225      Dt_size_16 encoded_dt_2(dt);
24226      if (IsUsingT32()) {
24227        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
24228        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
24229          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24230            uint32_t imm6 = dt.GetSize() + imm;
24231            EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
24232                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24233                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24234            AdvanceIT();
24235            return;
24236          }
24237        }
24238        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
24239        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
24240          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24241            EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
24242                       rd.Encode(22, 12) | rm.Encode(5, 0));
24243            AdvanceIT();
24244            return;
24245          }
24246        }
24247      } else {
24248        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
24249        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
24250          if (cond.Is(al)) {
24251            uint32_t imm6 = dt.GetSize() + imm;
24252            EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
24253                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24254                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24255            return;
24256          }
24257        }
24258        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
24259        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
24260          if (cond.Is(al)) {
24261            EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
24262                    rd.Encode(22, 12) | rm.Encode(5, 0));
24263            return;
24264          }
24265        }
24266      }
24267    }
24268  }
24269  Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
24270}
24271
24272void Assembler::vshr(Condition cond,
24273                     DataType dt,
24274                     DRegister rd,
24275                     DRegister rm,
24276                     const DOperand& operand) {
24277  VIXL_ASSERT(AllowAssembler());
24278  CheckIT(cond);
24279  if (operand.IsImmediate()) {
24280    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24281      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24282      Dt_L_imm6_1 encoded_dt(dt);
24283      if (IsUsingT32()) {
24284        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24285        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24286          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24287            uint32_t imm6 = dt.GetSize() - imm;
24288            EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
24289                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24290                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24291                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24292            AdvanceIT();
24293            return;
24294          }
24295        }
24296        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24297        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24298          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24299            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24300                       rm.Encode(5, 0));
24301            AdvanceIT();
24302            return;
24303          }
24304        }
24305      } else {
24306        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24307        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24308          if (cond.Is(al)) {
24309            uint32_t imm6 = dt.GetSize() - imm;
24310            EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
24311                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24312                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24313                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24314            return;
24315          }
24316        }
24317        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24318        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24319          if (cond.Is(al)) {
24320            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24321                    rm.Encode(5, 0));
24322            return;
24323          }
24324        }
24325      }
24326    }
24327  }
24328  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
24329}
24330
24331void Assembler::vshr(Condition cond,
24332                     DataType dt,
24333                     QRegister rd,
24334                     QRegister rm,
24335                     const QOperand& operand) {
24336  VIXL_ASSERT(AllowAssembler());
24337  CheckIT(cond);
24338  if (operand.IsImmediate()) {
24339    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24340      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24341      Dt_L_imm6_1 encoded_dt(dt);
24342      if (IsUsingT32()) {
24343        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24344        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24345          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24346            uint32_t imm6 = dt.GetSize() - imm;
24347            EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
24348                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24349                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24350                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24351            AdvanceIT();
24352            return;
24353          }
24354        }
24355        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24356        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24357          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24358            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24359                       rm.Encode(5, 0));
24360            AdvanceIT();
24361            return;
24362          }
24363        }
24364      } else {
24365        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24366        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24367          if (cond.Is(al)) {
24368            uint32_t imm6 = dt.GetSize() - imm;
24369            EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
24370                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24371                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24372                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24373            return;
24374          }
24375        }
24376        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24377        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24378          if (cond.Is(al)) {
24379            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24380                    rm.Encode(5, 0));
24381            return;
24382          }
24383        }
24384      }
24385    }
24386  }
24387  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
24388}
24389
24390void Assembler::vshrn(Condition cond,
24391                      DataType dt,
24392                      DRegister rd,
24393                      QRegister rm,
24394                      const QOperand& operand) {
24395  VIXL_ASSERT(AllowAssembler());
24396  CheckIT(cond);
24397  if (operand.IsImmediate()) {
24398    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24399      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24400      Dt_imm6_3 encoded_dt(dt);
24401      Dt_size_3 encoded_dt_2(dt);
24402      if (IsUsingT32()) {
24403        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24404        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24405          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24406            uint32_t imm6 = dt.GetSize() / 2 - imm;
24407            EmitT32_32(0xef800810U |
24408                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24409                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24410            AdvanceIT();
24411            return;
24412          }
24413        }
24414        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24415        if (encoded_dt_2.IsValid() && (imm == 0)) {
24416          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24417            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24418                       rd.Encode(22, 12) | rm.Encode(5, 0));
24419            AdvanceIT();
24420            return;
24421          }
24422        }
24423      } else {
24424        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24425        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24426          if (cond.Is(al)) {
24427            uint32_t imm6 = dt.GetSize() / 2 - imm;
24428            EmitA32(0xf2800810U |
24429                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24430                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24431            return;
24432          }
24433        }
24434        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24435        if (encoded_dt_2.IsValid() && (imm == 0)) {
24436          if (cond.Is(al)) {
24437            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24438                    rd.Encode(22, 12) | rm.Encode(5, 0));
24439            return;
24440          }
24441        }
24442      }
24443    }
24444  }
24445  Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
24446}
24447
24448void Assembler::vsli(Condition cond,
24449                     DataType dt,
24450                     DRegister rd,
24451                     DRegister rm,
24452                     const DOperand& operand) {
24453  VIXL_ASSERT(AllowAssembler());
24454  CheckIT(cond);
24455  if (operand.IsImmediate()) {
24456    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24457      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24458      Dt_L_imm6_4 encoded_dt(dt);
24459      if (IsUsingT32()) {
24460        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
24461        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24462          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24463            uint32_t imm6 = imm;
24464            EmitT32_32(0xff800510U |
24465                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24466                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24467                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24468            AdvanceIT();
24469            return;
24470          }
24471        }
24472      } else {
24473        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
24474        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24475          if (cond.Is(al)) {
24476            uint32_t imm6 = imm;
24477            EmitA32(0xf3800510U |
24478                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24479                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24480                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24481            return;
24482          }
24483        }
24484      }
24485    }
24486  }
24487  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
24488}
24489
24490void Assembler::vsli(Condition cond,
24491                     DataType dt,
24492                     QRegister rd,
24493                     QRegister rm,
24494                     const QOperand& operand) {
24495  VIXL_ASSERT(AllowAssembler());
24496  CheckIT(cond);
24497  if (operand.IsImmediate()) {
24498    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24499      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24500      Dt_L_imm6_4 encoded_dt(dt);
24501      if (IsUsingT32()) {
24502        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
24503        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24504          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24505            uint32_t imm6 = imm;
24506            EmitT32_32(0xff800550U |
24507                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24508                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24509                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24510            AdvanceIT();
24511            return;
24512          }
24513        }
24514      } else {
24515        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
24516        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24517          if (cond.Is(al)) {
24518            uint32_t imm6 = imm;
24519            EmitA32(0xf3800550U |
24520                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24521                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24522                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24523            return;
24524          }
24525        }
24526      }
24527    }
24528  }
24529  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
24530}
24531
24532void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
24533  VIXL_ASSERT(AllowAssembler());
24534  CheckIT(cond);
24535  if (IsUsingT32()) {
24536    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24537    if (dt.Is(F32)) {
24538      EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24539      AdvanceIT();
24540      return;
24541    }
24542  } else {
24543    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24544    if (dt.Is(F32) && cond.IsNotNever()) {
24545      EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24546              rm.Encode(5, 0));
24547      return;
24548    }
24549  }
24550  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
24551}
24552
24553void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
24554  VIXL_ASSERT(AllowAssembler());
24555  CheckIT(cond);
24556  if (IsUsingT32()) {
24557    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24558    if (dt.Is(F64)) {
24559      EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24560      AdvanceIT();
24561      return;
24562    }
24563  } else {
24564    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24565    if (dt.Is(F64) && cond.IsNotNever()) {
24566      EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24567              rm.Encode(5, 0));
24568      return;
24569    }
24570  }
24571  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
24572}
24573
24574void Assembler::vsra(Condition cond,
24575                     DataType dt,
24576                     DRegister rd,
24577                     DRegister rm,
24578                     const DOperand& operand) {
24579  VIXL_ASSERT(AllowAssembler());
24580  CheckIT(cond);
24581  if (operand.IsImmediate()) {
24582    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24583      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24584      Dt_L_imm6_1 encoded_dt(dt);
24585      if (IsUsingT32()) {
24586        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24587        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24588          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24589            uint32_t imm6 = dt.GetSize() - imm;
24590            EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
24591                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24592                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24593                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24594            AdvanceIT();
24595            return;
24596          }
24597        }
24598      } else {
24599        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24600        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24601          if (cond.Is(al)) {
24602            uint32_t imm6 = dt.GetSize() - imm;
24603            EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
24604                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24605                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24606                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24607            return;
24608          }
24609        }
24610      }
24611    }
24612  }
24613  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
24614}
24615
24616void Assembler::vsra(Condition cond,
24617                     DataType dt,
24618                     QRegister rd,
24619                     QRegister rm,
24620                     const QOperand& operand) {
24621  VIXL_ASSERT(AllowAssembler());
24622  CheckIT(cond);
24623  if (operand.IsImmediate()) {
24624    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24625      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24626      Dt_L_imm6_1 encoded_dt(dt);
24627      if (IsUsingT32()) {
24628        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24629        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24630          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24631            uint32_t imm6 = dt.GetSize() - imm;
24632            EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
24633                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24634                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24635                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24636            AdvanceIT();
24637            return;
24638          }
24639        }
24640      } else {
24641        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24642        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24643          if (cond.Is(al)) {
24644            uint32_t imm6 = dt.GetSize() - imm;
24645            EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
24646                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24647                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24648                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24649            return;
24650          }
24651        }
24652      }
24653    }
24654  }
24655  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
24656}
24657
24658void Assembler::vsri(Condition cond,
24659                     DataType dt,
24660                     DRegister rd,
24661                     DRegister rm,
24662                     const DOperand& operand) {
24663  VIXL_ASSERT(AllowAssembler());
24664  CheckIT(cond);
24665  if (operand.IsImmediate()) {
24666    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24667      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24668      Dt_L_imm6_4 encoded_dt(dt);
24669      if (IsUsingT32()) {
24670        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
24671        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24672          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24673            uint32_t imm6 = dt.GetSize() - imm;
24674            EmitT32_32(0xff800410U |
24675                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24676                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24677                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24678            AdvanceIT();
24679            return;
24680          }
24681        }
24682      } else {
24683        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
24684        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24685          if (cond.Is(al)) {
24686            uint32_t imm6 = dt.GetSize() - imm;
24687            EmitA32(0xf3800410U |
24688                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24689                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24690                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24691            return;
24692          }
24693        }
24694      }
24695    }
24696  }
24697  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
24698}
24699
24700void Assembler::vsri(Condition cond,
24701                     DataType dt,
24702                     QRegister rd,
24703                     QRegister rm,
24704                     const QOperand& operand) {
24705  VIXL_ASSERT(AllowAssembler());
24706  CheckIT(cond);
24707  if (operand.IsImmediate()) {
24708    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24709      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24710      Dt_L_imm6_4 encoded_dt(dt);
24711      if (IsUsingT32()) {
24712        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
24713        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24714          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24715            uint32_t imm6 = dt.GetSize() - imm;
24716            EmitT32_32(0xff800450U |
24717                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24718                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24719                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24720            AdvanceIT();
24721            return;
24722          }
24723        }
24724      } else {
24725        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
24726        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24727          if (cond.Is(al)) {
24728            uint32_t imm6 = dt.GetSize() - imm;
24729            EmitA32(0xf3800450U |
24730                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24731                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24732                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24733            return;
24734          }
24735        }
24736      }
24737    }
24738  }
24739  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
24740}
24741
24742void Assembler::vst1(Condition cond,
24743                     DataType dt,
24744                     const NeonRegisterList& nreglist,
24745                     const AlignedMemOperand& operand) {
24746  VIXL_ASSERT(AllowAssembler());
24747  CheckIT(cond);
24748  if (operand.IsImmediateZero()) {
24749    Register rn = operand.GetBaseRegister();
24750    Alignment align = operand.GetAlignment();
24751    Dt_size_6 encoded_dt(dt);
24752    Dt_size_7 encoded_dt_2(dt);
24753    Align_align_5 encoded_align_1(align, nreglist);
24754    Align_index_align_1 encoded_align_2(align, nreglist, dt);
24755    if (IsUsingT32()) {
24756      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
24757      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24758          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24759          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
24760          ((!rn.IsPC()) || AllowUnpredictable())) {
24761        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24762          const DRegister& first = nreglist.GetFirstDRegister();
24763          uint32_t len_encoding;
24764          switch (nreglist.GetLength()) {
24765            default:
24766              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24767            case 1:
24768              len_encoding = 0x7;
24769              break;
24770            case 2:
24771              len_encoding = 0xa;
24772              break;
24773            case 3:
24774              len_encoding = 0x6;
24775              break;
24776            case 4:
24777              len_encoding = 0x2;
24778              break;
24779          }
24780          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
24781                     (encoded_align_1.GetEncodingValue() << 4) |
24782                     first.Encode(22, 12) | (len_encoding << 8) |
24783                     (rn.GetCode() << 16));
24784          AdvanceIT();
24785          return;
24786        }
24787      }
24788      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
24789      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24790          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24791          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
24792          ((!rn.IsPC()) || AllowUnpredictable())) {
24793        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24794          const DRegister& first = nreglist.GetFirstDRegister();
24795          uint32_t len_encoding;
24796          switch (nreglist.GetLength()) {
24797            default:
24798              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24799            case 1:
24800              len_encoding = 0x7;
24801              break;
24802            case 2:
24803              len_encoding = 0xa;
24804              break;
24805            case 3:
24806              len_encoding = 0x6;
24807              break;
24808            case 4:
24809              len_encoding = 0x2;
24810              break;
24811          }
24812          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
24813                     (encoded_align_1.GetEncodingValue() << 4) |
24814                     first.Encode(22, 12) | (len_encoding << 8) |
24815                     (rn.GetCode() << 16));
24816          AdvanceIT();
24817          return;
24818        }
24819      }
24820      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
24821      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24822          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
24823          encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24824        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24825          const DRegister& first = nreglist.GetFirstDRegister();
24826          EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
24827                     (encoded_align_2.GetEncodingValue() << 4) |
24828                     first.Encode(22, 12) | (rn.GetCode() << 16));
24829          AdvanceIT();
24830          return;
24831        }
24832      }
24833      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
24834      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24835          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
24836          encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24837        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24838          const DRegister& first = nreglist.GetFirstDRegister();
24839          EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
24840                     (encoded_align_2.GetEncodingValue() << 4) |
24841                     first.Encode(22, 12) | (rn.GetCode() << 16));
24842          AdvanceIT();
24843          return;
24844        }
24845      }
24846    } else {
24847      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
24848      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24849          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24850          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
24851          ((!rn.IsPC()) || AllowUnpredictable())) {
24852        if (cond.Is(al)) {
24853          const DRegister& first = nreglist.GetFirstDRegister();
24854          uint32_t len_encoding;
24855          switch (nreglist.GetLength()) {
24856            default:
24857              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24858            case 1:
24859              len_encoding = 0x7;
24860              break;
24861            case 2:
24862              len_encoding = 0xa;
24863              break;
24864            case 3:
24865              len_encoding = 0x6;
24866              break;
24867            case 4:
24868              len_encoding = 0x2;
24869              break;
24870          }
24871          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
24872                  (encoded_align_1.GetEncodingValue() << 4) |
24873                  first.Encode(22, 12) | (len_encoding << 8) |
24874                  (rn.GetCode() << 16));
24875          return;
24876        }
24877      }
24878      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
24879      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24880          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24881          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
24882          ((!rn.IsPC()) || AllowUnpredictable())) {
24883        if (cond.Is(al)) {
24884          const DRegister& first = nreglist.GetFirstDRegister();
24885          uint32_t len_encoding;
24886          switch (nreglist.GetLength()) {
24887            default:
24888              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24889            case 1:
24890              len_encoding = 0x7;
24891              break;
24892            case 2:
24893              len_encoding = 0xa;
24894              break;
24895            case 3:
24896              len_encoding = 0x6;
24897              break;
24898            case 4:
24899              len_encoding = 0x2;
24900              break;
24901          }
24902          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
24903                  (encoded_align_1.GetEncodingValue() << 4) |
24904                  first.Encode(22, 12) | (len_encoding << 8) |
24905                  (rn.GetCode() << 16));
24906          return;
24907        }
24908      }
24909      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
24910      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24911          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
24912          encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24913        if (cond.Is(al)) {
24914          const DRegister& first = nreglist.GetFirstDRegister();
24915          EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
24916                  (encoded_align_2.GetEncodingValue() << 4) |
24917                  first.Encode(22, 12) | (rn.GetCode() << 16));
24918          return;
24919        }
24920      }
24921      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
24922      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24923          (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
24924          encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24925        if (cond.Is(al)) {
24926          const DRegister& first = nreglist.GetFirstDRegister();
24927          EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
24928                  (encoded_align_2.GetEncodingValue() << 4) |
24929                  first.Encode(22, 12) | (rn.GetCode() << 16));
24930          return;
24931        }
24932      }
24933    }
24934  }
24935  if (operand.IsPlainRegister()) {
24936    Register rn = operand.GetBaseRegister();
24937    Alignment align = operand.GetAlignment();
24938    Register rm = operand.GetOffsetRegister();
24939    Dt_size_6 encoded_dt(dt);
24940    Dt_size_7 encoded_dt_2(dt);
24941    Align_align_5 encoded_align_1(align, nreglist);
24942    Align_index_align_1 encoded_align_2(align, nreglist, dt);
24943    if (IsUsingT32()) {
24944      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
24945      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24946          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24947          !rm.IsPC() && !rm.IsSP()) {
24948        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24949          const DRegister& first = nreglist.GetFirstDRegister();
24950          uint32_t len_encoding;
24951          switch (nreglist.GetLength()) {
24952            default:
24953              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24954            case 1:
24955              len_encoding = 0x7;
24956              break;
24957            case 2:
24958              len_encoding = 0xa;
24959              break;
24960            case 3:
24961              len_encoding = 0x6;
24962              break;
24963            case 4:
24964              len_encoding = 0x2;
24965              break;
24966          }
24967          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
24968                     (encoded_align_1.GetEncodingValue() << 4) |
24969                     first.Encode(22, 12) | (len_encoding << 8) |
24970                     (rn.GetCode() << 16) | rm.GetCode());
24971          AdvanceIT();
24972          return;
24973        }
24974      }
24975      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
24976      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24977          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
24978        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24979          const DRegister& first = nreglist.GetFirstDRegister();
24980          EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
24981                     (encoded_align_2.GetEncodingValue() << 4) |
24982                     first.Encode(22, 12) | (rn.GetCode() << 16) |
24983                     rm.GetCode());
24984          AdvanceIT();
24985          return;
24986        }
24987      }
24988    } else {
24989      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
24990      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24991          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24992          !rm.IsPC() && !rm.IsSP()) {
24993        if (cond.Is(al)) {
24994          const DRegister& first = nreglist.GetFirstDRegister();
24995          uint32_t len_encoding;
24996          switch (nreglist.GetLength()) {
24997            default:
24998              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24999            case 1:
25000              len_encoding = 0x7;
25001              break;
25002            case 2:
25003              len_encoding = 0xa;
25004              break;
25005            case 3:
25006              len_encoding = 0x6;
25007              break;
25008            case 4:
25009              len_encoding = 0x2;
25010              break;
25011          }
25012          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25013                  (encoded_align_1.GetEncodingValue() << 4) |
25014                  first.Encode(22, 12) | (len_encoding << 8) |
25015                  (rn.GetCode() << 16) | rm.GetCode());
25016          return;
25017        }
25018      }
25019      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25020      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
25021          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
25022        if (cond.Is(al)) {
25023          const DRegister& first = nreglist.GetFirstDRegister();
25024          EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
25025                  (encoded_align_2.GetEncodingValue() << 4) |
25026                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25027          return;
25028        }
25029      }
25030    }
25031  }
25032  Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
25033}
25034
25035void Assembler::vst2(Condition cond,
25036                     DataType dt,
25037                     const NeonRegisterList& nreglist,
25038                     const AlignedMemOperand& operand) {
25039  VIXL_ASSERT(AllowAssembler());
25040  CheckIT(cond);
25041  if (operand.IsImmediateZero()) {
25042    Register rn = operand.GetBaseRegister();
25043    Alignment align = operand.GetAlignment();
25044    Dt_size_7 encoded_dt(dt);
25045    Align_align_2 encoded_align_1(align, nreglist);
25046    Align_index_align_2 encoded_align_2(align, nreglist, dt);
25047    if (IsUsingT32()) {
25048      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25049      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25050          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25051           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25052           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25053          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25054          ((!rn.IsPC()) || AllowUnpredictable())) {
25055        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25056          const DRegister& first = nreglist.GetFirstDRegister();
25057          uint32_t len_encoding;
25058          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25059            len_encoding = 0x8;
25060          }
25061          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25062            len_encoding = 0x9;
25063          }
25064          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25065            len_encoding = 0x3;
25066          }
25067          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25068                     (encoded_align_1.GetEncodingValue() << 4) |
25069                     first.Encode(22, 12) | (len_encoding << 8) |
25070                     (rn.GetCode() << 16));
25071          AdvanceIT();
25072          return;
25073        }
25074      }
25075      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25076      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25077          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25078           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25079           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25080          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25081          ((!rn.IsPC()) || AllowUnpredictable())) {
25082        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25083          const DRegister& first = nreglist.GetFirstDRegister();
25084          uint32_t len_encoding;
25085          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25086            len_encoding = 0x8;
25087          }
25088          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25089            len_encoding = 0x9;
25090          }
25091          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25092            len_encoding = 0x3;
25093          }
25094          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25095                     (encoded_align_1.GetEncodingValue() << 4) |
25096                     first.Encode(22, 12) | (len_encoding << 8) |
25097                     (rn.GetCode() << 16));
25098          AdvanceIT();
25099          return;
25100        }
25101      }
25102      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25103      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25104          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25105           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25106          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25107          ((!rn.IsPC()) || AllowUnpredictable())) {
25108        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25109          const DRegister& first = nreglist.GetFirstDRegister();
25110          EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
25111                     (encoded_align_2.GetEncodingValue() << 4) |
25112                     first.Encode(22, 12) | (rn.GetCode() << 16));
25113          AdvanceIT();
25114          return;
25115        }
25116      }
25117      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25118      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25119          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25120           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25121          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25122          ((!rn.IsPC()) || AllowUnpredictable())) {
25123        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25124          const DRegister& first = nreglist.GetFirstDRegister();
25125          EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
25126                     (encoded_align_2.GetEncodingValue() << 4) |
25127                     first.Encode(22, 12) | (rn.GetCode() << 16));
25128          AdvanceIT();
25129          return;
25130        }
25131      }
25132    } else {
25133      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25134      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25135          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25136           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25137           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25138          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25139          ((!rn.IsPC()) || AllowUnpredictable())) {
25140        if (cond.Is(al)) {
25141          const DRegister& first = nreglist.GetFirstDRegister();
25142          uint32_t len_encoding;
25143          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25144            len_encoding = 0x8;
25145          }
25146          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25147            len_encoding = 0x9;
25148          }
25149          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25150            len_encoding = 0x3;
25151          }
25152          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25153                  (encoded_align_1.GetEncodingValue() << 4) |
25154                  first.Encode(22, 12) | (len_encoding << 8) |
25155                  (rn.GetCode() << 16));
25156          return;
25157        }
25158      }
25159      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25160      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25161          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25162           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25163           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25164          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25165          ((!rn.IsPC()) || AllowUnpredictable())) {
25166        if (cond.Is(al)) {
25167          const DRegister& first = nreglist.GetFirstDRegister();
25168          uint32_t len_encoding;
25169          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25170            len_encoding = 0x8;
25171          }
25172          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25173            len_encoding = 0x9;
25174          }
25175          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25176            len_encoding = 0x3;
25177          }
25178          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25179                  (encoded_align_1.GetEncodingValue() << 4) |
25180                  first.Encode(22, 12) | (len_encoding << 8) |
25181                  (rn.GetCode() << 16));
25182          return;
25183        }
25184      }
25185      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25186      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25187          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25188           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25189          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25190          ((!rn.IsPC()) || AllowUnpredictable())) {
25191        if (cond.Is(al)) {
25192          const DRegister& first = nreglist.GetFirstDRegister();
25193          EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
25194                  (encoded_align_2.GetEncodingValue() << 4) |
25195                  first.Encode(22, 12) | (rn.GetCode() << 16));
25196          return;
25197        }
25198      }
25199      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25200      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25201          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25202           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25203          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25204          ((!rn.IsPC()) || AllowUnpredictable())) {
25205        if (cond.Is(al)) {
25206          const DRegister& first = nreglist.GetFirstDRegister();
25207          EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
25208                  (encoded_align_2.GetEncodingValue() << 4) |
25209                  first.Encode(22, 12) | (rn.GetCode() << 16));
25210          return;
25211        }
25212      }
25213    }
25214  }
25215  if (operand.IsPlainRegister()) {
25216    Register rn = operand.GetBaseRegister();
25217    Alignment align = operand.GetAlignment();
25218    Register rm = operand.GetOffsetRegister();
25219    Dt_size_7 encoded_dt(dt);
25220    Align_align_2 encoded_align_1(align, nreglist);
25221    Align_index_align_2 encoded_align_2(align, nreglist, dt);
25222    if (IsUsingT32()) {
25223      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25224      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25225          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25226           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25227           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25228          !rm.IsPC() && !rm.IsSP()) {
25229        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25230          const DRegister& first = nreglist.GetFirstDRegister();
25231          uint32_t len_encoding;
25232          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25233            len_encoding = 0x8;
25234          }
25235          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25236            len_encoding = 0x9;
25237          }
25238          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25239            len_encoding = 0x3;
25240          }
25241          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25242                     (encoded_align_1.GetEncodingValue() << 4) |
25243                     first.Encode(22, 12) | (len_encoding << 8) |
25244                     (rn.GetCode() << 16) | rm.GetCode());
25245          AdvanceIT();
25246          return;
25247        }
25248      }
25249      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25250      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25251          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25252           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25253          !rm.IsPC() && !rm.IsSP()) {
25254        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25255          const DRegister& first = nreglist.GetFirstDRegister();
25256          EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
25257                     (encoded_align_2.GetEncodingValue() << 4) |
25258                     first.Encode(22, 12) | (rn.GetCode() << 16) |
25259                     rm.GetCode());
25260          AdvanceIT();
25261          return;
25262        }
25263      }
25264    } else {
25265      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25266      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25267          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25268           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25269           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25270          !rm.IsPC() && !rm.IsSP()) {
25271        if (cond.Is(al)) {
25272          const DRegister& first = nreglist.GetFirstDRegister();
25273          uint32_t len_encoding;
25274          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25275            len_encoding = 0x8;
25276          }
25277          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25278            len_encoding = 0x9;
25279          }
25280          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25281            len_encoding = 0x3;
25282          }
25283          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25284                  (encoded_align_1.GetEncodingValue() << 4) |
25285                  first.Encode(22, 12) | (len_encoding << 8) |
25286                  (rn.GetCode() << 16) | rm.GetCode());
25287          return;
25288        }
25289      }
25290      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25291      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25292          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25293           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25294          !rm.IsPC() && !rm.IsSP()) {
25295        if (cond.Is(al)) {
25296          const DRegister& first = nreglist.GetFirstDRegister();
25297          EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
25298                  (encoded_align_2.GetEncodingValue() << 4) |
25299                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25300          return;
25301        }
25302      }
25303    }
25304  }
25305  Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
25306}
25307
25308void Assembler::vst3(Condition cond,
25309                     DataType dt,
25310                     const NeonRegisterList& nreglist,
25311                     const AlignedMemOperand& operand) {
25312  VIXL_ASSERT(AllowAssembler());
25313  CheckIT(cond);
25314  if (operand.IsImmediateZero()) {
25315    Register rn = operand.GetBaseRegister();
25316    Alignment align = operand.GetAlignment();
25317    Dt_size_7 encoded_dt(dt);
25318    Align_align_3 encoded_align_1(align);
25319    if (IsUsingT32()) {
25320      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25321      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25322          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25323           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25324          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25325          ((!rn.IsPC()) || AllowUnpredictable())) {
25326        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25327          const DRegister& first = nreglist.GetFirstDRegister();
25328          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25329          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25330                     (encoded_align_1.GetEncodingValue() << 4) |
25331                     first.Encode(22, 12) | (len_encoding << 8) |
25332                     (rn.GetCode() << 16));
25333          AdvanceIT();
25334          return;
25335        }
25336      }
25337      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25338      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25339          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25340           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25341          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25342          ((!rn.IsPC()) || AllowUnpredictable())) {
25343        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25344          const DRegister& first = nreglist.GetFirstDRegister();
25345          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25346          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25347                     (encoded_align_1.GetEncodingValue() << 4) |
25348                     first.Encode(22, 12) | (len_encoding << 8) |
25349                     (rn.GetCode() << 16));
25350          AdvanceIT();
25351          return;
25352        }
25353      }
25354    } else {
25355      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25356      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25357          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25358           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25359          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25360          ((!rn.IsPC()) || AllowUnpredictable())) {
25361        if (cond.Is(al)) {
25362          const DRegister& first = nreglist.GetFirstDRegister();
25363          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25364          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25365                  (encoded_align_1.GetEncodingValue() << 4) |
25366                  first.Encode(22, 12) | (len_encoding << 8) |
25367                  (rn.GetCode() << 16));
25368          return;
25369        }
25370      }
25371      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25372      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25373          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25374           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25375          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25376          ((!rn.IsPC()) || AllowUnpredictable())) {
25377        if (cond.Is(al)) {
25378          const DRegister& first = nreglist.GetFirstDRegister();
25379          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25380          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25381                  (encoded_align_1.GetEncodingValue() << 4) |
25382                  first.Encode(22, 12) | (len_encoding << 8) |
25383                  (rn.GetCode() << 16));
25384          return;
25385        }
25386      }
25387    }
25388  }
25389  if (operand.IsPlainRegister()) {
25390    Register rn = operand.GetBaseRegister();
25391    Alignment align = operand.GetAlignment();
25392    Register rm = operand.GetOffsetRegister();
25393    Dt_size_7 encoded_dt(dt);
25394    Align_align_3 encoded_align_1(align);
25395    if (IsUsingT32()) {
25396      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25397      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25398          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25399           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25400          !rm.IsPC() && !rm.IsSP()) {
25401        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25402          const DRegister& first = nreglist.GetFirstDRegister();
25403          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25404          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25405                     (encoded_align_1.GetEncodingValue() << 4) |
25406                     first.Encode(22, 12) | (len_encoding << 8) |
25407                     (rn.GetCode() << 16) | rm.GetCode());
25408          AdvanceIT();
25409          return;
25410        }
25411      }
25412    } else {
25413      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25414      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25415          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25416           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25417          !rm.IsPC() && !rm.IsSP()) {
25418        if (cond.Is(al)) {
25419          const DRegister& first = nreglist.GetFirstDRegister();
25420          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25421          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25422                  (encoded_align_1.GetEncodingValue() << 4) |
25423                  first.Encode(22, 12) | (len_encoding << 8) |
25424                  (rn.GetCode() << 16) | rm.GetCode());
25425          return;
25426        }
25427      }
25428    }
25429  }
25430  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
25431}
25432
25433void Assembler::vst3(Condition cond,
25434                     DataType dt,
25435                     const NeonRegisterList& nreglist,
25436                     const MemOperand& operand) {
25437  VIXL_ASSERT(AllowAssembler());
25438  CheckIT(cond);
25439  if (operand.IsImmediateZero()) {
25440    Register rn = operand.GetBaseRegister();
25441    Dt_size_7 encoded_dt(dt);
25442    Index_1 encoded_align_1(nreglist, dt);
25443    if (IsUsingT32()) {
25444      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
25445      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25446          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25447           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25448          (operand.GetAddrMode() == Offset) &&
25449          ((!rn.IsPC()) || AllowUnpredictable())) {
25450        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25451          const DRegister& first = nreglist.GetFirstDRegister();
25452          EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
25453                     (encoded_align_1.GetEncodingValue() << 4) |
25454                     first.Encode(22, 12) | (rn.GetCode() << 16));
25455          AdvanceIT();
25456          return;
25457        }
25458      }
25459      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
25460      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25461          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25462           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25463          (operand.GetAddrMode() == PreIndex) &&
25464          ((!rn.IsPC()) || AllowUnpredictable())) {
25465        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25466          const DRegister& first = nreglist.GetFirstDRegister();
25467          EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
25468                     (encoded_align_1.GetEncodingValue() << 4) |
25469                     first.Encode(22, 12) | (rn.GetCode() << 16));
25470          AdvanceIT();
25471          return;
25472        }
25473      }
25474    } else {
25475      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
25476      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25477          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25478           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25479          (operand.GetAddrMode() == Offset) &&
25480          ((!rn.IsPC()) || AllowUnpredictable())) {
25481        if (cond.Is(al)) {
25482          const DRegister& first = nreglist.GetFirstDRegister();
25483          EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
25484                  (encoded_align_1.GetEncodingValue() << 4) |
25485                  first.Encode(22, 12) | (rn.GetCode() << 16));
25486          return;
25487        }
25488      }
25489      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
25490      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25491          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25492           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25493          (operand.GetAddrMode() == PreIndex) &&
25494          ((!rn.IsPC()) || AllowUnpredictable())) {
25495        if (cond.Is(al)) {
25496          const DRegister& first = nreglist.GetFirstDRegister();
25497          EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
25498                  (encoded_align_1.GetEncodingValue() << 4) |
25499                  first.Encode(22, 12) | (rn.GetCode() << 16));
25500          return;
25501        }
25502      }
25503    }
25504  }
25505  if (operand.IsPlainRegister()) {
25506    Register rn = operand.GetBaseRegister();
25507    Sign sign = operand.GetSign();
25508    Register rm = operand.GetOffsetRegister();
25509    Dt_size_7 encoded_dt(dt);
25510    Index_1 encoded_align_1(nreglist, dt);
25511    if (IsUsingT32()) {
25512      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
25513      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25514          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25515           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25516          sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
25517        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25518          const DRegister& first = nreglist.GetFirstDRegister();
25519          EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
25520                     (encoded_align_1.GetEncodingValue() << 4) |
25521                     first.Encode(22, 12) | (rn.GetCode() << 16) |
25522                     rm.GetCode());
25523          AdvanceIT();
25524          return;
25525        }
25526      }
25527    } else {
25528      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
25529      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25530          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25531           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25532          sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
25533        if (cond.Is(al)) {
25534          const DRegister& first = nreglist.GetFirstDRegister();
25535          EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
25536                  (encoded_align_1.GetEncodingValue() << 4) |
25537                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25538          return;
25539        }
25540      }
25541    }
25542  }
25543  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
25544}
25545
25546void Assembler::vst4(Condition cond,
25547                     DataType dt,
25548                     const NeonRegisterList& nreglist,
25549                     const AlignedMemOperand& operand) {
25550  VIXL_ASSERT(AllowAssembler());
25551  CheckIT(cond);
25552  if (operand.IsImmediateZero()) {
25553    Register rn = operand.GetBaseRegister();
25554    Alignment align = operand.GetAlignment();
25555    Dt_size_7 encoded_dt(dt);
25556    Align_align_4 encoded_align_1(align);
25557    Align_index_align_3 encoded_align_2(align, nreglist, dt);
25558    if (IsUsingT32()) {
25559      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25560      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25561          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25562           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25563          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25564          ((!rn.IsPC()) || AllowUnpredictable())) {
25565        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25566          const DRegister& first = nreglist.GetFirstDRegister();
25567          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25568          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25569                     (encoded_align_1.GetEncodingValue() << 4) |
25570                     first.Encode(22, 12) | (len_encoding << 8) |
25571                     (rn.GetCode() << 16));
25572          AdvanceIT();
25573          return;
25574        }
25575      }
25576      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25577      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25578          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25579           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25580          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25581          ((!rn.IsPC()) || AllowUnpredictable())) {
25582        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25583          const DRegister& first = nreglist.GetFirstDRegister();
25584          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25585          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25586                     (encoded_align_1.GetEncodingValue() << 4) |
25587                     first.Encode(22, 12) | (len_encoding << 8) |
25588                     (rn.GetCode() << 16));
25589          AdvanceIT();
25590          return;
25591        }
25592      }
25593      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25594      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25595          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25596           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25597          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25598          ((!rn.IsPC()) || AllowUnpredictable())) {
25599        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25600          const DRegister& first = nreglist.GetFirstDRegister();
25601          EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
25602                     (encoded_align_2.GetEncodingValue() << 4) |
25603                     first.Encode(22, 12) | (rn.GetCode() << 16));
25604          AdvanceIT();
25605          return;
25606        }
25607      }
25608      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25609      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25610          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25611           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25612          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25613          ((!rn.IsPC()) || AllowUnpredictable())) {
25614        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25615          const DRegister& first = nreglist.GetFirstDRegister();
25616          EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
25617                     (encoded_align_2.GetEncodingValue() << 4) |
25618                     first.Encode(22, 12) | (rn.GetCode() << 16));
25619          AdvanceIT();
25620          return;
25621        }
25622      }
25623    } else {
25624      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25625      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25626          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25627           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25628          (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25629          ((!rn.IsPC()) || AllowUnpredictable())) {
25630        if (cond.Is(al)) {
25631          const DRegister& first = nreglist.GetFirstDRegister();
25632          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25633          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25634                  (encoded_align_1.GetEncodingValue() << 4) |
25635                  first.Encode(22, 12) | (len_encoding << 8) |
25636                  (rn.GetCode() << 16));
25637          return;
25638        }
25639      }
25640      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25641      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25642          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25643           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25644          (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25645          ((!rn.IsPC()) || AllowUnpredictable())) {
25646        if (cond.Is(al)) {
25647          const DRegister& first = nreglist.GetFirstDRegister();
25648          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25649          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25650                  (encoded_align_1.GetEncodingValue() << 4) |
25651                  first.Encode(22, 12) | (len_encoding << 8) |
25652                  (rn.GetCode() << 16));
25653          return;
25654        }
25655      }
25656      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25657      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25658          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25659           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25660          (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25661          ((!rn.IsPC()) || AllowUnpredictable())) {
25662        if (cond.Is(al)) {
25663          const DRegister& first = nreglist.GetFirstDRegister();
25664          EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
25665                  (encoded_align_2.GetEncodingValue() << 4) |
25666                  first.Encode(22, 12) | (rn.GetCode() << 16));
25667          return;
25668        }
25669      }
25670      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25671      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25672          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25673           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25674          (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25675          ((!rn.IsPC()) || AllowUnpredictable())) {
25676        if (cond.Is(al)) {
25677          const DRegister& first = nreglist.GetFirstDRegister();
25678          EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
25679                  (encoded_align_2.GetEncodingValue() << 4) |
25680                  first.Encode(22, 12) | (rn.GetCode() << 16));
25681          return;
25682        }
25683      }
25684    }
25685  }
25686  if (operand.IsPlainRegister()) {
25687    Register rn = operand.GetBaseRegister();
25688    Alignment align = operand.GetAlignment();
25689    Register rm = operand.GetOffsetRegister();
25690    Dt_size_7 encoded_dt(dt);
25691    Align_align_4 encoded_align_1(align);
25692    Align_index_align_3 encoded_align_2(align, nreglist, dt);
25693    if (IsUsingT32()) {
25694      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25695      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25696          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25697           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25698          !rm.IsPC() && !rm.IsSP()) {
25699        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25700          const DRegister& first = nreglist.GetFirstDRegister();
25701          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25702          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25703                     (encoded_align_1.GetEncodingValue() << 4) |
25704                     first.Encode(22, 12) | (len_encoding << 8) |
25705                     (rn.GetCode() << 16) | rm.GetCode());
25706          AdvanceIT();
25707          return;
25708        }
25709      }
25710      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25711      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25712          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25713           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25714          !rm.IsPC() && !rm.IsSP()) {
25715        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25716          const DRegister& first = nreglist.GetFirstDRegister();
25717          EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
25718                     (encoded_align_2.GetEncodingValue() << 4) |
25719                     first.Encode(22, 12) | (rn.GetCode() << 16) |
25720                     rm.GetCode());
25721          AdvanceIT();
25722          return;
25723        }
25724      }
25725    } else {
25726      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25727      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25728          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25729           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25730          !rm.IsPC() && !rm.IsSP()) {
25731        if (cond.Is(al)) {
25732          const DRegister& first = nreglist.GetFirstDRegister();
25733          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25734          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25735                  (encoded_align_1.GetEncodingValue() << 4) |
25736                  first.Encode(22, 12) | (len_encoding << 8) |
25737                  (rn.GetCode() << 16) | rm.GetCode());
25738          return;
25739        }
25740      }
25741      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25742      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25743          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25744           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25745          !rm.IsPC() && !rm.IsSP()) {
25746        if (cond.Is(al)) {
25747          const DRegister& first = nreglist.GetFirstDRegister();
25748          EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
25749                  (encoded_align_2.GetEncodingValue() << 4) |
25750                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25751          return;
25752        }
25753      }
25754    }
25755  }
25756  Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
25757}
25758
25759void Assembler::vstm(Condition cond,
25760                     DataType dt,
25761                     Register rn,
25762                     WriteBack write_back,
25763                     DRegisterList dreglist) {
25764  VIXL_ASSERT(AllowAssembler());
25765  CheckIT(cond);
25766  USE(dt);
25767  if (IsUsingT32()) {
25768    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
25769    if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25770      const DRegister& dreg = dreglist.GetFirstDRegister();
25771      unsigned len = dreglist.GetLength() * 2;
25772      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
25773                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25774                 (len & 0xff));
25775      AdvanceIT();
25776      return;
25777    }
25778  } else {
25779    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
25780    if (cond.IsNotNever() &&
25781        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25782      const DRegister& dreg = dreglist.GetFirstDRegister();
25783      unsigned len = dreglist.GetLength() * 2;
25784      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25785              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25786              (len & 0xff));
25787      return;
25788    }
25789  }
25790  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
25791}
25792
25793void Assembler::vstm(Condition cond,
25794                     DataType dt,
25795                     Register rn,
25796                     WriteBack write_back,
25797                     SRegisterList sreglist) {
25798  VIXL_ASSERT(AllowAssembler());
25799  CheckIT(cond);
25800  USE(dt);
25801  if (IsUsingT32()) {
25802    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
25803    const SRegister& sreg = sreglist.GetFirstSRegister();
25804    unsigned len = sreglist.GetLength();
25805    EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
25806               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25807               (len & 0xff));
25808    AdvanceIT();
25809    return;
25810  } else {
25811    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
25812    if (cond.IsNotNever()) {
25813      const SRegister& sreg = sreglist.GetFirstSRegister();
25814      unsigned len = sreglist.GetLength();
25815      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25816              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25817              (len & 0xff));
25818      return;
25819    }
25820  }
25821  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
25822}
25823
25824void Assembler::vstmdb(Condition cond,
25825                       DataType dt,
25826                       Register rn,
25827                       WriteBack write_back,
25828                       DRegisterList dreglist) {
25829  VIXL_ASSERT(AllowAssembler());
25830  CheckIT(cond);
25831  USE(dt);
25832  if (IsUsingT32()) {
25833    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
25834    if (write_back.DoesWriteBack() &&
25835        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25836      const DRegister& dreg = dreglist.GetFirstDRegister();
25837      unsigned len = dreglist.GetLength() * 2;
25838      EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
25839                 (len & 0xff));
25840      AdvanceIT();
25841      return;
25842    }
25843  } else {
25844    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
25845    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
25846        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25847      const DRegister& dreg = dreglist.GetFirstDRegister();
25848      unsigned len = dreglist.GetLength() * 2;
25849      EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25850              dreg.Encode(22, 12) | (len & 0xff));
25851      return;
25852    }
25853  }
25854  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
25855}
25856
25857void Assembler::vstmdb(Condition cond,
25858                       DataType dt,
25859                       Register rn,
25860                       WriteBack write_back,
25861                       SRegisterList sreglist) {
25862  VIXL_ASSERT(AllowAssembler());
25863  CheckIT(cond);
25864  USE(dt);
25865  if (IsUsingT32()) {
25866    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
25867    if (write_back.DoesWriteBack()) {
25868      const SRegister& sreg = sreglist.GetFirstSRegister();
25869      unsigned len = sreglist.GetLength();
25870      EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
25871                 (len & 0xff));
25872      AdvanceIT();
25873      return;
25874    }
25875  } else {
25876    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
25877    if (write_back.DoesWriteBack() && cond.IsNotNever()) {
25878      const SRegister& sreg = sreglist.GetFirstSRegister();
25879      unsigned len = sreglist.GetLength();
25880      EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25881              sreg.Encode(22, 12) | (len & 0xff));
25882      return;
25883    }
25884  }
25885  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
25886}
25887
25888void Assembler::vstmia(Condition cond,
25889                       DataType dt,
25890                       Register rn,
25891                       WriteBack write_back,
25892                       DRegisterList dreglist) {
25893  VIXL_ASSERT(AllowAssembler());
25894  CheckIT(cond);
25895  USE(dt);
25896  if (IsUsingT32()) {
25897    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
25898    if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25899      const DRegister& dreg = dreglist.GetFirstDRegister();
25900      unsigned len = dreglist.GetLength() * 2;
25901      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
25902                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25903                 (len & 0xff));
25904      AdvanceIT();
25905      return;
25906    }
25907  } else {
25908    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
25909    if (cond.IsNotNever() &&
25910        (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25911      const DRegister& dreg = dreglist.GetFirstDRegister();
25912      unsigned len = dreglist.GetLength() * 2;
25913      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25914              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25915              (len & 0xff));
25916      return;
25917    }
25918  }
25919  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
25920}
25921
25922void Assembler::vstmia(Condition cond,
25923                       DataType dt,
25924                       Register rn,
25925                       WriteBack write_back,
25926                       SRegisterList sreglist) {
25927  VIXL_ASSERT(AllowAssembler());
25928  CheckIT(cond);
25929  USE(dt);
25930  if (IsUsingT32()) {
25931    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
25932    const SRegister& sreg = sreglist.GetFirstSRegister();
25933    unsigned len = sreglist.GetLength();
25934    EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
25935               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25936               (len & 0xff));
25937    AdvanceIT();
25938    return;
25939  } else {
25940    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
25941    if (cond.IsNotNever()) {
25942      const SRegister& sreg = sreglist.GetFirstSRegister();
25943      unsigned len = sreglist.GetLength();
25944      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25945              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25946              (len & 0xff));
25947      return;
25948    }
25949  }
25950  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
25951}
25952
25953void Assembler::vstr(Condition cond,
25954                     DataType dt,
25955                     DRegister rd,
25956                     const MemOperand& operand) {
25957  VIXL_ASSERT(AllowAssembler());
25958  CheckIT(cond);
25959  if (operand.IsImmediate()) {
25960    Register rn = operand.GetBaseRegister();
25961    int32_t offset = operand.GetOffsetImmediate();
25962    if (IsUsingT32()) {
25963      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
25964      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
25965          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset)) {
25966        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25967        uint32_t offset_ = abs(offset) >> 2;
25968        EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
25969                   offset_ | (sign << 23));
25970        AdvanceIT();
25971        return;
25972      }
25973    } else {
25974      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
25975      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
25976          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
25977          cond.IsNotNever()) {
25978        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25979        uint32_t offset_ = abs(offset) >> 2;
25980        EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25981                (rn.GetCode() << 16) | offset_ | (sign << 23));
25982        return;
25983      }
25984    }
25985  }
25986  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
25987}
25988
25989void Assembler::vstr(Condition cond,
25990                     DataType dt,
25991                     SRegister rd,
25992                     const MemOperand& operand) {
25993  VIXL_ASSERT(AllowAssembler());
25994  CheckIT(cond);
25995  if (operand.IsImmediate()) {
25996    Register rn = operand.GetBaseRegister();
25997    int32_t offset = operand.GetOffsetImmediate();
25998    if (IsUsingT32()) {
25999      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
26000      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
26001          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset)) {
26002        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
26003        uint32_t offset_ = abs(offset) >> 2;
26004        EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
26005                   offset_ | (sign << 23));
26006        AdvanceIT();
26007        return;
26008      }
26009    } else {
26010      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
26011      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
26012          ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
26013          cond.IsNotNever()) {
26014        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
26015        uint32_t offset_ = abs(offset) >> 2;
26016        EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26017                (rn.GetCode() << 16) | offset_ | (sign << 23));
26018        return;
26019      }
26020    }
26021  }
26022  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
26023}
26024
26025void Assembler::vsub(
26026    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
26027  VIXL_ASSERT(AllowAssembler());
26028  CheckIT(cond);
26029  Dt_size_2 encoded_dt(dt);
26030  if (IsUsingT32()) {
26031    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
26032    if (dt.Is(F32)) {
26033      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26034        EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26035                   rm.Encode(5, 0));
26036        AdvanceIT();
26037        return;
26038      }
26039    }
26040    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
26041    if (dt.Is(F64)) {
26042      EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26043                 rm.Encode(5, 0));
26044      AdvanceIT();
26045      return;
26046    }
26047    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
26048    if (encoded_dt.IsValid()) {
26049      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26050        EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
26051                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26052        AdvanceIT();
26053        return;
26054      }
26055    }
26056  } else {
26057    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
26058    if (dt.Is(F32)) {
26059      if (cond.Is(al)) {
26060        EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26061                rm.Encode(5, 0));
26062        return;
26063      }
26064    }
26065    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
26066    if (dt.Is(F64) && cond.IsNotNever()) {
26067      EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26068              rn.Encode(7, 16) | rm.Encode(5, 0));
26069      return;
26070    }
26071    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
26072    if (encoded_dt.IsValid()) {
26073      if (cond.Is(al)) {
26074        EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
26075                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26076        return;
26077      }
26078    }
26079  }
26080  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26081}
26082
26083void Assembler::vsub(
26084    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
26085  VIXL_ASSERT(AllowAssembler());
26086  CheckIT(cond);
26087  Dt_size_2 encoded_dt(dt);
26088  if (IsUsingT32()) {
26089    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
26090    if (dt.Is(F32)) {
26091      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26092        EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26093                   rm.Encode(5, 0));
26094        AdvanceIT();
26095        return;
26096      }
26097    }
26098    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
26099    if (encoded_dt.IsValid()) {
26100      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26101        EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
26102                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26103        AdvanceIT();
26104        return;
26105      }
26106    }
26107  } else {
26108    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
26109    if (dt.Is(F32)) {
26110      if (cond.Is(al)) {
26111        EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26112                rm.Encode(5, 0));
26113        return;
26114      }
26115    }
26116    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
26117    if (encoded_dt.IsValid()) {
26118      if (cond.Is(al)) {
26119        EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
26120                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26121        return;
26122      }
26123    }
26124  }
26125  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26126}
26127
26128void Assembler::vsub(
26129    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
26130  VIXL_ASSERT(AllowAssembler());
26131  CheckIT(cond);
26132  if (IsUsingT32()) {
26133    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
26134    if (dt.Is(F32)) {
26135      EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26136                 rm.Encode(5, 0));
26137      AdvanceIT();
26138      return;
26139    }
26140  } else {
26141    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
26142    if (dt.Is(F32) && cond.IsNotNever()) {
26143      EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26144              rn.Encode(7, 16) | rm.Encode(5, 0));
26145      return;
26146    }
26147  }
26148  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26149}
26150
26151void Assembler::vsubhn(
26152    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
26153  VIXL_ASSERT(AllowAssembler());
26154  CheckIT(cond);
26155  Dt_size_3 encoded_dt(dt);
26156  if (IsUsingT32()) {
26157    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
26158    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
26159      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26160        EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
26161                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26162        AdvanceIT();
26163        return;
26164      }
26165    }
26166  } else {
26167    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
26168    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
26169      if (cond.Is(al)) {
26170        EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
26171                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26172        return;
26173      }
26174    }
26175  }
26176  Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
26177}
26178
26179void Assembler::vsubl(
26180    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
26181  VIXL_ASSERT(AllowAssembler());
26182  CheckIT(cond);
26183  Dt_U_size_1 encoded_dt(dt);
26184  if (IsUsingT32()) {
26185    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
26186    if (encoded_dt.IsValid()) {
26187      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26188        EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26189                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
26190                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26191        AdvanceIT();
26192        return;
26193      }
26194    }
26195  } else {
26196    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
26197    if (encoded_dt.IsValid()) {
26198      if (cond.Is(al)) {
26199        EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26200                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
26201                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26202        return;
26203      }
26204    }
26205  }
26206  Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
26207}
26208
26209void Assembler::vsubw(
26210    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
26211  VIXL_ASSERT(AllowAssembler());
26212  CheckIT(cond);
26213  Dt_U_size_1 encoded_dt(dt);
26214  if (IsUsingT32()) {
26215    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
26216    if (encoded_dt.IsValid()) {
26217      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26218        EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26219                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
26220                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26221        AdvanceIT();
26222        return;
26223      }
26224    }
26225  } else {
26226    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
26227    if (encoded_dt.IsValid()) {
26228      if (cond.Is(al)) {
26229        EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26230                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
26231                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26232        return;
26233      }
26234    }
26235  }
26236  Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
26237}
26238
26239void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26240  VIXL_ASSERT(AllowAssembler());
26241  CheckIT(cond);
26242  USE(dt);
26243  if (IsUsingT32()) {
26244    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
26245    if (cond.Is(al) || AllowStronglyDiscouraged()) {
26246      EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
26247      AdvanceIT();
26248      return;
26249    }
26250  } else {
26251    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
26252    if (cond.Is(al)) {
26253      EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
26254      return;
26255    }
26256  }
26257  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
26258}
26259
26260void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26261  VIXL_ASSERT(AllowAssembler());
26262  CheckIT(cond);
26263  USE(dt);
26264  if (IsUsingT32()) {
26265    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
26266    if (cond.Is(al) || AllowStronglyDiscouraged()) {
26267      EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
26268      AdvanceIT();
26269      return;
26270    }
26271  } else {
26272    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
26273    if (cond.Is(al)) {
26274      EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
26275      return;
26276    }
26277  }
26278  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
26279}
26280
26281void Assembler::vtbl(Condition cond,
26282                     DataType dt,
26283                     DRegister rd,
26284                     const NeonRegisterList& nreglist,
26285                     DRegister rm) {
26286  VIXL_ASSERT(AllowAssembler());
26287  CheckIT(cond);
26288  if (IsUsingT32()) {
26289    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
26290    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26291        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26292      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26293        const DRegister& first = nreglist.GetFirstDRegister();
26294        uint32_t len_encoding = nreglist.GetLength() - 1;
26295        EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
26296                   (len_encoding << 8) | rm.Encode(5, 0));
26297        AdvanceIT();
26298        return;
26299      }
26300    }
26301  } else {
26302    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
26303    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26304        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26305      if (cond.Is(al)) {
26306        const DRegister& first = nreglist.GetFirstDRegister();
26307        uint32_t len_encoding = nreglist.GetLength() - 1;
26308        EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
26309                (len_encoding << 8) | rm.Encode(5, 0));
26310        return;
26311      }
26312    }
26313  }
26314  Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
26315}
26316
26317void Assembler::vtbx(Condition cond,
26318                     DataType dt,
26319                     DRegister rd,
26320                     const NeonRegisterList& nreglist,
26321                     DRegister rm) {
26322  VIXL_ASSERT(AllowAssembler());
26323  CheckIT(cond);
26324  if (IsUsingT32()) {
26325    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
26326    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26327        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26328      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26329        const DRegister& first = nreglist.GetFirstDRegister();
26330        uint32_t len_encoding = nreglist.GetLength() - 1;
26331        EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
26332                   (len_encoding << 8) | rm.Encode(5, 0));
26333        AdvanceIT();
26334        return;
26335      }
26336    }
26337  } else {
26338    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
26339    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26340        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26341      if (cond.Is(al)) {
26342        const DRegister& first = nreglist.GetFirstDRegister();
26343        uint32_t len_encoding = nreglist.GetLength() - 1;
26344        EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
26345                (len_encoding << 8) | rm.Encode(5, 0));
26346        return;
26347      }
26348    }
26349  }
26350  Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
26351}
26352
26353void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26354  VIXL_ASSERT(AllowAssembler());
26355  CheckIT(cond);
26356  Dt_size_7 encoded_dt(dt);
26357  if (IsUsingT32()) {
26358    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26359    if (encoded_dt.IsValid()) {
26360      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26361        EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
26362                   rd.Encode(22, 12) | rm.Encode(5, 0));
26363        AdvanceIT();
26364        return;
26365      }
26366    }
26367  } else {
26368    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26369    if (encoded_dt.IsValid()) {
26370      if (cond.Is(al)) {
26371        EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
26372                rd.Encode(22, 12) | rm.Encode(5, 0));
26373        return;
26374      }
26375    }
26376  }
26377  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
26378}
26379
26380void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26381  VIXL_ASSERT(AllowAssembler());
26382  CheckIT(cond);
26383  Dt_size_7 encoded_dt(dt);
26384  if (IsUsingT32()) {
26385    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26386    if (encoded_dt.IsValid()) {
26387      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26388        EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
26389                   rd.Encode(22, 12) | rm.Encode(5, 0));
26390        AdvanceIT();
26391        return;
26392      }
26393    }
26394  } else {
26395    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26396    if (encoded_dt.IsValid()) {
26397      if (cond.Is(al)) {
26398        EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
26399                rd.Encode(22, 12) | rm.Encode(5, 0));
26400        return;
26401      }
26402    }
26403  }
26404  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
26405}
26406
26407void Assembler::vtst(
26408    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
26409  VIXL_ASSERT(AllowAssembler());
26410  CheckIT(cond);
26411  Dt_size_7 encoded_dt(dt);
26412  if (IsUsingT32()) {
26413    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
26414    if (encoded_dt.IsValid()) {
26415      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26416        EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
26417                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26418        AdvanceIT();
26419        return;
26420      }
26421    }
26422  } else {
26423    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
26424    if (encoded_dt.IsValid()) {
26425      if (cond.Is(al)) {
26426        EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
26427                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26428        return;
26429      }
26430    }
26431  }
26432  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
26433}
26434
26435void Assembler::vtst(
26436    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
26437  VIXL_ASSERT(AllowAssembler());
26438  CheckIT(cond);
26439  Dt_size_7 encoded_dt(dt);
26440  if (IsUsingT32()) {
26441    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
26442    if (encoded_dt.IsValid()) {
26443      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26444        EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
26445                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26446        AdvanceIT();
26447        return;
26448      }
26449    }
26450  } else {
26451    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
26452    if (encoded_dt.IsValid()) {
26453      if (cond.Is(al)) {
26454        EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
26455                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26456        return;
26457      }
26458    }
26459  }
26460  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
26461}
26462
26463void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26464  VIXL_ASSERT(AllowAssembler());
26465  CheckIT(cond);
26466  Dt_size_15 encoded_dt(dt);
26467  if (IsUsingT32()) {
26468    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26469    if (encoded_dt.IsValid()) {
26470      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26471        EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
26472                   rd.Encode(22, 12) | rm.Encode(5, 0));
26473        AdvanceIT();
26474        return;
26475      }
26476    }
26477    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
26478    if (dt.Is(Untyped32)) {
26479      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26480        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26481        AdvanceIT();
26482        return;
26483      }
26484    }
26485  } else {
26486    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26487    if (encoded_dt.IsValid()) {
26488      if (cond.Is(al)) {
26489        EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
26490                rd.Encode(22, 12) | rm.Encode(5, 0));
26491        return;
26492      }
26493    }
26494    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
26495    if (dt.Is(Untyped32)) {
26496      if (cond.Is(al)) {
26497        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26498        return;
26499      }
26500    }
26501  }
26502  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
26503}
26504
26505void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26506  VIXL_ASSERT(AllowAssembler());
26507  CheckIT(cond);
26508  Dt_size_7 encoded_dt(dt);
26509  if (IsUsingT32()) {
26510    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26511    if (encoded_dt.IsValid()) {
26512      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26513        EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
26514                   rd.Encode(22, 12) | rm.Encode(5, 0));
26515        AdvanceIT();
26516        return;
26517      }
26518    }
26519  } else {
26520    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26521    if (encoded_dt.IsValid()) {
26522      if (cond.Is(al)) {
26523        EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
26524                rd.Encode(22, 12) | rm.Encode(5, 0));
26525        return;
26526      }
26527    }
26528  }
26529  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
26530}
26531
26532void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26533  VIXL_ASSERT(AllowAssembler());
26534  CheckIT(cond);
26535  Dt_size_15 encoded_dt(dt);
26536  if (IsUsingT32()) {
26537    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26538    if (encoded_dt.IsValid()) {
26539      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26540        EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
26541                   rd.Encode(22, 12) | rm.Encode(5, 0));
26542        AdvanceIT();
26543        return;
26544      }
26545    }
26546    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
26547    if (dt.Is(Untyped32)) {
26548      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26549        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26550        AdvanceIT();
26551        return;
26552      }
26553    }
26554  } else {
26555    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26556    if (encoded_dt.IsValid()) {
26557      if (cond.Is(al)) {
26558        EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
26559                rd.Encode(22, 12) | rm.Encode(5, 0));
26560        return;
26561      }
26562    }
26563    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
26564    if (dt.Is(Untyped32)) {
26565      if (cond.Is(al)) {
26566        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26567        return;
26568      }
26569    }
26570  }
26571  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
26572}
26573
26574void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26575  VIXL_ASSERT(AllowAssembler());
26576  CheckIT(cond);
26577  Dt_size_7 encoded_dt(dt);
26578  if (IsUsingT32()) {
26579    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26580    if (encoded_dt.IsValid()) {
26581      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26582        EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
26583                   rd.Encode(22, 12) | rm.Encode(5, 0));
26584        AdvanceIT();
26585        return;
26586      }
26587    }
26588  } else {
26589    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26590    if (encoded_dt.IsValid()) {
26591      if (cond.Is(al)) {
26592        EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
26593                rd.Encode(22, 12) | rm.Encode(5, 0));
26594        return;
26595      }
26596    }
26597  }
26598  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
26599}
26600
26601void Assembler::yield(Condition cond, EncodingSize size) {
26602  VIXL_ASSERT(AllowAssembler());
26603  CheckIT(cond);
26604  if (IsUsingT32()) {
26605    // YIELD{<c>}{<q>} ; T1
26606    if (!size.IsWide()) {
26607      EmitT32_16(0xbf10);
26608      AdvanceIT();
26609      return;
26610    }
26611    // YIELD{<c>}.W ; T2
26612    if (!size.IsNarrow()) {
26613      EmitT32_32(0xf3af8001U);
26614      AdvanceIT();
26615      return;
26616    }
26617  } else {
26618    // YIELD{<c>}{<q>} ; A1
26619    if (cond.IsNotNever()) {
26620      EmitA32(0x0320f001U | (cond.GetCondition() << 28));
26621      return;
26622    }
26623  }
26624  Delegate(kYield, &Assembler::yield, cond, size);
26625}
26626// End of generated code.
26627
26628}  // namespace aarch32
26629}  // namespace vixl
26630