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>
36
37#include "utils-vixl.h"
38#include "aarch32/constants-aarch32.h"
39#include "aarch32/instructions-aarch32.h"
40#include "aarch32/operands-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
82void Assembler::BindHelper(Label* label) {
83  VIXL_ASSERT(!label->IsBound());
84  label->Bind(GetCursorOffset(), GetInstructionSetInUse());
85
86  for (Label::ForwardRefList::iterator ref = label->GetFirstForwardRef();
87       ref != label->GetEndForwardRef();
88       ref++) {
89    EncodeLabelFor(*ref, label);
90  }
91  if (label->IsInVeneerPool()) {
92    label->GetVeneerPoolManager()->RemoveLabel(label);
93  }
94}
95
96
97uint32_t Assembler::Link(uint32_t instr,
98                         Label* label,
99                         const Label::LabelEmitOperator& op) {
100  label->SetReferenced();
101  if (label->IsBound()) {
102    return op.Encode(instr,
103                     GetCursorOffset() + GetArchitectureStatePCOffset(),
104                     label);
105  }
106  label->AddForwardRef(GetCursorOffset(), GetInstructionSetInUse(), op);
107  return instr;
108}
109
110
111void Assembler::EncodeLabelFor(const Label::ForwardReference& forward,
112                               Label* label) {
113  const uint32_t location = forward.GetLocation();
114  const uint32_t from = location + forward.GetStatePCOffset();
115  const Label::LabelEmitOperator& encoder = forward.GetEmitOperator();
116  if (forward.IsUsingT32()) {
117    uint16_t* instr_ptr = buffer_.GetOffsetAddress<uint16_t*>(location);
118    if (Is16BitEncoding(instr_ptr[0])) {
119      // The Encode methods always deals with uint32_t types so we need
120      // to explicitely cast it.
121      uint32_t instr = static_cast<uint32_t>(instr_ptr[0]);
122      instr = encoder.Encode(instr, from, label);
123      // The Encode method should not ever set the top 16 bits.
124      VIXL_ASSERT((instr & ~0xffff) == 0);
125      instr_ptr[0] = static_cast<uint16_t>(instr);
126    } else {
127      uint32_t instr =
128          instr_ptr[1] | (static_cast<uint32_t>(instr_ptr[0]) << 16);
129      instr = encoder.Encode(instr, from, label);
130      instr_ptr[0] = static_cast<uint16_t>(instr >> 16);
131      instr_ptr[1] = static_cast<uint16_t>(instr);
132    }
133  } else {
134    uint32_t* instr_ptr = buffer_.GetOffsetAddress<uint32_t*>(location);
135    instr_ptr[0] = encoder.Encode(instr_ptr[0], from, label);
136  }
137}
138
139
140// Start of generated code.
141class Dt_L_imm6_1 : public EncodingValue {
142  uint32_t type_;
143
144 public:
145  explicit Dt_L_imm6_1(DataType dt);
146  uint32_t GetTypeEncodingValue() const { return type_; }
147};
148
149Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
150  switch (dt.GetValue()) {
151    case S8:
152      type_ = 0x0;
153      SetEncodingValue(0x1);
154      break;
155    case U8:
156      type_ = 0x1;
157      SetEncodingValue(0x1);
158      break;
159    case S16:
160      type_ = 0x0;
161      SetEncodingValue(0x2);
162      break;
163    case U16:
164      type_ = 0x1;
165      SetEncodingValue(0x2);
166      break;
167    case S32:
168      type_ = 0x0;
169      SetEncodingValue(0x4);
170      break;
171    case U32:
172      type_ = 0x1;
173      SetEncodingValue(0x4);
174      break;
175    case S64:
176      type_ = 0x0;
177      SetEncodingValue(0x8);
178      break;
179    case U64:
180      type_ = 0x1;
181      SetEncodingValue(0x8);
182      break;
183    default:
184      VIXL_UNREACHABLE();
185      type_ = 0x0;
186      break;
187  }
188}
189
190class Dt_L_imm6_2 : public EncodingValue {
191  uint32_t type_;
192
193 public:
194  explicit Dt_L_imm6_2(DataType dt);
195  uint32_t GetTypeEncodingValue() const { return type_; }
196};
197
198Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
199  switch (dt.GetValue()) {
200    case S8:
201      type_ = 0x1;
202      SetEncodingValue(0x1);
203      break;
204    case S16:
205      type_ = 0x1;
206      SetEncodingValue(0x2);
207      break;
208    case S32:
209      type_ = 0x1;
210      SetEncodingValue(0x4);
211      break;
212    case S64:
213      type_ = 0x1;
214      SetEncodingValue(0x8);
215      break;
216    default:
217      VIXL_UNREACHABLE();
218      type_ = 0x0;
219      break;
220  }
221}
222
223class Dt_L_imm6_3 : public EncodingValue {
224 public:
225  explicit Dt_L_imm6_3(DataType dt);
226};
227
228Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
229  switch (dt.GetValue()) {
230    case I8:
231      SetEncodingValue(0x1);
232      break;
233    case I16:
234      SetEncodingValue(0x2);
235      break;
236    case I32:
237      SetEncodingValue(0x4);
238      break;
239    case I64:
240      SetEncodingValue(0x8);
241      break;
242    default:
243      break;
244  }
245}
246
247class Dt_L_imm6_4 : public EncodingValue {
248 public:
249  explicit Dt_L_imm6_4(DataType dt);
250};
251
252Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
253  switch (dt.GetValue()) {
254    case Untyped8:
255      SetEncodingValue(0x1);
256      break;
257    case Untyped16:
258      SetEncodingValue(0x2);
259      break;
260    case Untyped32:
261      SetEncodingValue(0x4);
262      break;
263    case Untyped64:
264      SetEncodingValue(0x8);
265      break;
266    default:
267      break;
268  }
269}
270
271class Dt_imm6_1 : public EncodingValue {
272  uint32_t type_;
273
274 public:
275  explicit Dt_imm6_1(DataType dt);
276  uint32_t GetTypeEncodingValue() const { return type_; }
277};
278
279Dt_imm6_1::Dt_imm6_1(DataType dt) {
280  switch (dt.GetValue()) {
281    case S16:
282      type_ = 0x0;
283      SetEncodingValue(0x1);
284      break;
285    case U16:
286      type_ = 0x1;
287      SetEncodingValue(0x1);
288      break;
289    case S32:
290      type_ = 0x0;
291      SetEncodingValue(0x2);
292      break;
293    case U32:
294      type_ = 0x1;
295      SetEncodingValue(0x2);
296      break;
297    case S64:
298      type_ = 0x0;
299      SetEncodingValue(0x4);
300      break;
301    case U64:
302      type_ = 0x1;
303      SetEncodingValue(0x4);
304      break;
305    default:
306      VIXL_UNREACHABLE();
307      type_ = 0x0;
308      break;
309  }
310}
311
312class Dt_imm6_2 : public EncodingValue {
313  uint32_t type_;
314
315 public:
316  explicit Dt_imm6_2(DataType dt);
317  uint32_t GetTypeEncodingValue() const { return type_; }
318};
319
320Dt_imm6_2::Dt_imm6_2(DataType dt) {
321  switch (dt.GetValue()) {
322    case S16:
323      type_ = 0x1;
324      SetEncodingValue(0x1);
325      break;
326    case S32:
327      type_ = 0x1;
328      SetEncodingValue(0x2);
329      break;
330    case S64:
331      type_ = 0x1;
332      SetEncodingValue(0x4);
333      break;
334    default:
335      VIXL_UNREACHABLE();
336      type_ = 0x0;
337      break;
338  }
339}
340
341class Dt_imm6_3 : public EncodingValue {
342 public:
343  explicit Dt_imm6_3(DataType dt);
344};
345
346Dt_imm6_3::Dt_imm6_3(DataType dt) {
347  switch (dt.GetValue()) {
348    case I16:
349      SetEncodingValue(0x1);
350      break;
351    case I32:
352      SetEncodingValue(0x2);
353      break;
354    case I64:
355      SetEncodingValue(0x4);
356      break;
357    default:
358      break;
359  }
360}
361
362class Dt_imm6_4 : public EncodingValue {
363  uint32_t type_;
364
365 public:
366  explicit Dt_imm6_4(DataType dt);
367  uint32_t GetTypeEncodingValue() const { return type_; }
368};
369
370Dt_imm6_4::Dt_imm6_4(DataType dt) {
371  switch (dt.GetValue()) {
372    case S8:
373      type_ = 0x0;
374      SetEncodingValue(0x1);
375      break;
376    case U8:
377      type_ = 0x1;
378      SetEncodingValue(0x1);
379      break;
380    case S16:
381      type_ = 0x0;
382      SetEncodingValue(0x2);
383      break;
384    case U16:
385      type_ = 0x1;
386      SetEncodingValue(0x2);
387      break;
388    case S32:
389      type_ = 0x0;
390      SetEncodingValue(0x4);
391      break;
392    case U32:
393      type_ = 0x1;
394      SetEncodingValue(0x4);
395      break;
396    default:
397      VIXL_UNREACHABLE();
398      type_ = 0x0;
399      break;
400  }
401}
402
403class Dt_op_U_size_1 : public EncodingValue {
404 public:
405  explicit Dt_op_U_size_1(DataType dt);
406};
407
408Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
409  switch (dt.GetValue()) {
410    case S8:
411      SetEncodingValue(0x0);
412      break;
413    case S16:
414      SetEncodingValue(0x1);
415      break;
416    case S32:
417      SetEncodingValue(0x2);
418      break;
419    case U8:
420      SetEncodingValue(0x4);
421      break;
422    case U16:
423      SetEncodingValue(0x5);
424      break;
425    case U32:
426      SetEncodingValue(0x6);
427      break;
428    case P8:
429      SetEncodingValue(0x8);
430      break;
431    case P64:
432      SetEncodingValue(0xa);
433      break;
434    default:
435      break;
436  }
437}
438
439class Dt_op_size_1 : public EncodingValue {
440 public:
441  explicit Dt_op_size_1(DataType dt);
442};
443
444Dt_op_size_1::Dt_op_size_1(DataType dt) {
445  switch (dt.GetValue()) {
446    case I8:
447      SetEncodingValue(0x0);
448      break;
449    case I16:
450      SetEncodingValue(0x1);
451      break;
452    case I32:
453      SetEncodingValue(0x2);
454      break;
455    case P8:
456      SetEncodingValue(0x4);
457      break;
458    default:
459      break;
460  }
461}
462
463class Dt_op_size_2 : public EncodingValue {
464 public:
465  explicit Dt_op_size_2(DataType dt);
466};
467
468Dt_op_size_2::Dt_op_size_2(DataType dt) {
469  switch (dt.GetValue()) {
470    case S8:
471      SetEncodingValue(0x0);
472      break;
473    case S16:
474      SetEncodingValue(0x1);
475      break;
476    case S32:
477      SetEncodingValue(0x2);
478      break;
479    case U8:
480      SetEncodingValue(0x4);
481      break;
482    case U16:
483      SetEncodingValue(0x5);
484      break;
485    case U32:
486      SetEncodingValue(0x6);
487      break;
488    default:
489      break;
490  }
491}
492
493class Dt_op_size_3 : public EncodingValue {
494 public:
495  explicit Dt_op_size_3(DataType dt);
496};
497
498Dt_op_size_3::Dt_op_size_3(DataType dt) {
499  switch (dt.GetValue()) {
500    case S16:
501      SetEncodingValue(0x0);
502      break;
503    case S32:
504      SetEncodingValue(0x1);
505      break;
506    case S64:
507      SetEncodingValue(0x2);
508      break;
509    case U16:
510      SetEncodingValue(0x4);
511      break;
512    case U32:
513      SetEncodingValue(0x5);
514      break;
515    case U64:
516      SetEncodingValue(0x6);
517      break;
518    default:
519      break;
520  }
521}
522
523class Dt_U_imm3H_1 : public EncodingValue {
524 public:
525  explicit Dt_U_imm3H_1(DataType dt);
526};
527
528Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
529  switch (dt.GetValue()) {
530    case S8:
531      SetEncodingValue(0x1);
532      break;
533    case S16:
534      SetEncodingValue(0x2);
535      break;
536    case S32:
537      SetEncodingValue(0x4);
538      break;
539    case U8:
540      SetEncodingValue(0x9);
541      break;
542    case U16:
543      SetEncodingValue(0xa);
544      break;
545    case U32:
546      SetEncodingValue(0xc);
547      break;
548    default:
549      break;
550  }
551}
552
553class Dt_U_opc1_opc2_1 : public EncodingValue {
554 public:
555  explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
556};
557
558Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
559  switch (dt.GetValue()) {
560    case S8:
561      if ((lane.GetLane() & 7) != lane.GetLane()) {
562        return;
563      }
564      SetEncodingValue(0x8 | lane.GetLane());
565      break;
566    case S16:
567      if ((lane.GetLane() & 3) != lane.GetLane()) {
568        return;
569      }
570      SetEncodingValue(0x1 | (lane.GetLane() << 1));
571      break;
572    case U8:
573      if ((lane.GetLane() & 7) != lane.GetLane()) {
574        return;
575      }
576      SetEncodingValue(0x18 | lane.GetLane());
577      break;
578    case U16:
579      if ((lane.GetLane() & 3) != lane.GetLane()) {
580        return;
581      }
582      SetEncodingValue(0x11 | (lane.GetLane() << 1));
583      break;
584    case Untyped32:
585      if ((lane.GetLane() & 1) != lane.GetLane()) {
586        return;
587      }
588      SetEncodingValue(0x0 | (lane.GetLane() << 2));
589      break;
590    case kDataTypeValueNone:
591      if ((lane.GetLane() & 1) != lane.GetLane()) {
592        return;
593      }
594      SetEncodingValue(0x0 | (lane.GetLane() << 2));
595      break;
596    default:
597      break;
598  }
599}
600
601class Dt_opc1_opc2_1 : public EncodingValue {
602 public:
603  explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
604};
605
606Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
607  switch (dt.GetValue()) {
608    case Untyped8:
609      if ((lane.GetLane() & 7) != lane.GetLane()) {
610        return;
611      }
612      SetEncodingValue(0x8 | lane.GetLane());
613      break;
614    case Untyped16:
615      if ((lane.GetLane() & 3) != lane.GetLane()) {
616        return;
617      }
618      SetEncodingValue(0x1 | (lane.GetLane() << 1));
619      break;
620    case Untyped32:
621      if ((lane.GetLane() & 1) != lane.GetLane()) {
622        return;
623      }
624      SetEncodingValue(0x0 | (lane.GetLane() << 2));
625      break;
626    case kDataTypeValueNone:
627      if ((lane.GetLane() & 1) != lane.GetLane()) {
628        return;
629      }
630      SetEncodingValue(0x0 | (lane.GetLane() << 2));
631      break;
632    default:
633      break;
634  }
635}
636
637class Dt_imm4_1 : public EncodingValue {
638 public:
639  explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
640};
641
642Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
643  switch (dt.GetValue()) {
644    case Untyped8:
645      if ((lane.GetLane() & 7) != lane.GetLane()) {
646        return;
647      }
648      SetEncodingValue(0x1 | (lane.GetLane() << 1));
649      break;
650    case Untyped16:
651      if ((lane.GetLane() & 3) != lane.GetLane()) {
652        return;
653      }
654      SetEncodingValue(0x2 | (lane.GetLane() << 2));
655      break;
656    case Untyped32:
657      if ((lane.GetLane() & 1) != lane.GetLane()) {
658        return;
659      }
660      SetEncodingValue(0x4 | (lane.GetLane() << 3));
661      break;
662    default:
663      break;
664  }
665}
666
667class Dt_B_E_1 : public EncodingValue {
668 public:
669  explicit Dt_B_E_1(DataType dt);
670};
671
672Dt_B_E_1::Dt_B_E_1(DataType dt) {
673  switch (dt.GetValue()) {
674    case Untyped8:
675      SetEncodingValue(0x2);
676      break;
677    case Untyped16:
678      SetEncodingValue(0x1);
679      break;
680    case Untyped32:
681      SetEncodingValue(0x0);
682      break;
683    default:
684      break;
685  }
686}
687
688class Dt_op_1 : public EncodingValue {
689 public:
690  Dt_op_1(DataType dt1, DataType dt2);
691};
692
693Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
694  if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
695    SetEncodingValue(0x0);
696    return;
697  }
698  if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
699    SetEncodingValue(0x1);
700    return;
701  }
702  if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
703    SetEncodingValue(0x2);
704    return;
705  }
706  if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
707    SetEncodingValue(0x3);
708    return;
709  }
710}
711
712class Dt_op_2 : public EncodingValue {
713 public:
714  explicit Dt_op_2(DataType dt);
715};
716
717Dt_op_2::Dt_op_2(DataType dt) {
718  switch (dt.GetValue()) {
719    case U32:
720      SetEncodingValue(0x0);
721      break;
722    case S32:
723      SetEncodingValue(0x1);
724      break;
725    default:
726      break;
727  }
728}
729
730class Dt_op_3 : public EncodingValue {
731 public:
732  explicit Dt_op_3(DataType dt);
733};
734
735Dt_op_3::Dt_op_3(DataType dt) {
736  switch (dt.GetValue()) {
737    case S32:
738      SetEncodingValue(0x0);
739      break;
740    case U32:
741      SetEncodingValue(0x1);
742      break;
743    default:
744      break;
745  }
746}
747
748class Dt_U_sx_1 : public EncodingValue {
749 public:
750  explicit Dt_U_sx_1(DataType dt);
751};
752
753Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
754  switch (dt.GetValue()) {
755    case S16:
756      SetEncodingValue(0x0);
757      break;
758    case S32:
759      SetEncodingValue(0x1);
760      break;
761    case U16:
762      SetEncodingValue(0x2);
763      break;
764    case U32:
765      SetEncodingValue(0x3);
766      break;
767    default:
768      break;
769  }
770}
771
772class Dt_op_U_1 : public EncodingValue {
773 public:
774  Dt_op_U_1(DataType dt1, DataType dt2);
775};
776
777Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
778  if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
779    SetEncodingValue(0x0);
780    return;
781  }
782  if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
783    SetEncodingValue(0x1);
784    return;
785  }
786  if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
787    SetEncodingValue(0x2);
788    return;
789  }
790  if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
791    SetEncodingValue(0x3);
792    return;
793  }
794}
795
796class Dt_sz_1 : public EncodingValue {
797 public:
798  explicit Dt_sz_1(DataType dt);
799};
800
801Dt_sz_1::Dt_sz_1(DataType dt) {
802  switch (dt.GetValue()) {
803    case F32:
804      SetEncodingValue(0x0);
805      break;
806    default:
807      break;
808  }
809}
810
811class Dt_F_size_1 : public EncodingValue {
812 public:
813  explicit Dt_F_size_1(DataType dt);
814};
815
816Dt_F_size_1::Dt_F_size_1(DataType dt) {
817  switch (dt.GetValue()) {
818    case S8:
819      SetEncodingValue(0x0);
820      break;
821    case S16:
822      SetEncodingValue(0x1);
823      break;
824    case S32:
825      SetEncodingValue(0x2);
826      break;
827    case F32:
828      SetEncodingValue(0x6);
829      break;
830    default:
831      break;
832  }
833}
834
835class Dt_F_size_2 : public EncodingValue {
836 public:
837  explicit Dt_F_size_2(DataType dt);
838};
839
840Dt_F_size_2::Dt_F_size_2(DataType dt) {
841  switch (dt.GetValue()) {
842    case I8:
843      SetEncodingValue(0x0);
844      break;
845    case I16:
846      SetEncodingValue(0x1);
847      break;
848    case I32:
849      SetEncodingValue(0x2);
850      break;
851    case F32:
852      SetEncodingValue(0x6);
853      break;
854    default:
855      break;
856  }
857}
858
859class Dt_F_size_3 : public EncodingValue {
860 public:
861  explicit Dt_F_size_3(DataType dt);
862};
863
864Dt_F_size_3::Dt_F_size_3(DataType dt) {
865  switch (dt.GetValue()) {
866    case I16:
867      SetEncodingValue(0x1);
868      break;
869    case I32:
870      SetEncodingValue(0x2);
871      break;
872    case F32:
873      SetEncodingValue(0x6);
874      break;
875    default:
876      break;
877  }
878}
879
880class Dt_F_size_4 : public EncodingValue {
881 public:
882  explicit Dt_F_size_4(DataType dt);
883};
884
885Dt_F_size_4::Dt_F_size_4(DataType dt) {
886  switch (dt.GetValue()) {
887    case U32:
888      SetEncodingValue(0x2);
889      break;
890    case F32:
891      SetEncodingValue(0x6);
892      break;
893    default:
894      break;
895  }
896}
897
898class Dt_U_size_1 : public EncodingValue {
899 public:
900  explicit Dt_U_size_1(DataType dt);
901};
902
903Dt_U_size_1::Dt_U_size_1(DataType dt) {
904  switch (dt.GetValue()) {
905    case S8:
906      SetEncodingValue(0x0);
907      break;
908    case S16:
909      SetEncodingValue(0x1);
910      break;
911    case S32:
912      SetEncodingValue(0x2);
913      break;
914    case U8:
915      SetEncodingValue(0x4);
916      break;
917    case U16:
918      SetEncodingValue(0x5);
919      break;
920    case U32:
921      SetEncodingValue(0x6);
922      break;
923    default:
924      break;
925  }
926}
927
928class Dt_U_size_2 : public EncodingValue {
929 public:
930  explicit Dt_U_size_2(DataType dt);
931};
932
933Dt_U_size_2::Dt_U_size_2(DataType dt) {
934  switch (dt.GetValue()) {
935    case S16:
936      SetEncodingValue(0x1);
937      break;
938    case S32:
939      SetEncodingValue(0x2);
940      break;
941    case U16:
942      SetEncodingValue(0x5);
943      break;
944    case U32:
945      SetEncodingValue(0x6);
946      break;
947    default:
948      break;
949  }
950}
951
952class Dt_U_size_3 : public EncodingValue {
953 public:
954  explicit Dt_U_size_3(DataType dt);
955};
956
957Dt_U_size_3::Dt_U_size_3(DataType dt) {
958  switch (dt.GetValue()) {
959    case S8:
960      SetEncodingValue(0x0);
961      break;
962    case S16:
963      SetEncodingValue(0x1);
964      break;
965    case S32:
966      SetEncodingValue(0x2);
967      break;
968    case S64:
969      SetEncodingValue(0x3);
970      break;
971    case U8:
972      SetEncodingValue(0x4);
973      break;
974    case U16:
975      SetEncodingValue(0x5);
976      break;
977    case U32:
978      SetEncodingValue(0x6);
979      break;
980    case U64:
981      SetEncodingValue(0x7);
982      break;
983    default:
984      break;
985  }
986}
987
988class Dt_size_1 : public EncodingValue {
989 public:
990  explicit Dt_size_1(DataType dt);
991};
992
993Dt_size_1::Dt_size_1(DataType dt) {
994  switch (dt.GetValue()) {
995    case Untyped8:
996      SetEncodingValue(0x0);
997      break;
998    default:
999      break;
1000  }
1001}
1002
1003class Dt_size_2 : public EncodingValue {
1004 public:
1005  explicit Dt_size_2(DataType dt);
1006};
1007
1008Dt_size_2::Dt_size_2(DataType dt) {
1009  switch (dt.GetValue()) {
1010    case I8:
1011      SetEncodingValue(0x0);
1012      break;
1013    case I16:
1014      SetEncodingValue(0x1);
1015      break;
1016    case I32:
1017      SetEncodingValue(0x2);
1018      break;
1019    case I64:
1020      SetEncodingValue(0x3);
1021      break;
1022    default:
1023      break;
1024  }
1025}
1026
1027class Dt_size_3 : public EncodingValue {
1028 public:
1029  explicit Dt_size_3(DataType dt);
1030};
1031
1032Dt_size_3::Dt_size_3(DataType dt) {
1033  switch (dt.GetValue()) {
1034    case I16:
1035      SetEncodingValue(0x0);
1036      break;
1037    case I32:
1038      SetEncodingValue(0x1);
1039      break;
1040    case I64:
1041      SetEncodingValue(0x2);
1042      break;
1043    default:
1044      break;
1045  }
1046}
1047
1048class Dt_size_4 : public EncodingValue {
1049 public:
1050  explicit Dt_size_4(DataType dt);
1051};
1052
1053Dt_size_4::Dt_size_4(DataType dt) {
1054  switch (dt.GetValue()) {
1055    case I8:
1056      SetEncodingValue(0x0);
1057      break;
1058    case I16:
1059      SetEncodingValue(0x1);
1060      break;
1061    case I32:
1062      SetEncodingValue(0x2);
1063      break;
1064    default:
1065      break;
1066  }
1067}
1068
1069class Dt_size_5 : public EncodingValue {
1070 public:
1071  explicit Dt_size_5(DataType dt);
1072};
1073
1074Dt_size_5::Dt_size_5(DataType dt) {
1075  switch (dt.GetValue()) {
1076    case S8:
1077      SetEncodingValue(0x0);
1078      break;
1079    case S16:
1080      SetEncodingValue(0x1);
1081      break;
1082    case S32:
1083      SetEncodingValue(0x2);
1084      break;
1085    default:
1086      break;
1087  }
1088}
1089
1090class Dt_size_6 : public EncodingValue {
1091 public:
1092  explicit Dt_size_6(DataType dt);
1093};
1094
1095Dt_size_6::Dt_size_6(DataType dt) {
1096  switch (dt.GetValue()) {
1097    case Untyped8:
1098      SetEncodingValue(0x0);
1099      break;
1100    case Untyped16:
1101      SetEncodingValue(0x1);
1102      break;
1103    case Untyped32:
1104      SetEncodingValue(0x2);
1105      break;
1106    case Untyped64:
1107      SetEncodingValue(0x3);
1108      break;
1109    default:
1110      break;
1111  }
1112}
1113
1114class Dt_size_7 : public EncodingValue {
1115 public:
1116  explicit Dt_size_7(DataType dt);
1117};
1118
1119Dt_size_7::Dt_size_7(DataType dt) {
1120  switch (dt.GetValue()) {
1121    case Untyped8:
1122      SetEncodingValue(0x0);
1123      break;
1124    case Untyped16:
1125      SetEncodingValue(0x1);
1126      break;
1127    case Untyped32:
1128      SetEncodingValue(0x2);
1129      break;
1130    default:
1131      break;
1132  }
1133}
1134
1135class Dt_size_8 : public EncodingValue {
1136 public:
1137  Dt_size_8(DataType dt, Alignment align);
1138};
1139
1140Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
1141  switch (dt.GetValue()) {
1142    case Untyped8:
1143      SetEncodingValue(0x0);
1144      break;
1145    case Untyped16:
1146      SetEncodingValue(0x1);
1147      break;
1148    case Untyped32:
1149      if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
1150        SetEncodingValue(0x2);
1151      } else if (align.Is(k128BitAlign)) {
1152        SetEncodingValue(0x3);
1153      }
1154      break;
1155    default:
1156      break;
1157  }
1158}
1159
1160class Dt_size_9 : public EncodingValue {
1161  uint32_t type_;
1162
1163 public:
1164  explicit Dt_size_9(DataType dt);
1165  uint32_t GetTypeEncodingValue() const { return type_; }
1166};
1167
1168Dt_size_9::Dt_size_9(DataType dt) {
1169  switch (dt.GetValue()) {
1170    case I16:
1171      type_ = 0x0;
1172      SetEncodingValue(0x1);
1173      break;
1174    case I32:
1175      type_ = 0x0;
1176      SetEncodingValue(0x2);
1177      break;
1178    case F32:
1179      type_ = 0x1;
1180      SetEncodingValue(0x2);
1181      break;
1182    default:
1183      VIXL_UNREACHABLE();
1184      type_ = 0x0;
1185      break;
1186  }
1187}
1188
1189class Dt_size_10 : public EncodingValue {
1190 public:
1191  explicit Dt_size_10(DataType dt);
1192};
1193
1194Dt_size_10::Dt_size_10(DataType dt) {
1195  switch (dt.GetValue()) {
1196    case S8:
1197    case U8:
1198    case I8:
1199      SetEncodingValue(0x0);
1200      break;
1201    case S16:
1202    case U16:
1203    case I16:
1204      SetEncodingValue(0x1);
1205      break;
1206    case S32:
1207    case U32:
1208    case I32:
1209      SetEncodingValue(0x2);
1210      break;
1211    default:
1212      break;
1213  }
1214}
1215
1216class Dt_size_11 : public EncodingValue {
1217  uint32_t type_;
1218
1219 public:
1220  explicit Dt_size_11(DataType dt);
1221  uint32_t GetTypeEncodingValue() const { return type_; }
1222};
1223
1224Dt_size_11::Dt_size_11(DataType dt) {
1225  switch (dt.GetValue()) {
1226    case S16:
1227      type_ = 0x0;
1228      SetEncodingValue(0x1);
1229      break;
1230    case U16:
1231      type_ = 0x1;
1232      SetEncodingValue(0x1);
1233      break;
1234    case S32:
1235      type_ = 0x0;
1236      SetEncodingValue(0x2);
1237      break;
1238    case U32:
1239      type_ = 0x1;
1240      SetEncodingValue(0x2);
1241      break;
1242    default:
1243      VIXL_UNREACHABLE();
1244      type_ = 0x0;
1245      break;
1246  }
1247}
1248
1249class Dt_size_12 : public EncodingValue {
1250  uint32_t type_;
1251
1252 public:
1253  explicit Dt_size_12(DataType dt);
1254  uint32_t GetTypeEncodingValue() const { return type_; }
1255};
1256
1257Dt_size_12::Dt_size_12(DataType dt) {
1258  switch (dt.GetValue()) {
1259    case S8:
1260      type_ = 0x0;
1261      SetEncodingValue(0x0);
1262      break;
1263    case U8:
1264      type_ = 0x1;
1265      SetEncodingValue(0x0);
1266      break;
1267    case S16:
1268      type_ = 0x0;
1269      SetEncodingValue(0x1);
1270      break;
1271    case U16:
1272      type_ = 0x1;
1273      SetEncodingValue(0x1);
1274      break;
1275    case S32:
1276      type_ = 0x0;
1277      SetEncodingValue(0x2);
1278      break;
1279    case U32:
1280      type_ = 0x1;
1281      SetEncodingValue(0x2);
1282      break;
1283    default:
1284      VIXL_UNREACHABLE();
1285      type_ = 0x0;
1286      break;
1287  }
1288}
1289
1290class Dt_size_13 : public EncodingValue {
1291 public:
1292  explicit Dt_size_13(DataType dt);
1293};
1294
1295Dt_size_13::Dt_size_13(DataType dt) {
1296  switch (dt.GetValue()) {
1297    case S16:
1298      SetEncodingValue(0x1);
1299      break;
1300    case S32:
1301      SetEncodingValue(0x2);
1302      break;
1303    default:
1304      break;
1305  }
1306}
1307
1308class Dt_size_14 : public EncodingValue {
1309 public:
1310  explicit Dt_size_14(DataType dt);
1311};
1312
1313Dt_size_14::Dt_size_14(DataType dt) {
1314  switch (dt.GetValue()) {
1315    case S16:
1316      SetEncodingValue(0x0);
1317      break;
1318    case S32:
1319      SetEncodingValue(0x1);
1320      break;
1321    case S64:
1322      SetEncodingValue(0x2);
1323      break;
1324    default:
1325      break;
1326  }
1327}
1328
1329class Dt_size_15 : public EncodingValue {
1330 public:
1331  explicit Dt_size_15(DataType dt);
1332};
1333
1334Dt_size_15::Dt_size_15(DataType dt) {
1335  switch (dt.GetValue()) {
1336    case Untyped8:
1337      SetEncodingValue(0x0);
1338      break;
1339    case Untyped16:
1340      SetEncodingValue(0x1);
1341      break;
1342    default:
1343      break;
1344  }
1345}
1346
1347class Dt_size_16 : public EncodingValue {
1348 public:
1349  explicit Dt_size_16(DataType dt);
1350};
1351
1352Dt_size_16::Dt_size_16(DataType dt) {
1353  switch (dt.GetValue()) {
1354    case I8:
1355      SetEncodingValue(0x0);
1356      break;
1357    case I16:
1358      SetEncodingValue(0x1);
1359      break;
1360    case I32:
1361      SetEncodingValue(0x2);
1362      break;
1363    default:
1364      break;
1365  }
1366}
1367
1368class Index_1 : public EncodingValue {
1369 public:
1370  Index_1(const NeonRegisterList& nreglist, DataType dt);
1371};
1372
1373Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1374  switch (dt.GetValue()) {
1375    case Untyped8: {
1376      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1377        return;
1378      }
1379      uint32_t value = nreglist.GetTransferLane() << 1;
1380      if (!nreglist.IsSingleSpaced()) return;
1381      SetEncodingValue(value);
1382      break;
1383    }
1384    case Untyped16: {
1385      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1386        return;
1387      }
1388      uint32_t value = nreglist.GetTransferLane() << 2;
1389      if (nreglist.IsDoubleSpaced()) value |= 2;
1390      SetEncodingValue(value);
1391      break;
1392    }
1393    case Untyped32: {
1394      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1395        return;
1396      }
1397      uint32_t value = nreglist.GetTransferLane() << 3;
1398      if (nreglist.IsDoubleSpaced()) value |= 4;
1399      SetEncodingValue(value);
1400      break;
1401    }
1402    default:
1403      break;
1404  }
1405}
1406
1407class Align_index_align_1 : public EncodingValue {
1408 public:
1409  Align_index_align_1(Alignment align,
1410                      const NeonRegisterList& nreglist,
1411                      DataType dt);
1412};
1413
1414Align_index_align_1::Align_index_align_1(Alignment align,
1415                                         const NeonRegisterList& nreglist,
1416                                         DataType dt) {
1417  switch (dt.GetValue()) {
1418    case Untyped8: {
1419      uint32_t value;
1420      if (align.GetType() == kNoAlignment) {
1421        value = 0;
1422      } else {
1423        return;
1424      }
1425      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1426        return;
1427      }
1428      value |= nreglist.GetTransferLane() << 1;
1429      SetEncodingValue(value);
1430      break;
1431    }
1432    case Untyped16: {
1433      uint32_t value;
1434      if (align.GetType() == k16BitAlign) {
1435        value = 1;
1436      } else if (align.GetType() == kNoAlignment) {
1437        value = 0;
1438      } else {
1439        return;
1440      }
1441      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1442        return;
1443      }
1444      value |= nreglist.GetTransferLane() << 2;
1445      SetEncodingValue(value);
1446      break;
1447    }
1448    case Untyped32: {
1449      uint32_t value;
1450      if (align.GetType() == k32BitAlign) {
1451        value = 3;
1452      } else if (align.GetType() == kNoAlignment) {
1453        value = 0;
1454      } else {
1455        return;
1456      }
1457      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1458        return;
1459      }
1460      value |= nreglist.GetTransferLane() << 3;
1461      SetEncodingValue(value);
1462      break;
1463    }
1464    default:
1465      break;
1466  }
1467}
1468
1469class Align_index_align_2 : public EncodingValue {
1470 public:
1471  Align_index_align_2(Alignment align,
1472                      const NeonRegisterList& nreglist,
1473                      DataType dt);
1474};
1475
1476Align_index_align_2::Align_index_align_2(Alignment align,
1477                                         const NeonRegisterList& nreglist,
1478                                         DataType dt) {
1479  switch (dt.GetValue()) {
1480    case Untyped8: {
1481      uint32_t value;
1482      if (align.GetType() == k16BitAlign) {
1483        value = 1;
1484      } else if (align.GetType() == kNoAlignment) {
1485        value = 0;
1486      } else {
1487        return;
1488      }
1489      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1490        return;
1491      }
1492      value |= nreglist.GetTransferLane() << 1;
1493      if (!nreglist.IsSingleSpaced()) return;
1494      SetEncodingValue(value);
1495      break;
1496    }
1497    case Untyped16: {
1498      uint32_t value;
1499      if (align.GetType() == k32BitAlign) {
1500        value = 1;
1501      } else if (align.GetType() == kNoAlignment) {
1502        value = 0;
1503      } else {
1504        return;
1505      }
1506      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1507        return;
1508      }
1509      value |= nreglist.GetTransferLane() << 2;
1510      if (nreglist.IsDoubleSpaced()) value |= 2;
1511      SetEncodingValue(value);
1512      break;
1513    }
1514    case Untyped32: {
1515      uint32_t value;
1516      if (align.GetType() == k64BitAlign) {
1517        value = 1;
1518      } else if (align.GetType() == kNoAlignment) {
1519        value = 0;
1520      } else {
1521        return;
1522      }
1523      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1524        return;
1525      }
1526      value |= nreglist.GetTransferLane() << 3;
1527      if (nreglist.IsDoubleSpaced()) value |= 4;
1528      SetEncodingValue(value);
1529      break;
1530    }
1531    default:
1532      break;
1533  }
1534}
1535
1536class Align_index_align_3 : public EncodingValue {
1537 public:
1538  Align_index_align_3(Alignment align,
1539                      const NeonRegisterList& nreglist,
1540                      DataType dt);
1541};
1542
1543Align_index_align_3::Align_index_align_3(Alignment align,
1544                                         const NeonRegisterList& nreglist,
1545                                         DataType dt) {
1546  switch (dt.GetValue()) {
1547    case Untyped8: {
1548      uint32_t value;
1549      if (align.GetType() == k32BitAlign) {
1550        value = 1;
1551      } else if (align.GetType() == kNoAlignment) {
1552        value = 0;
1553      } else {
1554        return;
1555      }
1556      if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1557        return;
1558      }
1559      value |= nreglist.GetTransferLane() << 1;
1560      if (!nreglist.IsSingleSpaced()) return;
1561      SetEncodingValue(value);
1562      break;
1563    }
1564    case Untyped16: {
1565      uint32_t value;
1566      if (align.GetType() == k64BitAlign) {
1567        value = 1;
1568      } else if (align.GetType() == kNoAlignment) {
1569        value = 0;
1570      } else {
1571        return;
1572      }
1573      if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1574        return;
1575      }
1576      value |= nreglist.GetTransferLane() << 2;
1577      if (nreglist.IsDoubleSpaced()) value |= 2;
1578      SetEncodingValue(value);
1579      break;
1580    }
1581    case Untyped32: {
1582      uint32_t value;
1583      if (align.GetType() == k64BitAlign) {
1584        value = 1;
1585      } else if (align.GetType() == k128BitAlign) {
1586        value = 2;
1587      } else if (align.GetType() == kNoAlignment) {
1588        value = 0;
1589      } else {
1590        return;
1591      }
1592      if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1593        return;
1594      }
1595      value |= nreglist.GetTransferLane() << 3;
1596      if (nreglist.IsDoubleSpaced()) value |= 4;
1597      SetEncodingValue(value);
1598      break;
1599    }
1600    default:
1601      break;
1602  }
1603}
1604
1605class Align_a_1 : public EncodingValue {
1606 public:
1607  Align_a_1(Alignment align, DataType dt);
1608};
1609
1610Align_a_1::Align_a_1(Alignment align, DataType dt) {
1611  switch (align.GetType()) {
1612    case k16BitAlign:
1613      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1614      break;
1615    case k32BitAlign:
1616      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1617      break;
1618    case kNoAlignment:
1619      SetEncodingValue(0x0);
1620      break;
1621    default:
1622      break;
1623  }
1624}
1625
1626class Align_a_2 : public EncodingValue {
1627 public:
1628  Align_a_2(Alignment align, DataType dt);
1629};
1630
1631Align_a_2::Align_a_2(Alignment align, DataType dt) {
1632  switch (align.GetType()) {
1633    case k16BitAlign:
1634      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1635      break;
1636    case k32BitAlign:
1637      if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1638      break;
1639    case k64BitAlign:
1640      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1641      break;
1642    case kNoAlignment:
1643      SetEncodingValue(0x0);
1644      break;
1645    default:
1646      break;
1647  }
1648}
1649
1650class Align_a_3 : public EncodingValue {
1651 public:
1652  Align_a_3(Alignment align, DataType dt);
1653};
1654
1655Align_a_3::Align_a_3(Alignment align, DataType dt) {
1656  switch (align.GetType()) {
1657    case k32BitAlign:
1658      if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1659      break;
1660    case k64BitAlign:
1661      if (dt.Is(Untyped16))
1662        SetEncodingValue(0x1);
1663      else if (dt.Is(Untyped32))
1664        SetEncodingValue(0x1);
1665      break;
1666    case k128BitAlign:
1667      if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1668      break;
1669    case kNoAlignment:
1670      SetEncodingValue(0x0);
1671      break;
1672    default:
1673      break;
1674  }
1675}
1676
1677class Align_align_1 : public EncodingValue {
1678 public:
1679  Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1680};
1681
1682Align_align_1::Align_align_1(Alignment align,
1683                             const NeonRegisterList& nreglist) {
1684  switch (align.GetType()) {
1685    case k64BitAlign:
1686      SetEncodingValue(0x1);
1687      break;
1688    case k128BitAlign:
1689      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1690        SetEncodingValue(0x2);
1691      break;
1692    case k256BitAlign:
1693      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1694        SetEncodingValue(0x3);
1695      break;
1696    case kNoAlignment:
1697      SetEncodingValue(0x0);
1698      break;
1699    default:
1700      break;
1701  }
1702}
1703
1704class Align_align_2 : public EncodingValue {
1705 public:
1706  Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1707};
1708
1709Align_align_2::Align_align_2(Alignment align,
1710                             const NeonRegisterList& nreglist) {
1711  switch (align.GetType()) {
1712    case k64BitAlign:
1713      SetEncodingValue(0x1);
1714      break;
1715    case k128BitAlign:
1716      SetEncodingValue(0x2);
1717      break;
1718    case k256BitAlign:
1719      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1720      break;
1721    case kNoAlignment:
1722      SetEncodingValue(0x0);
1723      break;
1724    default:
1725      break;
1726  }
1727}
1728
1729class Align_align_3 : public EncodingValue {
1730 public:
1731  explicit Align_align_3(Alignment align);
1732};
1733
1734Align_align_3::Align_align_3(Alignment align) {
1735  switch (align.GetType()) {
1736    case k64BitAlign:
1737      SetEncodingValue(0x1);
1738      break;
1739    case kNoAlignment:
1740      SetEncodingValue(0x0);
1741      break;
1742    default:
1743      break;
1744  }
1745}
1746
1747class Align_align_4 : public EncodingValue {
1748 public:
1749  explicit Align_align_4(Alignment align);
1750};
1751
1752Align_align_4::Align_align_4(Alignment align) {
1753  switch (align.GetType()) {
1754    case k64BitAlign:
1755      SetEncodingValue(0x1);
1756      break;
1757    case k128BitAlign:
1758      SetEncodingValue(0x2);
1759      break;
1760    case k256BitAlign:
1761      SetEncodingValue(0x3);
1762      break;
1763    case kNoAlignment:
1764      SetEncodingValue(0x0);
1765      break;
1766    default:
1767      break;
1768  }
1769}
1770
1771class Align_align_5 : public EncodingValue {
1772 public:
1773  Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1774};
1775
1776Align_align_5::Align_align_5(Alignment align,
1777                             const NeonRegisterList& nreglist) {
1778  switch (align.GetType()) {
1779    case k64BitAlign:
1780      SetEncodingValue(0x1);
1781      break;
1782    case k128BitAlign:
1783      if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1784        SetEncodingValue(0x2);
1785      break;
1786    case k256BitAlign:
1787      if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1788      break;
1789    case kNoAlignment:
1790      SetEncodingValue(0x0);
1791      break;
1792    default:
1793      break;
1794  }
1795}
1796
1797
1798void Assembler::adc(Condition cond,
1799                    EncodingSize size,
1800                    Register rd,
1801                    Register rn,
1802                    const Operand& operand) {
1803  VIXL_ASSERT(AllowAssembler());
1804  CheckIT(cond);
1805  if (operand.IsImmediate()) {
1806    uint32_t imm = operand.GetImmediate();
1807    if (IsUsingT32()) {
1808      ImmediateT32 immediate_t32(imm);
1809      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1810      if (!size.IsNarrow() && immediate_t32.IsValid() &&
1811          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
1812        EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1813                   (immediate_t32.GetEncodingValue() & 0xff) |
1814                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1815                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1816        AdvanceIT();
1817        return;
1818      }
1819    } else {
1820      ImmediateA32 immediate_a32(imm);
1821      // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1822      if (immediate_a32.IsValid() && cond.IsNotNever()) {
1823        EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1824                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1825                immediate_a32.GetEncodingValue());
1826        return;
1827      }
1828    }
1829  }
1830  if (operand.IsImmediateShiftedRegister()) {
1831    Register rm = operand.GetBaseRegister();
1832    if (operand.IsPlainRegister()) {
1833      if (IsUsingT32()) {
1834        // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1835        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1836            rm.IsLow()) {
1837          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1838          AdvanceIT();
1839          return;
1840        }
1841      }
1842    }
1843    Shift shift = operand.GetShift();
1844    uint32_t amount = operand.GetShiftAmount();
1845    if (IsUsingT32()) {
1846      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1847      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1848          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
1849        uint32_t amount_ = amount % 32;
1850        EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1851                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1852                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1853        AdvanceIT();
1854        return;
1855      }
1856    } else {
1857      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1858      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1859        uint32_t amount_ = amount % 32;
1860        EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1861                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1862                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1863        return;
1864      }
1865    }
1866  }
1867  if (operand.IsRegisterShiftedRegister()) {
1868    Register rm = operand.GetBaseRegister();
1869    Shift shift = operand.GetShift();
1870    if (IsUsingA32()) {
1871      // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1872      if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
1873                                 !operand.GetShiftRegister().IsPC()) ||
1874                                AllowUnpredictable())) {
1875        EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
1876                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1877                (shift.GetType() << 5) |
1878                (operand.GetShiftRegister().GetCode() << 8));
1879        return;
1880      }
1881    }
1882  }
1883  Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
1884}
1885
1886void Assembler::adcs(Condition cond,
1887                     EncodingSize size,
1888                     Register rd,
1889                     Register rn,
1890                     const Operand& operand) {
1891  VIXL_ASSERT(AllowAssembler());
1892  CheckIT(cond);
1893  if (operand.IsImmediate()) {
1894    uint32_t imm = operand.GetImmediate();
1895    if (IsUsingT32()) {
1896      ImmediateT32 immediate_t32(imm);
1897      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1898      if (!size.IsNarrow() && immediate_t32.IsValid() &&
1899          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
1900        EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1901                   (immediate_t32.GetEncodingValue() & 0xff) |
1902                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1903                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1904        AdvanceIT();
1905        return;
1906      }
1907    } else {
1908      ImmediateA32 immediate_a32(imm);
1909      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1910      if (immediate_a32.IsValid() && cond.IsNotNever()) {
1911        EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
1912                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1913                immediate_a32.GetEncodingValue());
1914        return;
1915      }
1916    }
1917  }
1918  if (operand.IsImmediateShiftedRegister()) {
1919    Register rm = operand.GetBaseRegister();
1920    if (operand.IsPlainRegister()) {
1921      if (IsUsingT32()) {
1922        // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1923        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1924            rm.IsLow()) {
1925          EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1926          AdvanceIT();
1927          return;
1928        }
1929      }
1930    }
1931    Shift shift = operand.GetShift();
1932    uint32_t amount = operand.GetShiftAmount();
1933    if (IsUsingT32()) {
1934      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1935      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1936          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
1937        uint32_t amount_ = amount % 32;
1938        EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1939                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1940                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1941        AdvanceIT();
1942        return;
1943      }
1944    } else {
1945      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1946      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1947        uint32_t amount_ = amount % 32;
1948        EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
1949                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1950                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1951        return;
1952      }
1953    }
1954  }
1955  if (operand.IsRegisterShiftedRegister()) {
1956    Register rm = operand.GetBaseRegister();
1957    Shift shift = operand.GetShift();
1958    if (IsUsingA32()) {
1959      // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1960      if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
1961                                 !operand.GetShiftRegister().IsPC()) ||
1962                                AllowUnpredictable())) {
1963        EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
1964                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1965                (shift.GetType() << 5) |
1966                (operand.GetShiftRegister().GetCode() << 8));
1967        return;
1968      }
1969    }
1970  }
1971  Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
1972}
1973
1974void Assembler::add(Condition cond,
1975                    EncodingSize size,
1976                    Register rd,
1977                    Register rn,
1978                    const Operand& operand) {
1979  VIXL_ASSERT(AllowAssembler());
1980  CheckIT(cond);
1981  if (operand.IsImmediate()) {
1982    uint32_t imm = operand.GetImmediate();
1983    if (IsUsingT32()) {
1984      ImmediateT32 immediate_t32(imm);
1985      // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
1986      if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
1987          ((imm % 4) == 0)) {
1988        uint32_t imm_ = imm >> 2;
1989        EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
1990        AdvanceIT();
1991        return;
1992      }
1993      // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
1994      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
1995          (imm <= 7)) {
1996        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
1997        AdvanceIT();
1998        return;
1999      }
2000      // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2001      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2002          (imm <= 255)) {
2003        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2004        AdvanceIT();
2005        return;
2006      }
2007      // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
2008      if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
2009          ((imm % 4) == 0)) {
2010        uint32_t imm_ = imm >> 2;
2011        EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2012        AdvanceIT();
2013        return;
2014      }
2015      // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2016      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2017          ((imm % 4) == 0)) {
2018        uint32_t imm_ = imm >> 2;
2019        EmitT32_16(0xb000 | imm_);
2020        AdvanceIT();
2021        return;
2022      }
2023      // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2024      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
2025          (!rd.IsPC() || AllowUnpredictable())) {
2026        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2027                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2028        AdvanceIT();
2029        return;
2030      }
2031      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2032      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2033          ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
2034        EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2035                   (immediate_t32.GetEncodingValue() & 0xff) |
2036                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2037                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2038        AdvanceIT();
2039        return;
2040      }
2041      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2042      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
2043          (!rd.IsPC() || AllowUnpredictable())) {
2044        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2045                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2046        AdvanceIT();
2047        return;
2048      }
2049      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2050      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2051          (!rd.IsPC() || AllowUnpredictable())) {
2052        EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2053                   (immediate_t32.GetEncodingValue() & 0xff) |
2054                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2055                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2056        AdvanceIT();
2057        return;
2058      }
2059      // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2060      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
2061          (!rd.IsPC() || AllowUnpredictable())) {
2062        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2063                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2064        AdvanceIT();
2065        return;
2066      }
2067    } else {
2068      ImmediateA32 immediate_a32(imm);
2069      // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2070      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2071        EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2072                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2073        return;
2074      }
2075      // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2076      if (immediate_a32.IsValid() && cond.IsNotNever() &&
2077          ((rn.GetCode() & 0xd) != 0xd)) {
2078        EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2079                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2080                immediate_a32.GetEncodingValue());
2081        return;
2082      }
2083      // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2084      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2085        EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2086                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2087        return;
2088      }
2089    }
2090  }
2091  if (operand.IsImmediateShiftedRegister()) {
2092    Register rm = operand.GetBaseRegister();
2093    if (operand.IsPlainRegister()) {
2094      if (IsUsingT32()) {
2095        // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2096        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2097            rm.IsLow()) {
2098          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2099                     (rm.GetCode() << 6));
2100          AdvanceIT();
2101          return;
2102        }
2103        // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
2104        if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
2105            (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2106              (!rd.IsPC() || !rm.IsPC())) ||
2107             AllowUnpredictable())) {
2108          EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2109                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2110          AdvanceIT();
2111          return;
2112        }
2113        // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
2114        if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
2115            ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
2116             AllowUnpredictable())) {
2117          EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2118                     ((rd.GetCode() & 0x8) << 4));
2119          AdvanceIT();
2120          return;
2121        }
2122        // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2123        if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2124          EmitT32_16(0x4485 | (rm.GetCode() << 3));
2125          AdvanceIT();
2126          return;
2127        }
2128      }
2129    }
2130    Shift shift = operand.GetShift();
2131    uint32_t amount = operand.GetShiftAmount();
2132    if (IsUsingT32()) {
2133      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2134      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2135          ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2136        uint32_t amount_ = amount % 32;
2137        EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2138                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2139                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2140        AdvanceIT();
2141        return;
2142      }
2143      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2144      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2145          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2146        uint32_t amount_ = amount % 32;
2147        EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2148                   (operand.GetTypeEncodingValue() << 4) |
2149                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2150        AdvanceIT();
2151        return;
2152      }
2153    } else {
2154      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2155      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2156        uint32_t amount_ = amount % 32;
2157        EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2158                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2159                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2160        return;
2161      }
2162      // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2163      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2164        uint32_t amount_ = amount % 32;
2165        EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2166                (rd.GetCode() << 12) | rm.GetCode() |
2167                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2168        return;
2169      }
2170    }
2171  }
2172  if (operand.IsRegisterShiftedRegister()) {
2173    Register rm = operand.GetBaseRegister();
2174    Shift shift = operand.GetShift();
2175    if (IsUsingA32()) {
2176      // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2177      if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
2178                                 !operand.GetShiftRegister().IsPC()) ||
2179                                AllowUnpredictable())) {
2180        EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2181                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2182                (shift.GetType() << 5) |
2183                (operand.GetShiftRegister().GetCode() << 8));
2184        return;
2185      }
2186    }
2187  }
2188  Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2189}
2190
2191void Assembler::add(Condition cond, Register rd, const Operand& operand) {
2192  VIXL_ASSERT(AllowAssembler());
2193  CheckIT(cond);
2194  if (operand.IsImmediate()) {
2195    uint32_t imm = operand.GetImmediate();
2196    if (IsUsingT32()) {
2197      // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2198      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2199        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2200        AdvanceIT();
2201        return;
2202      }
2203    }
2204  }
2205  if (operand.IsPlainRegister()) {
2206    Register rm = operand.GetBaseRegister();
2207    if (IsUsingT32()) {
2208      // ADD<c>{<q>} <Rdn>, <Rm> ; T2
2209      if (InITBlock() && !rm.Is(sp) &&
2210          (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2211            (!rd.IsPC() || !rm.IsPC())) ||
2212           AllowUnpredictable())) {
2213        EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2214                   (rm.GetCode() << 3));
2215        AdvanceIT();
2216        return;
2217      }
2218    }
2219  }
2220  Delegate(kAdd, &Assembler::add, cond, rd, operand);
2221}
2222
2223void Assembler::adds(Condition cond,
2224                     EncodingSize size,
2225                     Register rd,
2226                     Register rn,
2227                     const Operand& operand) {
2228  VIXL_ASSERT(AllowAssembler());
2229  CheckIT(cond);
2230  if (operand.IsImmediate()) {
2231    uint32_t imm = operand.GetImmediate();
2232    if (IsUsingT32()) {
2233      ImmediateT32 immediate_t32(imm);
2234      // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2235      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2236          (imm <= 7)) {
2237        EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2238        AdvanceIT();
2239        return;
2240      }
2241      // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2242      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2243          (imm <= 255)) {
2244        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2245        AdvanceIT();
2246        return;
2247      }
2248      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2249      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2250          !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
2251        EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2252                   (immediate_t32.GetEncodingValue() & 0xff) |
2253                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2254                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2255        AdvanceIT();
2256        return;
2257      }
2258      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2259      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2260          !rd.Is(pc)) {
2261        EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2262                   (immediate_t32.GetEncodingValue() & 0xff) |
2263                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2264                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2265        AdvanceIT();
2266        return;
2267      }
2268    } else {
2269      ImmediateA32 immediate_a32(imm);
2270      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2271      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2272        EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2273                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2274                immediate_a32.GetEncodingValue());
2275        return;
2276      }
2277      // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2278      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2279        EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2280                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2281        return;
2282      }
2283    }
2284  }
2285  if (operand.IsImmediateShiftedRegister()) {
2286    Register rm = operand.GetBaseRegister();
2287    if (operand.IsPlainRegister()) {
2288      if (IsUsingT32()) {
2289        // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2290        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2291            rm.IsLow()) {
2292          EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2293                     (rm.GetCode() << 6));
2294          AdvanceIT();
2295          return;
2296        }
2297      }
2298    }
2299    Shift shift = operand.GetShift();
2300    uint32_t amount = operand.GetShiftAmount();
2301    if (IsUsingT32()) {
2302      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2303      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2304          !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
2305        uint32_t amount_ = amount % 32;
2306        EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2307                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2308                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2309        AdvanceIT();
2310        return;
2311      }
2312      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2313      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2314          !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
2315        uint32_t amount_ = amount % 32;
2316        EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2317                   (operand.GetTypeEncodingValue() << 4) |
2318                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2319        AdvanceIT();
2320        return;
2321      }
2322    } else {
2323      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2324      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2325        uint32_t amount_ = amount % 32;
2326        EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2327                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2328                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2329        return;
2330      }
2331      // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2332      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2333        uint32_t amount_ = amount % 32;
2334        EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2335                (rd.GetCode() << 12) | rm.GetCode() |
2336                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2337        return;
2338      }
2339    }
2340  }
2341  if (operand.IsRegisterShiftedRegister()) {
2342    Register rm = operand.GetBaseRegister();
2343    Shift shift = operand.GetShift();
2344    if (IsUsingA32()) {
2345      // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2346      if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
2347                                 !operand.GetShiftRegister().IsPC()) ||
2348                                AllowUnpredictable())) {
2349        EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2350                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2351                (shift.GetType() << 5) |
2352                (operand.GetShiftRegister().GetCode() << 8));
2353        return;
2354      }
2355    }
2356  }
2357  Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2358}
2359
2360void Assembler::adds(Register rd, const Operand& operand) {
2361  VIXL_ASSERT(AllowAssembler());
2362  CheckIT(al);
2363  if (operand.IsImmediate()) {
2364    uint32_t imm = operand.GetImmediate();
2365    if (IsUsingT32()) {
2366      // ADDS{<q>} <Rdn>, #<imm8> ; T2
2367      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2368        EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2369        AdvanceIT();
2370        return;
2371      }
2372    }
2373  }
2374  Delegate(kAdds, &Assembler::adds, rd, operand);
2375}
2376
2377void Assembler::addw(Condition cond,
2378                     Register rd,
2379                     Register rn,
2380                     const Operand& operand) {
2381  VIXL_ASSERT(AllowAssembler());
2382  CheckIT(cond);
2383  if (operand.IsImmediate()) {
2384    uint32_t imm = operand.GetImmediate();
2385    if (IsUsingT32()) {
2386      // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2387      if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2388        EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2389                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2390        AdvanceIT();
2391        return;
2392      }
2393      // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2394      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
2395          (!rd.IsPC() || AllowUnpredictable())) {
2396        EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2397                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2398        AdvanceIT();
2399        return;
2400      }
2401      // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2402      if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2403        EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2404                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2405        AdvanceIT();
2406        return;
2407      }
2408    }
2409  }
2410  Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2411}
2412
2413void Assembler::adr(Condition cond,
2414                    EncodingSize size,
2415                    Register rd,
2416                    Label* label) {
2417  VIXL_ASSERT(AllowAssembler());
2418  CheckIT(cond);
2419  Label::Offset offset =
2420      label->IsBound()
2421          ? label->GetLocation() -
2422                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2423          : 0;
2424  if (IsUsingT32()) {
2425    int32_t neg_offset = -offset;
2426    // ADR{<c>}{<q>} <Rd>, <label> ; T1
2427    if (!size.IsWide() && rd.IsLow() &&
2428        ((label->IsBound() && (offset >= 0) && (offset <= 1020) &&
2429          ((offset & 0x3) == 0)) ||
2430         (!label->IsBound() && size.IsNarrow()))) {
2431      static class EmitOp : public Label::LabelEmitOperator {
2432       public:
2433        EmitOp() : Label::LabelEmitOperator(0, 1020) {}
2434        virtual uint32_t Encode(uint32_t instr,
2435                                Label::Offset pc,
2436                                const Label* label) const VIXL_OVERRIDE {
2437          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2438          VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2439                      ((offset & 0x3) == 0));
2440          const int32_t target = offset >> 2;
2441          return instr | (target & 0xff);
2442        }
2443      } immop;
2444      EmitT32_16(Link(0xa000 | (rd.GetCode() << 8), label, immop));
2445      AdvanceIT();
2446      return;
2447    }
2448    // ADR{<c>}{<q>} <Rd>, <label> ; T2
2449    if (!size.IsNarrow() && label->IsBound() && (neg_offset > 0) &&
2450        (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
2451      EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2452                 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2453      AdvanceIT();
2454      return;
2455    }
2456    // ADR{<c>}{<q>} <Rd>, <label> ; T3
2457    if (!size.IsNarrow() &&
2458        (!label->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
2459        (!rd.IsPC() || AllowUnpredictable())) {
2460      static class EmitOp : public Label::LabelEmitOperator {
2461       public:
2462        EmitOp() : Label::LabelEmitOperator(0, 4095) {}
2463        virtual uint32_t Encode(uint32_t instr,
2464                                Label::Offset pc,
2465                                const Label* label) const VIXL_OVERRIDE {
2466          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2467          int32_t target;
2468          if ((offset >= 0) && (offset <= 4095) && !label->IsMinusZero()) {
2469            target = offset;
2470          } else {
2471            target = -offset;
2472            VIXL_ASSERT((target >= 0) && (target <= 4095));
2473            // Emit the T2 encoding.
2474            instr |= 0x00a00000;
2475          }
2476          return instr | (target & 0xff) | ((target & 0x700) << 4) |
2477                 ((target & 0x800) << 15);
2478        }
2479      } immop;
2480      EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8), label, immop));
2481      AdvanceIT();
2482      return;
2483    }
2484  } else {
2485    ImmediateA32 positive_immediate_a32(offset);
2486    ImmediateA32 negative_immediate_a32(-offset);
2487    // ADR{<c>}{<q>} <Rd>, <label> ; A1
2488    if ((!label->IsBound() || positive_immediate_a32.IsValid()) &&
2489        cond.IsNotNever()) {
2490      static class EmitOp : public Label::LabelEmitOperator {
2491       public:
2492        EmitOp() : Label::LabelEmitOperator(0, 255) {}
2493        virtual uint32_t Encode(uint32_t instr,
2494                                Label::Offset pc,
2495                                const Label* label) const VIXL_OVERRIDE {
2496          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2497          int32_t target;
2498          ImmediateA32 positive_immediate_a32(offset);
2499          if (positive_immediate_a32.IsValid()) {
2500            target = positive_immediate_a32.GetEncodingValue();
2501          } else {
2502            ImmediateA32 negative_immediate_a32(-offset);
2503            VIXL_ASSERT(negative_immediate_a32.IsValid());
2504            // Emit the A2 encoding.
2505            target = negative_immediate_a32.GetEncodingValue();
2506            instr = (instr & ~0x00f00000) | 0x00400000;
2507          }
2508          return instr | (target & 0xfff);
2509        }
2510      } immop;
2511      EmitA32(
2512          Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
2513               label,
2514               immop));
2515      return;
2516    }
2517    // ADR{<c>}{<q>} <Rd>, <label> ; A2
2518    if (label->IsBound() && negative_immediate_a32.IsValid() &&
2519        cond.IsNotNever()) {
2520      EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2521              negative_immediate_a32.GetEncodingValue());
2522      return;
2523    }
2524  }
2525  Delegate(kAdr, &Assembler::adr, cond, size, rd, label);
2526}
2527
2528void Assembler::and_(Condition cond,
2529                     EncodingSize size,
2530                     Register rd,
2531                     Register rn,
2532                     const Operand& operand) {
2533  VIXL_ASSERT(AllowAssembler());
2534  CheckIT(cond);
2535  if (operand.IsImmediate()) {
2536    uint32_t imm = operand.GetImmediate();
2537    if (IsUsingT32()) {
2538      ImmediateT32 immediate_t32(imm);
2539      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2540      if (!size.IsNarrow() && immediate_t32.IsValid()) {
2541        EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2542                   (immediate_t32.GetEncodingValue() & 0xff) |
2543                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2544                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2545        AdvanceIT();
2546        return;
2547      }
2548    } else {
2549      ImmediateA32 immediate_a32(imm);
2550      // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2551      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2552        EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2553                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2554                immediate_a32.GetEncodingValue());
2555        return;
2556      }
2557    }
2558  }
2559  if (operand.IsImmediateShiftedRegister()) {
2560    Register rm = operand.GetBaseRegister();
2561    if (operand.IsPlainRegister()) {
2562      if (IsUsingT32()) {
2563        // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2564        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2565            rm.IsLow()) {
2566          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2567          AdvanceIT();
2568          return;
2569        }
2570      }
2571    }
2572    Shift shift = operand.GetShift();
2573    uint32_t amount = operand.GetShiftAmount();
2574    if (IsUsingT32()) {
2575      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2576      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
2577        uint32_t amount_ = amount % 32;
2578        EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2579                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2580                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2581        AdvanceIT();
2582        return;
2583      }
2584    } else {
2585      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2586      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2587        uint32_t amount_ = amount % 32;
2588        EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2589                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2590                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2591        return;
2592      }
2593    }
2594  }
2595  if (operand.IsRegisterShiftedRegister()) {
2596    Register rm = operand.GetBaseRegister();
2597    Shift shift = operand.GetShift();
2598    if (IsUsingA32()) {
2599      // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2600      if (cond.IsNotNever()) {
2601        EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2602                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2603                (shift.GetType() << 5) |
2604                (operand.GetShiftRegister().GetCode() << 8));
2605        return;
2606      }
2607    }
2608  }
2609  Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2610}
2611
2612void Assembler::ands(Condition cond,
2613                     EncodingSize size,
2614                     Register rd,
2615                     Register rn,
2616                     const Operand& operand) {
2617  VIXL_ASSERT(AllowAssembler());
2618  CheckIT(cond);
2619  if (operand.IsImmediate()) {
2620    uint32_t imm = operand.GetImmediate();
2621    if (IsUsingT32()) {
2622      ImmediateT32 immediate_t32(imm);
2623      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2624      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc)) {
2625        EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2626                   (immediate_t32.GetEncodingValue() & 0xff) |
2627                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2628                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2629        AdvanceIT();
2630        return;
2631      }
2632    } else {
2633      ImmediateA32 immediate_a32(imm);
2634      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2635      if (immediate_a32.IsValid() && cond.IsNotNever()) {
2636        EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2637                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2638                immediate_a32.GetEncodingValue());
2639        return;
2640      }
2641    }
2642  }
2643  if (operand.IsImmediateShiftedRegister()) {
2644    Register rm = operand.GetBaseRegister();
2645    if (operand.IsPlainRegister()) {
2646      if (IsUsingT32()) {
2647        // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2648        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2649            rm.IsLow()) {
2650          EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2651          AdvanceIT();
2652          return;
2653        }
2654      }
2655    }
2656    Shift shift = operand.GetShift();
2657    uint32_t amount = operand.GetShiftAmount();
2658    if (IsUsingT32()) {
2659      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2660      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc)) {
2661        uint32_t amount_ = amount % 32;
2662        EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2663                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2664                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2665        AdvanceIT();
2666        return;
2667      }
2668    } else {
2669      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2670      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2671        uint32_t amount_ = amount % 32;
2672        EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2673                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2674                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2675        return;
2676      }
2677    }
2678  }
2679  if (operand.IsRegisterShiftedRegister()) {
2680    Register rm = operand.GetBaseRegister();
2681    Shift shift = operand.GetShift();
2682    if (IsUsingA32()) {
2683      // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2684      if (cond.IsNotNever()) {
2685        EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2686                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2687                (shift.GetType() << 5) |
2688                (operand.GetShiftRegister().GetCode() << 8));
2689        return;
2690      }
2691    }
2692  }
2693  Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2694}
2695
2696void Assembler::asr(Condition cond,
2697                    EncodingSize size,
2698                    Register rd,
2699                    Register rm,
2700                    const Operand& operand) {
2701  VIXL_ASSERT(AllowAssembler());
2702  CheckIT(cond);
2703  if (operand.IsImmediate()) {
2704    uint32_t imm = operand.GetImmediate();
2705    if (IsUsingT32()) {
2706      // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2707      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2708          (imm >= 1) && (imm <= 32)) {
2709        uint32_t amount_ = imm % 32;
2710        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2711                   (amount_ << 6));
2712        AdvanceIT();
2713        return;
2714      }
2715      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2716      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
2717        uint32_t amount_ = imm % 32;
2718        EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2719                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2720        AdvanceIT();
2721        return;
2722      }
2723    } else {
2724      // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2725      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2726        uint32_t amount_ = imm % 32;
2727        EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2728                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2729        return;
2730      }
2731    }
2732  }
2733  if (operand.IsPlainRegister()) {
2734    Register rs = operand.GetBaseRegister();
2735    if (IsUsingT32()) {
2736      // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2737      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2738          rs.IsLow()) {
2739        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2740        AdvanceIT();
2741        return;
2742      }
2743      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2744      if (!size.IsNarrow()) {
2745        EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2746                   rs.GetCode());
2747        AdvanceIT();
2748        return;
2749      }
2750    } else {
2751      // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2752      if (cond.IsNotNever()) {
2753        EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2754                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2755        return;
2756      }
2757    }
2758  }
2759  Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2760}
2761
2762void Assembler::asrs(Condition cond,
2763                     EncodingSize size,
2764                     Register rd,
2765                     Register rm,
2766                     const Operand& operand) {
2767  VIXL_ASSERT(AllowAssembler());
2768  CheckIT(cond);
2769  if (operand.IsImmediate()) {
2770    uint32_t imm = operand.GetImmediate();
2771    if (IsUsingT32()) {
2772      // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2773      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2774          (imm >= 1) && (imm <= 32)) {
2775        uint32_t amount_ = imm % 32;
2776        EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2777                   (amount_ << 6));
2778        AdvanceIT();
2779        return;
2780      }
2781      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2782      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
2783        uint32_t amount_ = imm % 32;
2784        EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2785                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2786        AdvanceIT();
2787        return;
2788      }
2789    } else {
2790      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2791      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2792        uint32_t amount_ = imm % 32;
2793        EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2794                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2795        return;
2796      }
2797    }
2798  }
2799  if (operand.IsPlainRegister()) {
2800    Register rs = operand.GetBaseRegister();
2801    if (IsUsingT32()) {
2802      // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2803      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2804          rs.IsLow()) {
2805        EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2806        AdvanceIT();
2807        return;
2808      }
2809      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2810      if (!size.IsNarrow()) {
2811        EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2812                   rs.GetCode());
2813        AdvanceIT();
2814        return;
2815      }
2816    } else {
2817      // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2818      if (cond.IsNotNever()) {
2819        EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
2820                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2821        return;
2822      }
2823    }
2824  }
2825  Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
2826}
2827
2828void Assembler::b(Condition cond, EncodingSize size, Label* label) {
2829  VIXL_ASSERT(AllowAssembler());
2830  Label::Offset offset =
2831      label->IsBound()
2832          ? label->GetLocation() -
2833                (GetCursorOffset() + GetArchitectureStatePCOffset())
2834          : 0;
2835  if (IsUsingT32()) {
2836    // B<c>{<q>} <label> ; T1
2837    if (OutsideITBlock() && !size.IsWide() &&
2838        ((label->IsBound() && (offset >= -256) && (offset <= 254) &&
2839          ((offset & 0x1) == 0)) ||
2840         (!label->IsBound() && size.IsNarrow())) &&
2841        !cond.Is(al) && cond.IsNotNever()) {
2842      static class EmitOp : public Label::LabelEmitOperator {
2843       public:
2844        EmitOp() : Label::LabelEmitOperator(-256, 254) {}
2845        virtual uint32_t Encode(uint32_t instr,
2846                                Label::Offset pc,
2847                                const Label* label) const VIXL_OVERRIDE {
2848          Label::Offset offset = label->GetLocation() - pc;
2849          VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
2850                      ((offset & 0x1) == 0));
2851          const int32_t target = offset >> 1;
2852          return instr | (target & 0xff);
2853        }
2854      } immop;
2855      EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8), label, immop));
2856      AdvanceIT();
2857      return;
2858    }
2859    // B{<c>}{<q>} <label> ; T2
2860    if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
2861        ((label->IsBound() && (offset >= -2048) && (offset <= 2046) &&
2862          ((offset & 0x1) == 0)) ||
2863         (!label->IsBound() && size.IsNarrow()))) {
2864      CheckIT(cond);
2865      static class EmitOp : public Label::LabelEmitOperator {
2866       public:
2867        EmitOp() : Label::LabelEmitOperator(-2048, 2046) {}
2868        virtual uint32_t Encode(uint32_t instr,
2869                                Label::Offset pc,
2870                                const Label* label) const VIXL_OVERRIDE {
2871          Label::Offset offset = label->GetLocation() - pc;
2872          VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
2873                      ((offset & 0x1) == 0));
2874          const int32_t target = offset >> 1;
2875          return instr | (target & 0x7ff);
2876        }
2877      } immop;
2878      EmitT32_16(Link(0xe000, label, immop));
2879      AdvanceIT();
2880      return;
2881    }
2882    // B<c>{<q>} <label> ; T3
2883    if (OutsideITBlock() && !size.IsNarrow() &&
2884        ((label->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
2885          ((offset & 0x1) == 0)) ||
2886         !label->IsBound()) &&
2887        !cond.Is(al) && cond.IsNotNever()) {
2888      static class EmitOp : public Label::LabelEmitOperator {
2889       public:
2890        EmitOp() : Label::LabelEmitOperator(-1048576, 1048574) {}
2891        virtual uint32_t Encode(uint32_t instr,
2892                                Label::Offset pc,
2893                                const Label* label) const VIXL_OVERRIDE {
2894          Label::Offset offset = label->GetLocation() - pc;
2895          VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
2896                      ((offset & 0x1) == 0));
2897          const int32_t target = offset >> 1;
2898          return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
2899                 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
2900                 ((target & 0x80000) << 7);
2901        }
2902      } immop;
2903      EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22), label, immop));
2904      AdvanceIT();
2905      return;
2906    }
2907    // B{<c>}{<q>} <label> ; T4
2908    if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
2909        ((label->IsBound() && (offset >= -16777216) && (offset <= 16777214) &&
2910          ((offset & 0x1) == 0)) ||
2911         !label->IsBound())) {
2912      CheckIT(cond);
2913      static class EmitOp : public Label::LabelEmitOperator {
2914       public:
2915        EmitOp() : Label::LabelEmitOperator(-16777216, 16777214) {}
2916        virtual uint32_t Encode(uint32_t instr,
2917                                Label::Offset pc,
2918                                const Label* label) const VIXL_OVERRIDE {
2919          Label::Offset offset = label->GetLocation() - pc;
2920          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
2921                      ((offset & 0x1) == 0));
2922          int32_t target = offset >> 1;
2923          uint32_t S = target & (1 << 23);
2924          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
2925          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
2926                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
2927                 ((target & 0x800000) << 3);
2928        }
2929      } immop;
2930      EmitT32_32(Link(0xf0009000U, label, immop));
2931      AdvanceIT();
2932      return;
2933    }
2934  } else {
2935    // B{<c>}{<q>} <label> ; A1
2936    if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554428) &&
2937          ((offset & 0x3) == 0)) ||
2938         !label->IsBound()) &&
2939        cond.IsNotNever()) {
2940      static class EmitOp : public Label::LabelEmitOperator {
2941       public:
2942        EmitOp() : Label::LabelEmitOperator(-33554432, 33554428) {}
2943        virtual uint32_t Encode(uint32_t instr,
2944                                Label::Offset pc,
2945                                const Label* label) const VIXL_OVERRIDE {
2946          Label::Offset offset = label->GetLocation() - pc;
2947          VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
2948                      ((offset & 0x3) == 0));
2949          const int32_t target = offset >> 2;
2950          return instr | (target & 0xffffff);
2951        }
2952      } immop;
2953      EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28), label, immop));
2954      return;
2955    }
2956  }
2957  Delegate(kB, &Assembler::b, cond, size, label);
2958}
2959
2960void Assembler::bfc(Condition cond,
2961                    Register rd,
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      // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
2970      if ((lsb <= 31) &&
2971          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2972        uint32_t msb = lsb + width - 1;
2973        EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
2974                   ((lsb & 0x1c) << 10) | msb);
2975        AdvanceIT();
2976        return;
2977      }
2978    } else {
2979      // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
2980      if ((lsb <= 31) && cond.IsNotNever() &&
2981          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2982        uint32_t msb = lsb + width - 1;
2983        EmitA32(0x07c0001fU | (cond.GetCondition() << 28) |
2984                (rd.GetCode() << 12) | (lsb << 7) | (msb << 16));
2985        return;
2986      }
2987    }
2988  }
2989  Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, operand);
2990}
2991
2992void Assembler::bfi(Condition cond,
2993                    Register rd,
2994                    Register rn,
2995                    uint32_t lsb,
2996                    const Operand& operand) {
2997  VIXL_ASSERT(AllowAssembler());
2998  CheckIT(cond);
2999  if (operand.IsImmediate()) {
3000    uint32_t width = operand.GetImmediate();
3001    if (IsUsingT32()) {
3002      // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
3003      if ((lsb <= 31) && !rn.Is(pc) &&
3004          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
3005        uint32_t msb = lsb + width - 1;
3006        EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3007                   ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
3008        AdvanceIT();
3009        return;
3010      }
3011    } else {
3012      // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
3013      if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
3014          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
3015        uint32_t msb = lsb + width - 1;
3016        EmitA32(0x07c00010U | (cond.GetCondition() << 28) |
3017                (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) | (msb << 16));
3018        return;
3019      }
3020    }
3021  }
3022  Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, operand);
3023}
3024
3025void Assembler::bic(Condition cond,
3026                    EncodingSize size,
3027                    Register rd,
3028                    Register rn,
3029                    const Operand& operand) {
3030  VIXL_ASSERT(AllowAssembler());
3031  CheckIT(cond);
3032  if (operand.IsImmediate()) {
3033    uint32_t imm = operand.GetImmediate();
3034    if (IsUsingT32()) {
3035      ImmediateT32 immediate_t32(imm);
3036      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3037      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3038        EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3039                   (immediate_t32.GetEncodingValue() & 0xff) |
3040                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3041                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3042        AdvanceIT();
3043        return;
3044      }
3045    } else {
3046      ImmediateA32 immediate_a32(imm);
3047      // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3048      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3049        EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3050                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3051                immediate_a32.GetEncodingValue());
3052        return;
3053      }
3054    }
3055  }
3056  if (operand.IsImmediateShiftedRegister()) {
3057    Register rm = operand.GetBaseRegister();
3058    if (operand.IsPlainRegister()) {
3059      if (IsUsingT32()) {
3060        // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3061        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3062            rm.IsLow()) {
3063          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3064          AdvanceIT();
3065          return;
3066        }
3067      }
3068    }
3069    Shift shift = operand.GetShift();
3070    uint32_t amount = operand.GetShiftAmount();
3071    if (IsUsingT32()) {
3072      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3073      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3074        uint32_t amount_ = amount % 32;
3075        EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3076                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3077                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3078        AdvanceIT();
3079        return;
3080      }
3081    } else {
3082      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3083      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3084        uint32_t amount_ = amount % 32;
3085        EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3086                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3087                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3088        return;
3089      }
3090    }
3091  }
3092  if (operand.IsRegisterShiftedRegister()) {
3093    Register rm = operand.GetBaseRegister();
3094    Shift shift = operand.GetShift();
3095    if (IsUsingA32()) {
3096      // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3097      if (cond.IsNotNever()) {
3098        EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3099                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3100                (shift.GetType() << 5) |
3101                (operand.GetShiftRegister().GetCode() << 8));
3102        return;
3103      }
3104    }
3105  }
3106  Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3107}
3108
3109void Assembler::bics(Condition cond,
3110                     EncodingSize size,
3111                     Register rd,
3112                     Register rn,
3113                     const Operand& operand) {
3114  VIXL_ASSERT(AllowAssembler());
3115  CheckIT(cond);
3116  if (operand.IsImmediate()) {
3117    uint32_t imm = operand.GetImmediate();
3118    if (IsUsingT32()) {
3119      ImmediateT32 immediate_t32(imm);
3120      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3121      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3122        EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3123                   (immediate_t32.GetEncodingValue() & 0xff) |
3124                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3125                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3126        AdvanceIT();
3127        return;
3128      }
3129    } else {
3130      ImmediateA32 immediate_a32(imm);
3131      // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3132      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3133        EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3134                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3135                immediate_a32.GetEncodingValue());
3136        return;
3137      }
3138    }
3139  }
3140  if (operand.IsImmediateShiftedRegister()) {
3141    Register rm = operand.GetBaseRegister();
3142    if (operand.IsPlainRegister()) {
3143      if (IsUsingT32()) {
3144        // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3145        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3146            rm.IsLow()) {
3147          EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3148          AdvanceIT();
3149          return;
3150        }
3151      }
3152    }
3153    Shift shift = operand.GetShift();
3154    uint32_t amount = operand.GetShiftAmount();
3155    if (IsUsingT32()) {
3156      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3157      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3158        uint32_t amount_ = amount % 32;
3159        EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3160                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3161                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3162        AdvanceIT();
3163        return;
3164      }
3165    } else {
3166      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3167      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3168        uint32_t amount_ = amount % 32;
3169        EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3170                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3171                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3172        return;
3173      }
3174    }
3175  }
3176  if (operand.IsRegisterShiftedRegister()) {
3177    Register rm = operand.GetBaseRegister();
3178    Shift shift = operand.GetShift();
3179    if (IsUsingA32()) {
3180      // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3181      if (cond.IsNotNever()) {
3182        EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3183                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3184                (shift.GetType() << 5) |
3185                (operand.GetShiftRegister().GetCode() << 8));
3186        return;
3187      }
3188    }
3189  }
3190  Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3191}
3192
3193void Assembler::bkpt(Condition cond, uint32_t imm) {
3194  VIXL_ASSERT(AllowAssembler());
3195  CheckIT(cond);
3196  if (IsUsingT32()) {
3197    // BKPT{<q>} {#}<imm> ; T1
3198    if ((imm <= 255)) {
3199      EmitT32_16(0xbe00 | imm);
3200      AdvanceIT();
3201      return;
3202    }
3203  } else {
3204    // BKPT{<q>} {#}<imm> ; A1
3205    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3206      EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3207              ((imm & 0xfff0) << 4));
3208      return;
3209    }
3210  }
3211  Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3212}
3213
3214void Assembler::bl(Condition cond, Label* label) {
3215  VIXL_ASSERT(AllowAssembler());
3216  CheckIT(cond);
3217  Label::Offset offset =
3218      label->IsBound()
3219          ? label->GetLocation() -
3220                (GetCursorOffset() + GetArchitectureStatePCOffset())
3221          : 0;
3222  if (IsUsingT32()) {
3223    // BL{<c>}{<q>} <label> ; T1
3224    if (((label->IsBound() && (offset >= -16777216) && (offset <= 16777214) &&
3225          ((offset & 0x1) == 0)) ||
3226         !label->IsBound())) {
3227      static class EmitOp : public Label::LabelEmitOperator {
3228       public:
3229        EmitOp() : Label::LabelEmitOperator(-16777216, 16777214) {}
3230        virtual uint32_t Encode(uint32_t instr,
3231                                Label::Offset pc,
3232                                const Label* label) const VIXL_OVERRIDE {
3233          Label::Offset offset = label->GetLocation() - pc;
3234          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3235                      ((offset & 0x1) == 0));
3236          int32_t target = offset >> 1;
3237          uint32_t S = target & (1 << 23);
3238          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3239          return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3240                 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3241                 ((target & 0x800000) << 3);
3242        }
3243      } immop;
3244      EmitT32_32(Link(0xf000d000U, label, immop));
3245      AdvanceIT();
3246      return;
3247    }
3248  } else {
3249    // BL{<c>}{<q>} <label> ; A1
3250    if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554428) &&
3251          ((offset & 0x3) == 0)) ||
3252         !label->IsBound()) &&
3253        cond.IsNotNever()) {
3254      static class EmitOp : public Label::LabelEmitOperator {
3255       public:
3256        EmitOp() : Label::LabelEmitOperator(-33554432, 33554428) {}
3257        virtual uint32_t Encode(uint32_t instr,
3258                                Label::Offset pc,
3259                                const Label* label) const VIXL_OVERRIDE {
3260          Label::Offset offset = label->GetLocation() - pc;
3261          VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3262                      ((offset & 0x3) == 0));
3263          const int32_t target = offset >> 2;
3264          return instr | (target & 0xffffff);
3265        }
3266      } immop;
3267      EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28), label, immop));
3268      return;
3269    }
3270  }
3271  Delegate(kBl, &Assembler::bl, cond, label);
3272}
3273
3274void Assembler::blx(Condition cond, Label* label) {
3275  VIXL_ASSERT(AllowAssembler());
3276  CheckIT(cond);
3277  Label::Offset offset =
3278      label->IsBound()
3279          ? label->GetLocation() -
3280                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3281          : 0;
3282  if (IsUsingT32()) {
3283    // BLX{<c>}{<q>} <label> ; T2
3284    if (((label->IsBound() && (offset >= -16777216) && (offset <= 16777212) &&
3285          ((offset & 0x3) == 0)) ||
3286         !label->IsBound())) {
3287      static class EmitOp : public Label::LabelEmitOperator {
3288       public:
3289        EmitOp() : Label::LabelEmitOperator(-16777216, 16777212) {}
3290        virtual uint32_t Encode(uint32_t instr,
3291                                Label::Offset pc,
3292                                const Label* label) const VIXL_OVERRIDE {
3293          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
3294          VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3295                      ((offset & 0x3) == 0));
3296          int32_t target = offset >> 2;
3297          uint32_t S = target & (1 << 22);
3298          target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3299          return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3300                 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3301                 ((target & 0x400000) << 4);
3302        }
3303      } immop;
3304      EmitT32_32(Link(0xf000c000U, label, immop));
3305      AdvanceIT();
3306      return;
3307    }
3308  } else {
3309    // BLX{<c>}{<q>} <label> ; A2
3310    if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554430) &&
3311          ((offset & 0x1) == 0)) ||
3312         !label->IsBound())) {
3313      if (cond.Is(al) || AllowStronglyDiscouraged()) {
3314        static class EmitOp : public Label::LabelEmitOperator {
3315         public:
3316          EmitOp() : Label::LabelEmitOperator(-33554432, 33554430) {}
3317          virtual uint32_t Encode(uint32_t instr,
3318                                  Label::Offset pc,
3319                                  const Label* label) const VIXL_OVERRIDE {
3320            Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
3321            VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3322                        ((offset & 0x1) == 0));
3323            const int32_t target = offset >> 1;
3324            return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3325          }
3326        } immop;
3327        EmitA32(Link(0xfa000000U, label, immop));
3328        return;
3329      }
3330    }
3331  }
3332  Delegate(kBlx, &Assembler::blx, cond, label);
3333}
3334
3335void Assembler::blx(Condition cond, Register rm) {
3336  VIXL_ASSERT(AllowAssembler());
3337  CheckIT(cond);
3338  if (IsUsingT32()) {
3339    // BLX{<c>}{<q>} <Rm> ; T1
3340    EmitT32_16(0x4780 | (rm.GetCode() << 3));
3341    AdvanceIT();
3342    return;
3343  } else {
3344    // BLX{<c>}{<q>} <Rm> ; A1
3345    if (cond.IsNotNever()) {
3346      EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3347      return;
3348    }
3349  }
3350  Delegate(kBlx, &Assembler::blx, cond, rm);
3351}
3352
3353void Assembler::bx(Condition cond, Register rm) {
3354  VIXL_ASSERT(AllowAssembler());
3355  CheckIT(cond);
3356  if (IsUsingT32()) {
3357    // BX{<c>}{<q>} <Rm> ; T1
3358    EmitT32_16(0x4700 | (rm.GetCode() << 3));
3359    AdvanceIT();
3360    return;
3361  } else {
3362    // BX{<c>}{<q>} <Rm> ; A1
3363    if (cond.IsNotNever()) {
3364      EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3365      return;
3366    }
3367  }
3368  Delegate(kBx, &Assembler::bx, cond, rm);
3369}
3370
3371void Assembler::bxj(Condition cond, Register rm) {
3372  VIXL_ASSERT(AllowAssembler());
3373  CheckIT(cond);
3374  if (IsUsingT32()) {
3375    // BXJ{<c>}{<q>} <Rm> ; T1
3376    EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3377    AdvanceIT();
3378    return;
3379  } else {
3380    // BXJ{<c>}{<q>} <Rm> ; A1
3381    if (cond.IsNotNever()) {
3382      EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3383      return;
3384    }
3385  }
3386  Delegate(kBxj, &Assembler::bxj, cond, rm);
3387}
3388
3389void Assembler::cbnz(Register rn, Label* label) {
3390  VIXL_ASSERT(AllowAssembler());
3391  CheckIT(al);
3392  Label::Offset offset =
3393      label->IsBound()
3394          ? label->GetLocation() -
3395                (GetCursorOffset() + GetArchitectureStatePCOffset())
3396          : 0;
3397  if (IsUsingT32()) {
3398    // CBNZ{<q>} <Rn>, <label> ; T1
3399    if (rn.IsLow() && ((label->IsBound() && (offset >= 0) && (offset <= 126) &&
3400                        ((offset & 0x1) == 0)) ||
3401                       !label->IsBound())) {
3402      static class EmitOp : public Label::LabelEmitOperator {
3403       public:
3404        EmitOp() : Label::LabelEmitOperator(0, 126) {}
3405        virtual uint32_t Encode(uint32_t instr,
3406                                Label::Offset pc,
3407                                const Label* label) const VIXL_OVERRIDE {
3408          Label::Offset offset = label->GetLocation() - pc;
3409          VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3410                      ((offset & 0x1) == 0));
3411          const int32_t target = offset >> 1;
3412          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3413        }
3414      } immop;
3415      EmitT32_16(Link(0xb900 | rn.GetCode(), label, immop));
3416      AdvanceIT();
3417      return;
3418    }
3419  }
3420  Delegate(kCbnz, &Assembler::cbnz, rn, label);
3421}
3422
3423void Assembler::cbz(Register rn, Label* label) {
3424  VIXL_ASSERT(AllowAssembler());
3425  CheckIT(al);
3426  Label::Offset offset =
3427      label->IsBound()
3428          ? label->GetLocation() -
3429                (GetCursorOffset() + GetArchitectureStatePCOffset())
3430          : 0;
3431  if (IsUsingT32()) {
3432    // CBZ{<q>} <Rn>, <label> ; T1
3433    if (rn.IsLow() && ((label->IsBound() && (offset >= 0) && (offset <= 126) &&
3434                        ((offset & 0x1) == 0)) ||
3435                       !label->IsBound())) {
3436      static class EmitOp : public Label::LabelEmitOperator {
3437       public:
3438        EmitOp() : Label::LabelEmitOperator(0, 126) {}
3439        virtual uint32_t Encode(uint32_t instr,
3440                                Label::Offset pc,
3441                                const Label* label) const VIXL_OVERRIDE {
3442          Label::Offset offset = label->GetLocation() - pc;
3443          VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3444                      ((offset & 0x1) == 0));
3445          const int32_t target = offset >> 1;
3446          return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3447        }
3448      } immop;
3449      EmitT32_16(Link(0xb100 | rn.GetCode(), label, immop));
3450      AdvanceIT();
3451      return;
3452    }
3453  }
3454  Delegate(kCbz, &Assembler::cbz, rn, label);
3455}
3456
3457void Assembler::clrex(Condition cond) {
3458  VIXL_ASSERT(AllowAssembler());
3459  CheckIT(cond);
3460  if (IsUsingT32()) {
3461    // CLREX{<c>}{<q>} ; T1
3462    EmitT32_32(0xf3bf8f2fU);
3463    AdvanceIT();
3464    return;
3465  } else {
3466    // CLREX{<c>}{<q>} ; A1
3467    if (cond.Is(al)) {
3468      EmitA32(0xf57ff01fU);
3469      return;
3470    }
3471  }
3472  Delegate(kClrex, &Assembler::clrex, cond);
3473}
3474
3475void Assembler::clz(Condition cond, Register rd, Register rm) {
3476  VIXL_ASSERT(AllowAssembler());
3477  CheckIT(cond);
3478  if (IsUsingT32()) {
3479    // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
3480    if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3481      EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3482                 (rm.GetCode() << 16));
3483      AdvanceIT();
3484      return;
3485    }
3486  } else {
3487    // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
3488    if (cond.IsNotNever() &&
3489        ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3490      EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3491              rm.GetCode());
3492      return;
3493    }
3494  }
3495  Delegate(kClz, &Assembler::clz, cond, rd, rm);
3496}
3497
3498void Assembler::cmn(Condition cond,
3499                    EncodingSize size,
3500                    Register rn,
3501                    const Operand& operand) {
3502  VIXL_ASSERT(AllowAssembler());
3503  CheckIT(cond);
3504  if (operand.IsImmediate()) {
3505    uint32_t imm = operand.GetImmediate();
3506    if (IsUsingT32()) {
3507      ImmediateT32 immediate_t32(imm);
3508      // CMN{<c>}{<q>} <Rn>, #<const> ; T1
3509      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3510        EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3511                   (immediate_t32.GetEncodingValue() & 0xff) |
3512                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3513                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3514        AdvanceIT();
3515        return;
3516      }
3517    } else {
3518      ImmediateA32 immediate_a32(imm);
3519      // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3520      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3521        EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3522                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3523        return;
3524      }
3525    }
3526  }
3527  if (operand.IsImmediateShiftedRegister()) {
3528    Register rm = operand.GetBaseRegister();
3529    if (operand.IsPlainRegister()) {
3530      if (IsUsingT32()) {
3531        // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3532        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3533          EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3534          AdvanceIT();
3535          return;
3536        }
3537      }
3538    }
3539    Shift shift = operand.GetShift();
3540    uint32_t amount = operand.GetShiftAmount();
3541    if (IsUsingT32()) {
3542      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
3543      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3544        uint32_t amount_ = amount % 32;
3545        EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3546                   (operand.GetTypeEncodingValue() << 4) |
3547                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3548        AdvanceIT();
3549        return;
3550      }
3551    } else {
3552      // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3553      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3554        uint32_t amount_ = amount % 32;
3555        EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3556                (rn.GetCode() << 16) | rm.GetCode() |
3557                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3558        return;
3559      }
3560    }
3561  }
3562  if (operand.IsRegisterShiftedRegister()) {
3563    Register rm = operand.GetBaseRegister();
3564    Shift shift = operand.GetShift();
3565    if (IsUsingA32()) {
3566      // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3567      if (cond.IsNotNever()) {
3568        EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3569                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3570                (operand.GetShiftRegister().GetCode() << 8));
3571        return;
3572      }
3573    }
3574  }
3575  Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3576}
3577
3578void Assembler::cmp(Condition cond,
3579                    EncodingSize size,
3580                    Register rn,
3581                    const Operand& operand) {
3582  VIXL_ASSERT(AllowAssembler());
3583  CheckIT(cond);
3584  if (operand.IsImmediate()) {
3585    uint32_t imm = operand.GetImmediate();
3586    if (IsUsingT32()) {
3587      ImmediateT32 immediate_t32(imm);
3588      // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3589      if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3590        EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3591        AdvanceIT();
3592        return;
3593      }
3594      // CMP{<c>}{<q>} <Rn>, #<const> ; T2
3595      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3596        EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3597                   (immediate_t32.GetEncodingValue() & 0xff) |
3598                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3599                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3600        AdvanceIT();
3601        return;
3602      }
3603    } else {
3604      ImmediateA32 immediate_a32(imm);
3605      // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3606      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3607        EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3608                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3609        return;
3610      }
3611    }
3612  }
3613  if (operand.IsImmediateShiftedRegister()) {
3614    Register rm = operand.GetBaseRegister();
3615    if (operand.IsPlainRegister()) {
3616      if (IsUsingT32()) {
3617        // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3618        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3619          EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3620          AdvanceIT();
3621          return;
3622        }
3623        // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
3624        if (!size.IsWide()) {
3625          EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3626                     ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3627          AdvanceIT();
3628          return;
3629        }
3630      }
3631    }
3632    Shift shift = operand.GetShift();
3633    uint32_t amount = operand.GetShiftAmount();
3634    if (IsUsingT32()) {
3635      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
3636      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3637        uint32_t amount_ = amount % 32;
3638        EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3639                   (operand.GetTypeEncodingValue() << 4) |
3640                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3641        AdvanceIT();
3642        return;
3643      }
3644    } else {
3645      // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3646      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3647        uint32_t amount_ = amount % 32;
3648        EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3649                (rn.GetCode() << 16) | rm.GetCode() |
3650                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3651        return;
3652      }
3653    }
3654  }
3655  if (operand.IsRegisterShiftedRegister()) {
3656    Register rm = operand.GetBaseRegister();
3657    Shift shift = operand.GetShift();
3658    if (IsUsingA32()) {
3659      // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3660      if (cond.IsNotNever()) {
3661        EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3662                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3663                (operand.GetShiftRegister().GetCode() << 8));
3664        return;
3665      }
3666    }
3667  }
3668  Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
3669}
3670
3671void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
3672  VIXL_ASSERT(AllowAssembler());
3673  CheckIT(cond);
3674  if (IsUsingT32()) {
3675    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
3676    EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3677               rm.GetCode());
3678    AdvanceIT();
3679    return;
3680  } else {
3681    // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
3682    if ((cond.Is(al) || AllowUnpredictable())) {
3683      EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3684              (rn.GetCode() << 16) | rm.GetCode());
3685      return;
3686    }
3687  }
3688  Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
3689}
3690
3691void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
3692  VIXL_ASSERT(AllowAssembler());
3693  CheckIT(cond);
3694  if (IsUsingT32()) {
3695    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
3696    EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3697               rm.GetCode());
3698    AdvanceIT();
3699    return;
3700  } else {
3701    // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
3702    if ((cond.Is(al) || AllowUnpredictable())) {
3703      EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3704              (rn.GetCode() << 16) | rm.GetCode());
3705      return;
3706    }
3707  }
3708  Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
3709}
3710
3711void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
3712  VIXL_ASSERT(AllowAssembler());
3713  CheckIT(cond);
3714  if (IsUsingT32()) {
3715    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
3716    EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3717               rm.GetCode());
3718    AdvanceIT();
3719    return;
3720  } else {
3721    // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
3722    if ((cond.Is(al) || AllowUnpredictable())) {
3723      EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3724              (rn.GetCode() << 16) | rm.GetCode());
3725      return;
3726    }
3727  }
3728  Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
3729}
3730
3731void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
3732  VIXL_ASSERT(AllowAssembler());
3733  CheckIT(cond);
3734  if (IsUsingT32()) {
3735    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
3736    EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3737               rm.GetCode());
3738    AdvanceIT();
3739    return;
3740  } else {
3741    // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
3742    if ((cond.Is(al) || AllowUnpredictable())) {
3743      EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3744              (rn.GetCode() << 16) | rm.GetCode());
3745      return;
3746    }
3747  }
3748  Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
3749}
3750
3751void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
3752  VIXL_ASSERT(AllowAssembler());
3753  CheckIT(cond);
3754  if (IsUsingT32()) {
3755    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
3756    EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3757               rm.GetCode());
3758    AdvanceIT();
3759    return;
3760  } else {
3761    // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
3762    if ((cond.Is(al) || AllowUnpredictable())) {
3763      EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3764              (rn.GetCode() << 16) | rm.GetCode());
3765      return;
3766    }
3767  }
3768  Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
3769}
3770
3771void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
3772  VIXL_ASSERT(AllowAssembler());
3773  CheckIT(cond);
3774  if (IsUsingT32()) {
3775    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
3776    EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3777               rm.GetCode());
3778    AdvanceIT();
3779    return;
3780  } else {
3781    // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
3782    if ((cond.Is(al) || AllowUnpredictable())) {
3783      EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3784              (rn.GetCode() << 16) | rm.GetCode());
3785      return;
3786    }
3787  }
3788  Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
3789}
3790
3791void Assembler::dmb(Condition cond, MemoryBarrier option) {
3792  VIXL_ASSERT(AllowAssembler());
3793  CheckIT(cond);
3794  if (IsUsingT32()) {
3795    // DMB{<c>}{<q>} {<option>} ; T1
3796    EmitT32_32(0xf3bf8f50U | option.GetType());
3797    AdvanceIT();
3798    return;
3799  } else {
3800    // DMB{<c>}{<q>} {<option>} ; A1
3801    if (cond.Is(al)) {
3802      EmitA32(0xf57ff050U | option.GetType());
3803      return;
3804    }
3805  }
3806  Delegate(kDmb, &Assembler::dmb, cond, option);
3807}
3808
3809void Assembler::dsb(Condition cond, MemoryBarrier option) {
3810  VIXL_ASSERT(AllowAssembler());
3811  CheckIT(cond);
3812  if (IsUsingT32()) {
3813    // DSB{<c>}{<q>} {<option>} ; T1
3814    EmitT32_32(0xf3bf8f40U | option.GetType());
3815    AdvanceIT();
3816    return;
3817  } else {
3818    // DSB{<c>}{<q>} {<option>} ; A1
3819    if (cond.Is(al)) {
3820      EmitA32(0xf57ff040U | option.GetType());
3821      return;
3822    }
3823  }
3824  Delegate(kDsb, &Assembler::dsb, cond, option);
3825}
3826
3827void Assembler::eor(Condition cond,
3828                    EncodingSize size,
3829                    Register rd,
3830                    Register rn,
3831                    const Operand& operand) {
3832  VIXL_ASSERT(AllowAssembler());
3833  CheckIT(cond);
3834  if (operand.IsImmediate()) {
3835    uint32_t imm = operand.GetImmediate();
3836    if (IsUsingT32()) {
3837      ImmediateT32 immediate_t32(imm);
3838      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3839      if (!size.IsNarrow() && immediate_t32.IsValid()) {
3840        EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3841                   (immediate_t32.GetEncodingValue() & 0xff) |
3842                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3843                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3844        AdvanceIT();
3845        return;
3846      }
3847    } else {
3848      ImmediateA32 immediate_a32(imm);
3849      // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3850      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3851        EmitA32(0x02200000U | (cond.GetCondition() << 28) |
3852                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3853                immediate_a32.GetEncodingValue());
3854        return;
3855      }
3856    }
3857  }
3858  if (operand.IsImmediateShiftedRegister()) {
3859    Register rm = operand.GetBaseRegister();
3860    if (operand.IsPlainRegister()) {
3861      if (IsUsingT32()) {
3862        // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3863        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3864            rm.IsLow()) {
3865          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
3866          AdvanceIT();
3867          return;
3868        }
3869      }
3870    }
3871    Shift shift = operand.GetShift();
3872    uint32_t amount = operand.GetShiftAmount();
3873    if (IsUsingT32()) {
3874      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3875      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3876        uint32_t amount_ = amount % 32;
3877        EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3878                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3879                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3880        AdvanceIT();
3881        return;
3882      }
3883    } else {
3884      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3885      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3886        uint32_t amount_ = amount % 32;
3887        EmitA32(0x00200000U | (cond.GetCondition() << 28) |
3888                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3889                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3890        return;
3891      }
3892    }
3893  }
3894  if (operand.IsRegisterShiftedRegister()) {
3895    Register rm = operand.GetBaseRegister();
3896    Shift shift = operand.GetShift();
3897    if (IsUsingA32()) {
3898      // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3899      if (cond.IsNotNever()) {
3900        EmitA32(0x00200010U | (cond.GetCondition() << 28) |
3901                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3902                (shift.GetType() << 5) |
3903                (operand.GetShiftRegister().GetCode() << 8));
3904        return;
3905      }
3906    }
3907  }
3908  Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
3909}
3910
3911void Assembler::eors(Condition cond,
3912                     EncodingSize size,
3913                     Register rd,
3914                     Register rn,
3915                     const Operand& operand) {
3916  VIXL_ASSERT(AllowAssembler());
3917  CheckIT(cond);
3918  if (operand.IsImmediate()) {
3919    uint32_t imm = operand.GetImmediate();
3920    if (IsUsingT32()) {
3921      ImmediateT32 immediate_t32(imm);
3922      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3923      if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc)) {
3924        EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3925                   (immediate_t32.GetEncodingValue() & 0xff) |
3926                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3927                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3928        AdvanceIT();
3929        return;
3930      }
3931    } else {
3932      ImmediateA32 immediate_a32(imm);
3933      // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3934      if (immediate_a32.IsValid() && cond.IsNotNever()) {
3935        EmitA32(0x02300000U | (cond.GetCondition() << 28) |
3936                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3937                immediate_a32.GetEncodingValue());
3938        return;
3939      }
3940    }
3941  }
3942  if (operand.IsImmediateShiftedRegister()) {
3943    Register rm = operand.GetBaseRegister();
3944    if (operand.IsPlainRegister()) {
3945      if (IsUsingT32()) {
3946        // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3947        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3948            rm.IsLow()) {
3949          EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
3950          AdvanceIT();
3951          return;
3952        }
3953      }
3954    }
3955    Shift shift = operand.GetShift();
3956    uint32_t amount = operand.GetShiftAmount();
3957    if (IsUsingT32()) {
3958      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3959      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc)) {
3960        uint32_t amount_ = amount % 32;
3961        EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3962                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3963                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3964        AdvanceIT();
3965        return;
3966      }
3967    } else {
3968      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3969      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3970        uint32_t amount_ = amount % 32;
3971        EmitA32(0x00300000U | (cond.GetCondition() << 28) |
3972                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3973                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3974        return;
3975      }
3976    }
3977  }
3978  if (operand.IsRegisterShiftedRegister()) {
3979    Register rm = operand.GetBaseRegister();
3980    Shift shift = operand.GetShift();
3981    if (IsUsingA32()) {
3982      // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3983      if (cond.IsNotNever()) {
3984        EmitA32(0x00300010U | (cond.GetCondition() << 28) |
3985                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3986                (shift.GetType() << 5) |
3987                (operand.GetShiftRegister().GetCode() << 8));
3988        return;
3989      }
3990    }
3991  }
3992  Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
3993}
3994
3995void Assembler::fldmdbx(Condition cond,
3996                        Register rn,
3997                        WriteBack write_back,
3998                        DRegisterList dreglist) {
3999  VIXL_ASSERT(AllowAssembler());
4000  CheckIT(cond);
4001  if (IsUsingT32()) {
4002    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4003    if (write_back.DoesWriteBack() &&
4004        (((dreglist.GetLength() <= 16) &&
4005          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4006         AllowUnpredictable())) {
4007      const DRegister& dreg = dreglist.GetFirstDRegister();
4008      unsigned len = dreglist.GetLength() * 2;
4009      EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4010                 (len & 0xff));
4011      AdvanceIT();
4012      return;
4013    }
4014  } else {
4015    // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4016    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4017        (((dreglist.GetLength() <= 16) &&
4018          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4019         AllowUnpredictable())) {
4020      const DRegister& dreg = dreglist.GetFirstDRegister();
4021      unsigned len = dreglist.GetLength() * 2;
4022      EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4023              dreg.Encode(22, 12) | (len & 0xff));
4024      return;
4025    }
4026  }
4027  Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
4028}
4029
4030void Assembler::fldmiax(Condition cond,
4031                        Register rn,
4032                        WriteBack write_back,
4033                        DRegisterList dreglist) {
4034  VIXL_ASSERT(AllowAssembler());
4035  CheckIT(cond);
4036  if (IsUsingT32()) {
4037    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4038    if ((((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(0xec900b01U | (rn.GetCode() << 16) |
4044                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4045                 (len & 0xff));
4046      AdvanceIT();
4047      return;
4048    }
4049  } else {
4050    // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4051    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4052                               (dreglist.GetLastDRegister().GetCode() < 16)) ||
4053                              AllowUnpredictable())) {
4054      const DRegister& dreg = dreglist.GetFirstDRegister();
4055      unsigned len = dreglist.GetLength() * 2;
4056      EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4057              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4058              (len & 0xff));
4059      return;
4060    }
4061  }
4062  Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4063}
4064
4065void Assembler::fstmdbx(Condition cond,
4066                        Register rn,
4067                        WriteBack write_back,
4068                        DRegisterList dreglist) {
4069  VIXL_ASSERT(AllowAssembler());
4070  CheckIT(cond);
4071  if (IsUsingT32()) {
4072    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4073    if (write_back.DoesWriteBack() &&
4074        (((dreglist.GetLength() <= 16) &&
4075          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4076         AllowUnpredictable())) {
4077      const DRegister& dreg = dreglist.GetFirstDRegister();
4078      unsigned len = dreglist.GetLength() * 2;
4079      EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4080                 (len & 0xff));
4081      AdvanceIT();
4082      return;
4083    }
4084  } else {
4085    // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4086    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4087        (((dreglist.GetLength() <= 16) &&
4088          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4089         AllowUnpredictable())) {
4090      const DRegister& dreg = dreglist.GetFirstDRegister();
4091      unsigned len = dreglist.GetLength() * 2;
4092      EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4093              dreg.Encode(22, 12) | (len & 0xff));
4094      return;
4095    }
4096  }
4097  Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4098}
4099
4100void Assembler::fstmiax(Condition cond,
4101                        Register rn,
4102                        WriteBack write_back,
4103                        DRegisterList dreglist) {
4104  VIXL_ASSERT(AllowAssembler());
4105  CheckIT(cond);
4106  if (IsUsingT32()) {
4107    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4108    if ((((dreglist.GetLength() <= 16) &&
4109          (dreglist.GetLastDRegister().GetCode() < 16)) ||
4110         AllowUnpredictable())) {
4111      const DRegister& dreg = dreglist.GetFirstDRegister();
4112      unsigned len = dreglist.GetLength() * 2;
4113      EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4114                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4115                 (len & 0xff));
4116      AdvanceIT();
4117      return;
4118    }
4119  } else {
4120    // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4121    if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4122                               (dreglist.GetLastDRegister().GetCode() < 16)) ||
4123                              AllowUnpredictable())) {
4124      const DRegister& dreg = dreglist.GetFirstDRegister();
4125      unsigned len = dreglist.GetLength() * 2;
4126      EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4127              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4128              (len & 0xff));
4129      return;
4130    }
4131  }
4132  Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4133}
4134
4135void Assembler::hlt(Condition cond, uint32_t imm) {
4136  VIXL_ASSERT(AllowAssembler());
4137  CheckIT(cond);
4138  if (IsUsingT32()) {
4139    // HLT{<q>} {#}<imm> ; T1
4140    if ((imm <= 63)) {
4141      EmitT32_16(0xba80 | imm);
4142      AdvanceIT();
4143      return;
4144    }
4145  } else {
4146    // HLT{<q>} {#}<imm> ; A1
4147    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4148      EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4149              ((imm & 0xfff0) << 4));
4150      return;
4151    }
4152  }
4153  Delegate(kHlt, &Assembler::hlt, cond, imm);
4154}
4155
4156void Assembler::hvc(Condition cond, uint32_t imm) {
4157  VIXL_ASSERT(AllowAssembler());
4158  CheckIT(cond);
4159  if (IsUsingT32()) {
4160    // HVC{<q>} {#}<imm16> ; T1
4161    if ((imm <= 65535)) {
4162      EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4163      AdvanceIT();
4164      return;
4165    }
4166  } else {
4167    // HVC{<q>} {#}<imm16> ; A1
4168    if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4169      EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4170              ((imm & 0xfff0) << 4));
4171      return;
4172    }
4173  }
4174  Delegate(kHvc, &Assembler::hvc, cond, imm);
4175}
4176
4177void Assembler::isb(Condition cond, MemoryBarrier option) {
4178  VIXL_ASSERT(AllowAssembler());
4179  CheckIT(cond);
4180  if (IsUsingT32()) {
4181    // ISB{<c>}{<q>} {<option>} ; T1
4182    EmitT32_32(0xf3bf8f60U | option.GetType());
4183    AdvanceIT();
4184    return;
4185  } else {
4186    // ISB{<c>}{<q>} {<option>} ; A1
4187    if (cond.Is(al)) {
4188      EmitA32(0xf57ff060U | option.GetType());
4189      return;
4190    }
4191  }
4192  Delegate(kIsb, &Assembler::isb, cond, option);
4193}
4194
4195void Assembler::it(Condition cond, uint16_t mask) {
4196  VIXL_ASSERT(AllowAssembler());
4197  CheckNotIT();
4198  if (mask != 0) {
4199    if ((cond.GetCondition() & 0x1) != 0) {
4200      if ((mask & 0x1) != 0) {
4201        mask ^= 0xE;
4202      } else if ((mask & 0x2) != 0) {
4203        mask ^= 0xC;
4204      } else if ((mask & 0x4) != 0) {
4205        mask ^= 0x8;
4206      }
4207    }
4208    if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
4209    SetIT(cond, mask);
4210    return;
4211  }
4212  DelegateIt(cond, mask);
4213}
4214
4215void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
4216  VIXL_ASSERT(AllowAssembler());
4217  CheckIT(cond);
4218  if (operand.IsImmediateZero()) {
4219    Register rn = operand.GetBaseRegister();
4220    if (IsUsingT32()) {
4221      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
4222      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4223        EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4224        AdvanceIT();
4225        return;
4226      }
4227    } else {
4228      // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
4229      if (operand.IsOffset() && cond.IsNotNever() &&
4230          (!rn.IsPC() || AllowUnpredictable())) {
4231        EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4232                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4233        return;
4234      }
4235    }
4236  }
4237  Delegate(kLda, &Assembler::lda, cond, rt, operand);
4238}
4239
4240void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
4241  VIXL_ASSERT(AllowAssembler());
4242  CheckIT(cond);
4243  if (operand.IsImmediateZero()) {
4244    Register rn = operand.GetBaseRegister();
4245    if (IsUsingT32()) {
4246      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4247      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4248        EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4249        AdvanceIT();
4250        return;
4251      }
4252    } else {
4253      // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4254      if (operand.IsOffset() && cond.IsNotNever() &&
4255          (!rn.IsPC() || AllowUnpredictable())) {
4256        EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4257                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4258        return;
4259      }
4260    }
4261  }
4262  Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4263}
4264
4265void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
4266  VIXL_ASSERT(AllowAssembler());
4267  CheckIT(cond);
4268  if (operand.IsImmediateZero()) {
4269    Register rn = operand.GetBaseRegister();
4270    if (IsUsingT32()) {
4271      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
4272      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4273        EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4274        AdvanceIT();
4275        return;
4276      }
4277    } else {
4278      // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
4279      if (operand.IsOffset() && cond.IsNotNever() &&
4280          (!rn.IsPC() || AllowUnpredictable())) {
4281        EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4282                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4283        return;
4284      }
4285    }
4286  }
4287  Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4288}
4289
4290void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
4291  VIXL_ASSERT(AllowAssembler());
4292  CheckIT(cond);
4293  if (operand.IsImmediateZero()) {
4294    Register rn = operand.GetBaseRegister();
4295    if (IsUsingT32()) {
4296      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4297      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4298        EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4299        AdvanceIT();
4300        return;
4301      }
4302    } else {
4303      // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4304      if (operand.IsOffset() && cond.IsNotNever() &&
4305          (!rn.IsPC() || AllowUnpredictable())) {
4306        EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4307                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4308        return;
4309      }
4310    }
4311  }
4312  Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4313}
4314
4315void Assembler::ldaexd(Condition cond,
4316                       Register rt,
4317                       Register rt2,
4318                       const MemOperand& operand) {
4319  VIXL_ASSERT(AllowAssembler());
4320  CheckIT(cond);
4321  if (operand.IsImmediateZero()) {
4322    Register rn = operand.GetBaseRegister();
4323    if (IsUsingT32()) {
4324      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
4325      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4326        EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4327                   (rn.GetCode() << 16));
4328        AdvanceIT();
4329        return;
4330      }
4331    } else {
4332      // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4333      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
4334          operand.IsOffset() && cond.IsNotNever() &&
4335          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
4336           AllowUnpredictable())) {
4337        EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4338                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4339        return;
4340      }
4341    }
4342  }
4343  Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4344}
4345
4346void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
4347  VIXL_ASSERT(AllowAssembler());
4348  CheckIT(cond);
4349  if (operand.IsImmediateZero()) {
4350    Register rn = operand.GetBaseRegister();
4351    if (IsUsingT32()) {
4352      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4353      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4354        EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4355        AdvanceIT();
4356        return;
4357      }
4358    } else {
4359      // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4360      if (operand.IsOffset() && cond.IsNotNever() &&
4361          (!rn.IsPC() || AllowUnpredictable())) {
4362        EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4363                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4364        return;
4365      }
4366    }
4367  }
4368  Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4369}
4370
4371void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
4372  VIXL_ASSERT(AllowAssembler());
4373  CheckIT(cond);
4374  if (operand.IsImmediateZero()) {
4375    Register rn = operand.GetBaseRegister();
4376    if (IsUsingT32()) {
4377      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4378      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
4379        EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4380        AdvanceIT();
4381        return;
4382      }
4383    } else {
4384      // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4385      if (operand.IsOffset() && cond.IsNotNever() &&
4386          (!rn.IsPC() || AllowUnpredictable())) {
4387        EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4388                (rt.GetCode() << 12) | (rn.GetCode() << 16));
4389        return;
4390      }
4391    }
4392  }
4393  Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4394}
4395
4396void Assembler::ldm(Condition cond,
4397                    EncodingSize size,
4398                    Register rn,
4399                    WriteBack write_back,
4400                    RegisterList registers) {
4401  VIXL_ASSERT(AllowAssembler());
4402  CheckIT(cond);
4403  if (IsUsingT32()) {
4404    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4405    if (!size.IsWide() && rn.IsLow() &&
4406        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4407         write_back.DoesWriteBack()) &&
4408        ((registers.GetList() & ~0xff) == 0)) {
4409      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4410                 GetRegisterListEncoding(registers, 0, 8));
4411      AdvanceIT();
4412      return;
4413    }
4414    // LDM{<c>}{<q>} SP!, <registers> ; T1
4415    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4416        ((registers.GetList() & ~0x80ff) == 0)) {
4417      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4418                 GetRegisterListEncoding(registers, 0, 8));
4419      AdvanceIT();
4420      return;
4421    }
4422    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
4423    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
4424      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4425                 (write_back.GetWriteBackUint32() << 21) |
4426                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4427                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4428                 GetRegisterListEncoding(registers, 0, 13));
4429      AdvanceIT();
4430      return;
4431    }
4432  } else {
4433    // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
4434    if (cond.IsNotNever()) {
4435      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4436              (write_back.GetWriteBackUint32() << 21) |
4437              GetRegisterListEncoding(registers, 0, 16));
4438      return;
4439    }
4440  }
4441  Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4442}
4443
4444void Assembler::ldmda(Condition cond,
4445                      Register rn,
4446                      WriteBack write_back,
4447                      RegisterList registers) {
4448  VIXL_ASSERT(AllowAssembler());
4449  CheckIT(cond);
4450  if (IsUsingA32()) {
4451    // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4452    if (cond.IsNotNever()) {
4453      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4454              (write_back.GetWriteBackUint32() << 21) |
4455              GetRegisterListEncoding(registers, 0, 16));
4456      return;
4457    }
4458  }
4459  Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4460}
4461
4462void Assembler::ldmdb(Condition cond,
4463                      Register rn,
4464                      WriteBack write_back,
4465                      RegisterList registers) {
4466  VIXL_ASSERT(AllowAssembler());
4467  CheckIT(cond);
4468  if (IsUsingT32()) {
4469    // LDMDB{<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    // LDMDB{<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(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4489}
4490
4491void Assembler::ldmea(Condition cond,
4492                      Register rn,
4493                      WriteBack write_back,
4494                      RegisterList registers) {
4495  VIXL_ASSERT(AllowAssembler());
4496  CheckIT(cond);
4497  if (IsUsingT32()) {
4498    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
4499    if (((registers.GetList() & ~0xdfff) == 0)) {
4500      EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4501                 (write_back.GetWriteBackUint32() << 21) |
4502                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4503                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4504                 GetRegisterListEncoding(registers, 0, 13));
4505      AdvanceIT();
4506      return;
4507    }
4508  } else {
4509    // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4510    if (cond.IsNotNever()) {
4511      EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4512              (write_back.GetWriteBackUint32() << 21) |
4513              GetRegisterListEncoding(registers, 0, 16));
4514      return;
4515    }
4516  }
4517  Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4518}
4519
4520void Assembler::ldmed(Condition cond,
4521                      Register rn,
4522                      WriteBack write_back,
4523                      RegisterList registers) {
4524  VIXL_ASSERT(AllowAssembler());
4525  CheckIT(cond);
4526  if (IsUsingA32()) {
4527    // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
4528    if (cond.IsNotNever()) {
4529      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4530              (write_back.GetWriteBackUint32() << 21) |
4531              GetRegisterListEncoding(registers, 0, 16));
4532      return;
4533    }
4534  }
4535  Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4536}
4537
4538void Assembler::ldmfa(Condition cond,
4539                      Register rn,
4540                      WriteBack write_back,
4541                      RegisterList registers) {
4542  VIXL_ASSERT(AllowAssembler());
4543  CheckIT(cond);
4544  if (IsUsingA32()) {
4545    // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4546    if (cond.IsNotNever()) {
4547      EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4548              (write_back.GetWriteBackUint32() << 21) |
4549              GetRegisterListEncoding(registers, 0, 16));
4550      return;
4551    }
4552  }
4553  Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4554}
4555
4556void Assembler::ldmfd(Condition cond,
4557                      EncodingSize size,
4558                      Register rn,
4559                      WriteBack write_back,
4560                      RegisterList registers) {
4561  VIXL_ASSERT(AllowAssembler());
4562  CheckIT(cond);
4563  if (IsUsingT32()) {
4564    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4565    if (!size.IsWide() && rn.IsLow() &&
4566        (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4567         write_back.DoesWriteBack()) &&
4568        ((registers.GetList() & ~0xff) == 0)) {
4569      EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4570                 GetRegisterListEncoding(registers, 0, 8));
4571      AdvanceIT();
4572      return;
4573    }
4574    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
4575    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
4576      EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4577                 (write_back.GetWriteBackUint32() << 21) |
4578                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4579                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4580                 GetRegisterListEncoding(registers, 0, 13));
4581      AdvanceIT();
4582      return;
4583    }
4584  } else {
4585    // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
4586    if (cond.IsNotNever()) {
4587      EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4588              (write_back.GetWriteBackUint32() << 21) |
4589              GetRegisterListEncoding(registers, 0, 16));
4590      return;
4591    }
4592  }
4593  Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4594}
4595
4596void Assembler::ldmib(Condition cond,
4597                      Register rn,
4598                      WriteBack write_back,
4599                      RegisterList registers) {
4600  VIXL_ASSERT(AllowAssembler());
4601  CheckIT(cond);
4602  if (IsUsingA32()) {
4603    // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4604    if (cond.IsNotNever()) {
4605      EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4606              (write_back.GetWriteBackUint32() << 21) |
4607              GetRegisterListEncoding(registers, 0, 16));
4608      return;
4609    }
4610  }
4611  Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4612}
4613
4614void Assembler::ldr(Condition cond,
4615                    EncodingSize size,
4616                    Register rt,
4617                    const MemOperand& operand) {
4618  VIXL_ASSERT(AllowAssembler());
4619  CheckIT(cond);
4620  if (operand.IsImmediate()) {
4621    Register rn = operand.GetBaseRegister();
4622    int32_t offset = operand.GetOffsetImmediate();
4623    if (IsUsingT32()) {
4624      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4625      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4626          (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
4627        int32_t offset_ = offset >> 2;
4628        EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
4629                   ((offset_ & 0x1f) << 6));
4630        AdvanceIT();
4631        return;
4632      }
4633      // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
4634      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
4635          ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
4636        int32_t offset_ = offset >> 2;
4637        EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
4638        AdvanceIT();
4639        return;
4640      }
4641      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
4642      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
4643          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
4644        EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4645                   (offset & 0xfff));
4646        AdvanceIT();
4647        return;
4648      }
4649      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
4650      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
4651          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
4652        EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4653                   (-offset & 0xff));
4654        AdvanceIT();
4655        return;
4656      }
4657      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
4658      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4659          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
4660        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4661        uint32_t offset_ = abs(offset);
4662        EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4663                   offset_ | (sign << 9));
4664        AdvanceIT();
4665        return;
4666      }
4667      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
4668      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4669          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
4670        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4671        uint32_t offset_ = abs(offset);
4672        EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4673                   offset_ | (sign << 9));
4674        AdvanceIT();
4675        return;
4676      }
4677      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
4678      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
4679          rn.Is(pc) && operand.IsOffset()) {
4680        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4681        uint32_t offset_ = abs(offset);
4682        EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
4683        AdvanceIT();
4684        return;
4685      }
4686    } else {
4687      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
4688      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
4689          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
4690        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4691        uint32_t offset_ = abs(offset);
4692        EmitA32(0x05100000U | (cond.GetCondition() << 28) |
4693                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4694                (sign << 23));
4695        return;
4696      }
4697      // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
4698      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
4699          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
4700        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4701        uint32_t offset_ = abs(offset);
4702        EmitA32(0x04100000U | (cond.GetCondition() << 28) |
4703                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4704                (sign << 23));
4705        return;
4706      }
4707      // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
4708      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
4709          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
4710        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4711        uint32_t offset_ = abs(offset);
4712        EmitA32(0x05300000U | (cond.GetCondition() << 28) |
4713                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4714                (sign << 23));
4715        return;
4716      }
4717      // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
4718      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
4719          operand.IsOffset() && cond.IsNotNever()) {
4720        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4721        uint32_t offset_ = abs(offset);
4722        EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
4723                (rt.GetCode() << 12) | offset_ | (sign << 23));
4724        return;
4725      }
4726    }
4727  }
4728  if (operand.IsPlainRegister()) {
4729    Register rn = operand.GetBaseRegister();
4730    Sign sign = operand.GetSign();
4731    Register rm = operand.GetOffsetRegister();
4732    if (IsUsingT32()) {
4733      // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
4734      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
4735          sign.IsPlus() && operand.IsOffset()) {
4736        EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
4737                   (rm.GetCode() << 6));
4738        AdvanceIT();
4739        return;
4740      }
4741    }
4742  }
4743  if (operand.IsShiftedRegister()) {
4744    Register rn = operand.GetBaseRegister();
4745    Sign sign = operand.GetSign();
4746    Register rm = operand.GetOffsetRegister();
4747    Shift shift = operand.GetShift();
4748    uint32_t amount = operand.GetShiftAmount();
4749    if (IsUsingT32()) {
4750      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
4751      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
4752          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
4753        EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4754                   rm.GetCode() | (amount << 4));
4755        AdvanceIT();
4756        return;
4757      }
4758    } else {
4759      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
4760      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever()) {
4761        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4762        uint32_t shift_ = TypeEncodingValue(shift);
4763        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4764        EmitA32(0x07100000U | (cond.GetCondition() << 28) |
4765                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4766                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4767        return;
4768      }
4769      // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
4770      if (operand.IsShiftValid() && operand.IsPostIndex() &&
4771          cond.IsNotNever()) {
4772        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4773        uint32_t shift_ = TypeEncodingValue(shift);
4774        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4775        EmitA32(0x06100000U | (cond.GetCondition() << 28) |
4776                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4777                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4778        return;
4779      }
4780      // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
4781      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever()) {
4782        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4783        uint32_t shift_ = TypeEncodingValue(shift);
4784        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4785        EmitA32(0x07300000U | (cond.GetCondition() << 28) |
4786                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4787                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4788        return;
4789      }
4790    }
4791  }
4792  Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
4793}
4794
4795void Assembler::ldr(Condition cond,
4796                    EncodingSize size,
4797                    Register rt,
4798                    Label* label) {
4799  VIXL_ASSERT(AllowAssembler());
4800  CheckIT(cond);
4801  Label::Offset offset =
4802      label->IsBound()
4803          ? label->GetLocation() -
4804                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
4805          : 0;
4806  if (IsUsingT32()) {
4807    // LDR{<c>}{<q>} <Rt>, <label> ; T1
4808    if (!size.IsWide() && rt.IsLow() &&
4809        ((label->IsBound() && (offset >= 0) && (offset <= 1020) &&
4810          ((offset & 0x3) == 0)) ||
4811         (!label->IsBound() && size.IsNarrow()))) {
4812      static class EmitOp : public Label::LabelEmitOperator {
4813       public:
4814        EmitOp() : Label::LabelEmitOperator(0, 1020) {}
4815        virtual uint32_t Encode(uint32_t instr,
4816                                Label::Offset pc,
4817                                const Label* label) const VIXL_OVERRIDE {
4818          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4819          VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
4820                      ((offset & 0x3) == 0));
4821          const int32_t target = offset >> 2;
4822          return instr | (target & 0xff);
4823        }
4824      } immop;
4825      EmitT32_16(Link(0x4800 | (rt.GetCode() << 8), label, immop));
4826      AdvanceIT();
4827      return;
4828    }
4829    // LDR{<c>}{<q>} <Rt>, <label> ; T2
4830    if (!size.IsNarrow() &&
4831        ((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
4832         !label->IsBound())) {
4833      static class EmitOp : public Label::LabelEmitOperator {
4834       public:
4835        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
4836        virtual uint32_t Encode(uint32_t instr,
4837                                Label::Offset pc,
4838                                const Label* label) const VIXL_OVERRIDE {
4839          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4840          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
4841          uint32_t U = (offset >= 0) && !label->IsMinusZero();
4842          int32_t target = abs(offset) | (U << 12);
4843          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
4844        }
4845      } immop;
4846      EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12), label, immop));
4847      AdvanceIT();
4848      return;
4849    }
4850  } else {
4851    // LDR{<c>}{<q>} <Rt>, <label> ; A1
4852    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
4853         !label->IsBound()) &&
4854        cond.IsNotNever()) {
4855      static class EmitOp : public Label::LabelEmitOperator {
4856       public:
4857        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
4858        virtual uint32_t Encode(uint32_t instr,
4859                                Label::Offset pc,
4860                                const Label* label) const VIXL_OVERRIDE {
4861          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4862          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
4863          uint32_t U = (offset >= 0) && !label->IsMinusZero();
4864          int32_t target = abs(offset) | (U << 12);
4865          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
4866        }
4867      } immop;
4868      EmitA32(
4869          Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
4870               label,
4871               immop));
4872      return;
4873    }
4874  }
4875  Delegate(kLdr, &Assembler::ldr, cond, size, rt, label);
4876}
4877
4878void Assembler::ldrb(Condition cond,
4879                     EncodingSize size,
4880                     Register rt,
4881                     const MemOperand& operand) {
4882  VIXL_ASSERT(AllowAssembler());
4883  CheckIT(cond);
4884  if (operand.IsImmediate()) {
4885    Register rn = operand.GetBaseRegister();
4886    int32_t offset = operand.GetOffsetImmediate();
4887    if (IsUsingT32()) {
4888      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4889      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4890          (offset <= 31) && operand.IsOffset()) {
4891        EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
4892                   ((offset & 0x1f) << 6));
4893        AdvanceIT();
4894        return;
4895      }
4896      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
4897      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
4898          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
4899        EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4900                   (offset & 0xfff));
4901        AdvanceIT();
4902        return;
4903      }
4904      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
4905      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
4906          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
4907        EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4908                   (-offset & 0xff));
4909        AdvanceIT();
4910        return;
4911      }
4912      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
4913      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4914          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
4915        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4916        uint32_t offset_ = abs(offset);
4917        EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4918                   offset_ | (sign << 9));
4919        AdvanceIT();
4920        return;
4921      }
4922      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
4923      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4924          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
4925        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4926        uint32_t offset_ = abs(offset);
4927        EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4928                   offset_ | (sign << 9));
4929        AdvanceIT();
4930        return;
4931      }
4932      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
4933      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
4934          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
4935        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4936        uint32_t offset_ = abs(offset);
4937        EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
4938        AdvanceIT();
4939        return;
4940      }
4941    } else {
4942      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
4943      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
4944          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
4945        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4946        uint32_t offset_ = abs(offset);
4947        EmitA32(0x05500000U | (cond.GetCondition() << 28) |
4948                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4949                (sign << 23));
4950        return;
4951      }
4952      // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
4953      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
4954          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
4955        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4956        uint32_t offset_ = abs(offset);
4957        EmitA32(0x04500000U | (cond.GetCondition() << 28) |
4958                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4959                (sign << 23));
4960        return;
4961      }
4962      // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
4963      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
4964          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
4965        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4966        uint32_t offset_ = abs(offset);
4967        EmitA32(0x05700000U | (cond.GetCondition() << 28) |
4968                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4969                (sign << 23));
4970        return;
4971      }
4972      // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
4973      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
4974          operand.IsOffset() && cond.IsNotNever()) {
4975        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4976        uint32_t offset_ = abs(offset);
4977        EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
4978                (rt.GetCode() << 12) | offset_ | (sign << 23));
4979        return;
4980      }
4981    }
4982  }
4983  if (operand.IsPlainRegister()) {
4984    Register rn = operand.GetBaseRegister();
4985    Sign sign = operand.GetSign();
4986    Register rm = operand.GetOffsetRegister();
4987    if (IsUsingT32()) {
4988      // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
4989      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
4990          sign.IsPlus() && operand.IsOffset()) {
4991        EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
4992                   (rm.GetCode() << 6));
4993        AdvanceIT();
4994        return;
4995      }
4996    }
4997  }
4998  if (operand.IsShiftedRegister()) {
4999    Register rn = operand.GetBaseRegister();
5000    Sign sign = operand.GetSign();
5001    Register rm = operand.GetOffsetRegister();
5002    Shift shift = operand.GetShift();
5003    uint32_t amount = operand.GetShiftAmount();
5004    if (IsUsingT32()) {
5005      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5006      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5007          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5008        EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5009                   rm.GetCode() | (amount << 4));
5010        AdvanceIT();
5011        return;
5012      }
5013    } else {
5014      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5015      if (operand.IsShiftValid() && operand.IsOffset() && 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(0x07500000U | (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.IsPostIndex() &&
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(0x06500000U | (cond.GetCondition() << 28) |
5031                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5032                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5033        return;
5034      }
5035      // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5036      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever()) {
5037        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5038        uint32_t shift_ = TypeEncodingValue(shift);
5039        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5040        EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5041                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5042                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5043        return;
5044      }
5045    }
5046  }
5047  Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5048}
5049
5050void Assembler::ldrb(Condition cond, Register rt, Label* label) {
5051  VIXL_ASSERT(AllowAssembler());
5052  CheckIT(cond);
5053  Label::Offset offset =
5054      label->IsBound()
5055          ? label->GetLocation() -
5056                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5057          : 0;
5058  if (IsUsingT32()) {
5059    // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5060    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5061         !label->IsBound()) &&
5062        !rt.Is(pc)) {
5063      static class EmitOp : public Label::LabelEmitOperator {
5064       public:
5065        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5066        virtual uint32_t Encode(uint32_t instr,
5067                                Label::Offset pc,
5068                                const Label* label) const VIXL_OVERRIDE {
5069          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5070          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5071          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5072          int32_t target = abs(offset) | (U << 12);
5073          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5074        }
5075      } immop;
5076      EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12), label, immop));
5077      AdvanceIT();
5078      return;
5079    }
5080  } else {
5081    // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5082    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5083         !label->IsBound()) &&
5084        cond.IsNotNever()) {
5085      static class EmitOp : public Label::LabelEmitOperator {
5086       public:
5087        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5088        virtual uint32_t Encode(uint32_t instr,
5089                                Label::Offset pc,
5090                                const Label* label) const VIXL_OVERRIDE {
5091          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5092          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5093          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5094          int32_t target = abs(offset) | (U << 12);
5095          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5096        }
5097      } immop;
5098      EmitA32(
5099          Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5100               label,
5101               immop));
5102      return;
5103    }
5104  }
5105  Delegate(kLdrb, &Assembler::ldrb, cond, rt, label);
5106}
5107
5108void Assembler::ldrd(Condition cond,
5109                     Register rt,
5110                     Register rt2,
5111                     const MemOperand& operand) {
5112  VIXL_ASSERT(AllowAssembler());
5113  CheckIT(cond);
5114  if (operand.IsImmediate()) {
5115    Register rn = operand.GetBaseRegister();
5116    int32_t offset = operand.GetOffsetImmediate();
5117    if (IsUsingT32()) {
5118      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5119      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5120          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
5121        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5122        uint32_t offset_ = abs(offset) >> 2;
5123        EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5124                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5125        AdvanceIT();
5126        return;
5127      }
5128      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5129      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5130          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5131        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5132        uint32_t offset_ = abs(offset) >> 2;
5133        EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5134                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5135        AdvanceIT();
5136        return;
5137      }
5138      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5139      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5140          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5141        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5142        uint32_t offset_ = abs(offset) >> 2;
5143        EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5144                   (rn.GetCode() << 16) | offset_ | (sign << 23));
5145        AdvanceIT();
5146        return;
5147      }
5148      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5149      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5150          operand.IsOffset()) {
5151        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5152        uint32_t offset_ = abs(offset);
5153        EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5154                   offset_ | (sign << 23));
5155        AdvanceIT();
5156        return;
5157      }
5158    } else {
5159      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5160      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5161          (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5162          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5163          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5164        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5165        uint32_t offset_ = abs(offset);
5166        EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5167                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5168                ((offset_ & 0xf0) << 4) | (sign << 23));
5169        return;
5170      }
5171      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5172      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5173          (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5174          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5175          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5176        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5177        uint32_t offset_ = abs(offset);
5178        EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5179                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5180                ((offset_ & 0xf0) << 4) | (sign << 23));
5181        return;
5182      }
5183      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5184      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5185          (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5186          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5187          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5188        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5189        uint32_t offset_ = abs(offset);
5190        EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5191                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5192                ((offset_ & 0xf0) << 4) | (sign << 23));
5193        return;
5194      }
5195      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5196      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5197          (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5198          operand.IsOffset() && cond.IsNotNever() &&
5199          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5200        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5201        uint32_t offset_ = abs(offset);
5202        EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5203                (rt.GetCode() << 12) | (offset_ & 0xf) |
5204                ((offset_ & 0xf0) << 4) | (sign << 23));
5205        return;
5206      }
5207    }
5208  }
5209  if (operand.IsPlainRegister()) {
5210    Register rn = operand.GetBaseRegister();
5211    Sign sign = operand.GetSign();
5212    Register rm = operand.GetOffsetRegister();
5213    if (IsUsingA32()) {
5214      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5215      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5216          operand.IsOffset() && cond.IsNotNever() &&
5217          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5218        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5219        EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5220                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5221                (sign_ << 23));
5222        return;
5223      }
5224      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5225      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5226          operand.IsPostIndex() && cond.IsNotNever() &&
5227          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5228        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5229        EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5230                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5231                (sign_ << 23));
5232        return;
5233      }
5234      // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5235      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5236          operand.IsPreIndex() && cond.IsNotNever() &&
5237          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5238        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5239        EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5240                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5241                (sign_ << 23));
5242        return;
5243      }
5244    }
5245  }
5246  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5247}
5248
5249void Assembler::ldrd(Condition cond, Register rt, Register rt2, Label* label) {
5250  VIXL_ASSERT(AllowAssembler());
5251  CheckIT(cond);
5252  Label::Offset offset =
5253      label->IsBound()
5254          ? label->GetLocation() -
5255                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5256          : 0;
5257  if (IsUsingT32()) {
5258    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5259    if (((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
5260          ((offset & 0x3) == 0)) ||
5261         !label->IsBound())) {
5262      static class EmitOp : public Label::LabelEmitOperator {
5263       public:
5264        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
5265        virtual uint32_t Encode(uint32_t instr,
5266                                Label::Offset pc,
5267                                const Label* label) const VIXL_OVERRIDE {
5268          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5269          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5270                      ((offset & 0x3) == 0));
5271          int32_t target = offset >> 2;
5272          uint32_t U = (target >= 0) && !label->IsMinusZero();
5273          target = abs(target) | (U << 8);
5274          return instr | (target & 0xff) | ((target & 0x100) << 15);
5275        }
5276      } immop;
5277      EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
5278                      label,
5279                      immop));
5280      AdvanceIT();
5281      return;
5282    }
5283  } else {
5284    // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5285    if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5286        ((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5287         !label->IsBound()) &&
5288        cond.IsNotNever() &&
5289        ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5290      static class EmitOp : public Label::LabelEmitOperator {
5291       public:
5292        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
5293        virtual uint32_t Encode(uint32_t instr,
5294                                Label::Offset pc,
5295                                const Label* label) const VIXL_OVERRIDE {
5296          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5297          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5298          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5299          int32_t target = abs(offset) | (U << 8);
5300          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5301                 ((target & 0x100) << 15);
5302        }
5303      } immop;
5304      EmitA32(
5305          Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5306               label,
5307               immop));
5308      return;
5309    }
5310  }
5311  Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, label);
5312}
5313
5314void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
5315  VIXL_ASSERT(AllowAssembler());
5316  CheckIT(cond);
5317  if (operand.IsImmediate()) {
5318    Register rn = operand.GetBaseRegister();
5319    int32_t offset = operand.GetOffsetImmediate();
5320    if (IsUsingT32()) {
5321      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5322      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
5323          operand.IsOffset()) {
5324        int32_t offset_ = offset >> 2;
5325        EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5326                   (offset_ & 0xff));
5327        AdvanceIT();
5328        return;
5329      }
5330    } else {
5331      // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
5332      if ((offset == 0) && operand.IsOffset() && cond.IsNotNever()) {
5333        EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5334                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5335        return;
5336      }
5337    }
5338  }
5339  Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5340}
5341
5342void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
5343  VIXL_ASSERT(AllowAssembler());
5344  CheckIT(cond);
5345  if (operand.IsImmediateZero()) {
5346    Register rn = operand.GetBaseRegister();
5347    if (IsUsingT32()) {
5348      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
5349      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
5350        EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5351        AdvanceIT();
5352        return;
5353      }
5354    } else {
5355      // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
5356      if (operand.IsOffset() && cond.IsNotNever() &&
5357          (!rn.IsPC() || AllowUnpredictable())) {
5358        EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5359                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5360        return;
5361      }
5362    }
5363  }
5364  Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5365}
5366
5367void Assembler::ldrexd(Condition cond,
5368                       Register rt,
5369                       Register rt2,
5370                       const MemOperand& operand) {
5371  VIXL_ASSERT(AllowAssembler());
5372  CheckIT(cond);
5373  if (operand.IsImmediateZero()) {
5374    Register rn = operand.GetBaseRegister();
5375    if (IsUsingT32()) {
5376      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
5377      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
5378        EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5379                   (rn.GetCode() << 16));
5380        AdvanceIT();
5381        return;
5382      }
5383    } else {
5384      // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5385      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5386          operand.IsOffset() && cond.IsNotNever() &&
5387          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
5388           AllowUnpredictable())) {
5389        EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5390                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5391        return;
5392      }
5393    }
5394  }
5395  Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5396}
5397
5398void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
5399  VIXL_ASSERT(AllowAssembler());
5400  CheckIT(cond);
5401  if (operand.IsImmediateZero()) {
5402    Register rn = operand.GetBaseRegister();
5403    if (IsUsingT32()) {
5404      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
5405      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
5406        EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5407        AdvanceIT();
5408        return;
5409      }
5410    } else {
5411      // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
5412      if (operand.IsOffset() && cond.IsNotNever() &&
5413          (!rn.IsPC() || AllowUnpredictable())) {
5414        EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5415                (rt.GetCode() << 12) | (rn.GetCode() << 16));
5416        return;
5417      }
5418    }
5419  }
5420  Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5421}
5422
5423void Assembler::ldrh(Condition cond,
5424                     EncodingSize size,
5425                     Register rt,
5426                     const MemOperand& operand) {
5427  VIXL_ASSERT(AllowAssembler());
5428  CheckIT(cond);
5429  if (operand.IsImmediate()) {
5430    Register rn = operand.GetBaseRegister();
5431    int32_t offset = operand.GetOffsetImmediate();
5432    if (IsUsingT32()) {
5433      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5434      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5435          (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
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.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5445        EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5446                   (offset & 0xfff));
5447        AdvanceIT();
5448        return;
5449      }
5450      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5451      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5452          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5453        EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5454                   (-offset & 0xff));
5455        AdvanceIT();
5456        return;
5457      }
5458      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5459      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5460          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5461        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5462        uint32_t offset_ = abs(offset);
5463        EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5464                   offset_ | (sign << 9));
5465        AdvanceIT();
5466        return;
5467      }
5468      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5469      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5470          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5471        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5472        uint32_t offset_ = abs(offset);
5473        EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5474                   offset_ | (sign << 9));
5475        AdvanceIT();
5476        return;
5477      }
5478      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5479      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5480          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
5481        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5482        uint32_t offset_ = abs(offset);
5483        EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5484        AdvanceIT();
5485        return;
5486      }
5487    } else {
5488      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5489      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5490          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5491        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5492        uint32_t offset_ = abs(offset);
5493        EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
5494                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5495                ((offset_ & 0xf0) << 4) | (sign << 23));
5496        return;
5497      }
5498      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5499      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5500          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5501        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5502        uint32_t offset_ = abs(offset);
5503        EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
5504                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5505                ((offset_ & 0xf0) << 4) | (sign << 23));
5506        return;
5507      }
5508      // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5509      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5510          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5511        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5512        uint32_t offset_ = abs(offset);
5513        EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
5514                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5515                ((offset_ & 0xf0) << 4) | (sign << 23));
5516        return;
5517      }
5518      // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5519      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5520          operand.IsOffset() && cond.IsNotNever()) {
5521        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5522        uint32_t offset_ = abs(offset);
5523        EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
5524                (rt.GetCode() << 12) | (offset_ & 0xf) |
5525                ((offset_ & 0xf0) << 4) | (sign << 23));
5526        return;
5527      }
5528    }
5529  }
5530  if (operand.IsPlainRegister()) {
5531    Register rn = operand.GetBaseRegister();
5532    Sign sign = operand.GetSign();
5533    Register rm = operand.GetOffsetRegister();
5534    if (IsUsingT32()) {
5535      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5536      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5537          sign.IsPlus() && operand.IsOffset()) {
5538        EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
5539                   (rm.GetCode() << 6));
5540        AdvanceIT();
5541        return;
5542      }
5543    } else {
5544      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5545      if (operand.IsOffset() && cond.IsNotNever()) {
5546        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5547        EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
5548                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5549                (sign_ << 23));
5550        return;
5551      }
5552      // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5553      if (operand.IsPostIndex() && cond.IsNotNever()) {
5554        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5555        EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
5556                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5557                (sign_ << 23));
5558        return;
5559      }
5560      // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5561      if (operand.IsPreIndex() && cond.IsNotNever()) {
5562        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5563        EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
5564                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5565                (sign_ << 23));
5566        return;
5567      }
5568    }
5569  }
5570  if (operand.IsShiftedRegister()) {
5571    Register rn = operand.GetBaseRegister();
5572    Sign sign = operand.GetSign();
5573    Register rm = operand.GetOffsetRegister();
5574    Shift shift = operand.GetShift();
5575    uint32_t amount = operand.GetShiftAmount();
5576    if (IsUsingT32()) {
5577      // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5578      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5579          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5580        EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5581                   rm.GetCode() | (amount << 4));
5582        AdvanceIT();
5583        return;
5584      }
5585    }
5586  }
5587  Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
5588}
5589
5590void Assembler::ldrh(Condition cond, Register rt, Label* label) {
5591  VIXL_ASSERT(AllowAssembler());
5592  CheckIT(cond);
5593  Label::Offset offset =
5594      label->IsBound()
5595          ? label->GetLocation() -
5596                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5597          : 0;
5598  if (IsUsingT32()) {
5599    // LDRH{<c>}{<q>} <Rt>, <label> ; T1
5600    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5601         !label->IsBound()) &&
5602        !rt.Is(pc)) {
5603      static class EmitOp : public Label::LabelEmitOperator {
5604       public:
5605        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5606        virtual uint32_t Encode(uint32_t instr,
5607                                Label::Offset pc,
5608                                const Label* label) const VIXL_OVERRIDE {
5609          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5610          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5611          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5612          int32_t target = abs(offset) | (U << 12);
5613          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5614        }
5615      } immop;
5616      EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12), label, immop));
5617      AdvanceIT();
5618      return;
5619    }
5620  } else {
5621    // LDRH{<c>}{<q>} <Rt>, <label> ; A1
5622    if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5623         !label->IsBound()) &&
5624        cond.IsNotNever()) {
5625      static class EmitOp : public Label::LabelEmitOperator {
5626       public:
5627        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
5628        virtual uint32_t Encode(uint32_t instr,
5629                                Label::Offset pc,
5630                                const Label* label) const VIXL_OVERRIDE {
5631          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5632          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5633          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5634          int32_t target = abs(offset) | (U << 8);
5635          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5636                 ((target & 0x100) << 15);
5637        }
5638      } immop;
5639      EmitA32(
5640          Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5641               label,
5642               immop));
5643      return;
5644    }
5645  }
5646  Delegate(kLdrh, &Assembler::ldrh, cond, rt, label);
5647}
5648
5649void Assembler::ldrsb(Condition cond,
5650                      EncodingSize size,
5651                      Register rt,
5652                      const MemOperand& operand) {
5653  VIXL_ASSERT(AllowAssembler());
5654  CheckIT(cond);
5655  if (operand.IsImmediate()) {
5656    Register rn = operand.GetBaseRegister();
5657    int32_t offset = operand.GetOffsetImmediate();
5658    if (IsUsingT32()) {
5659      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5660      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5661          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5662        EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5663                   (offset & 0xfff));
5664        AdvanceIT();
5665        return;
5666      }
5667      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
5668      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5669          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5670        EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5671                   (-offset & 0xff));
5672        AdvanceIT();
5673        return;
5674      }
5675      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
5676      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5677          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5678        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5679        uint32_t offset_ = abs(offset);
5680        EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5681                   offset_ | (sign << 9));
5682        AdvanceIT();
5683        return;
5684      }
5685      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
5686      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5687          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5688        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5689        uint32_t offset_ = abs(offset);
5690        EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5691                   offset_ | (sign << 9));
5692        AdvanceIT();
5693        return;
5694      }
5695      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5696      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5697          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
5698        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5699        uint32_t offset_ = abs(offset);
5700        EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5701        AdvanceIT();
5702        return;
5703      }
5704    } else {
5705      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
5706      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5707          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5708        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5709        uint32_t offset_ = abs(offset);
5710        EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
5711                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5712                ((offset_ & 0xf0) << 4) | (sign << 23));
5713        return;
5714      }
5715      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
5716      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5717          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5718        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5719        uint32_t offset_ = abs(offset);
5720        EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
5721                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5722                ((offset_ & 0xf0) << 4) | (sign << 23));
5723        return;
5724      }
5725      // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
5726      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5727          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5728        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5729        uint32_t offset_ = abs(offset);
5730        EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
5731                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5732                ((offset_ & 0xf0) << 4) | (sign << 23));
5733        return;
5734      }
5735      // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5736      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5737          operand.IsOffset() && cond.IsNotNever()) {
5738        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5739        uint32_t offset_ = abs(offset);
5740        EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
5741                (rt.GetCode() << 12) | (offset_ & 0xf) |
5742                ((offset_ & 0xf0) << 4) | (sign << 23));
5743        return;
5744      }
5745    }
5746  }
5747  if (operand.IsPlainRegister()) {
5748    Register rn = operand.GetBaseRegister();
5749    Sign sign = operand.GetSign();
5750    Register rm = operand.GetOffsetRegister();
5751    if (IsUsingT32()) {
5752      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5753      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5754          sign.IsPlus() && operand.IsOffset()) {
5755        EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
5756                   (rm.GetCode() << 6));
5757        AdvanceIT();
5758        return;
5759      }
5760    } else {
5761      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5762      if (operand.IsOffset() && cond.IsNotNever()) {
5763        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5764        EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
5765                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5766                (sign_ << 23));
5767        return;
5768      }
5769      // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5770      if (operand.IsPostIndex() && cond.IsNotNever()) {
5771        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5772        EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
5773                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5774                (sign_ << 23));
5775        return;
5776      }
5777      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5778      if (operand.IsPreIndex() && cond.IsNotNever()) {
5779        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5780        EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
5781                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5782                (sign_ << 23));
5783        return;
5784      }
5785    }
5786  }
5787  if (operand.IsShiftedRegister()) {
5788    Register rn = operand.GetBaseRegister();
5789    Sign sign = operand.GetSign();
5790    Register rm = operand.GetOffsetRegister();
5791    Shift shift = operand.GetShift();
5792    uint32_t amount = operand.GetShiftAmount();
5793    if (IsUsingT32()) {
5794      // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5795      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5796          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5797        EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5798                   rm.GetCode() | (amount << 4));
5799        AdvanceIT();
5800        return;
5801      }
5802    }
5803  }
5804  Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
5805}
5806
5807void Assembler::ldrsb(Condition cond, Register rt, Label* label) {
5808  VIXL_ASSERT(AllowAssembler());
5809  CheckIT(cond);
5810  Label::Offset offset =
5811      label->IsBound()
5812          ? label->GetLocation() -
5813                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5814          : 0;
5815  if (IsUsingT32()) {
5816    // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
5817    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5818         !label->IsBound()) &&
5819        !rt.Is(pc)) {
5820      static class EmitOp : public Label::LabelEmitOperator {
5821       public:
5822        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
5823        virtual uint32_t Encode(uint32_t instr,
5824                                Label::Offset pc,
5825                                const Label* label) const VIXL_OVERRIDE {
5826          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5827          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5828          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5829          int32_t target = abs(offset) | (U << 12);
5830          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5831        }
5832      } immop;
5833      EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12), label, immop));
5834      AdvanceIT();
5835      return;
5836    }
5837  } else {
5838    // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
5839    if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5840         !label->IsBound()) &&
5841        cond.IsNotNever()) {
5842      static class EmitOp : public Label::LabelEmitOperator {
5843       public:
5844        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
5845        virtual uint32_t Encode(uint32_t instr,
5846                                Label::Offset pc,
5847                                const Label* label) const VIXL_OVERRIDE {
5848          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5849          VIXL_ASSERT((offset >= -255) && (offset <= 255));
5850          uint32_t U = (offset >= 0) && !label->IsMinusZero();
5851          int32_t target = abs(offset) | (U << 8);
5852          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5853                 ((target & 0x100) << 15);
5854        }
5855      } immop;
5856      EmitA32(
5857          Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5858               label,
5859               immop));
5860      return;
5861    }
5862  }
5863  Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, label);
5864}
5865
5866void Assembler::ldrsh(Condition cond,
5867                      EncodingSize size,
5868                      Register rt,
5869                      const MemOperand& operand) {
5870  VIXL_ASSERT(AllowAssembler());
5871  CheckIT(cond);
5872  if (operand.IsImmediate()) {
5873    Register rn = operand.GetBaseRegister();
5874    int32_t offset = operand.GetOffsetImmediate();
5875    if (IsUsingT32()) {
5876      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5877      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5878          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5879        EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5880                   (offset & 0xfff));
5881        AdvanceIT();
5882        return;
5883      }
5884      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
5885      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5886          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
5887        EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5888                   (-offset & 0xff));
5889        AdvanceIT();
5890        return;
5891      }
5892      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
5893      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5894          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5895        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5896        uint32_t offset_ = abs(offset);
5897        EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5898                   offset_ | (sign << 9));
5899        AdvanceIT();
5900        return;
5901      }
5902      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
5903      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5904          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
5905        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5906        uint32_t offset_ = abs(offset);
5907        EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5908                   offset_ | (sign << 9));
5909        AdvanceIT();
5910        return;
5911      }
5912      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5913      if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5914          rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
5915        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5916        uint32_t offset_ = abs(offset);
5917        EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5918        AdvanceIT();
5919        return;
5920      }
5921    } else {
5922      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
5923      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5924          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5925        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5926        uint32_t offset_ = abs(offset);
5927        EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
5928                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5929                ((offset_ & 0xf0) << 4) | (sign << 23));
5930        return;
5931      }
5932      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
5933      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5934          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5935        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5936        uint32_t offset_ = abs(offset);
5937        EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
5938                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5939                ((offset_ & 0xf0) << 4) | (sign << 23));
5940        return;
5941      }
5942      // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
5943      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5944          cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
5945        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5946        uint32_t offset_ = abs(offset);
5947        EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
5948                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5949                ((offset_ & 0xf0) << 4) | (sign << 23));
5950        return;
5951      }
5952      // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5953      if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5954          operand.IsOffset() && cond.IsNotNever()) {
5955        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5956        uint32_t offset_ = abs(offset);
5957        EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
5958                (rt.GetCode() << 12) | (offset_ & 0xf) |
5959                ((offset_ & 0xf0) << 4) | (sign << 23));
5960        return;
5961      }
5962    }
5963  }
5964  if (operand.IsPlainRegister()) {
5965    Register rn = operand.GetBaseRegister();
5966    Sign sign = operand.GetSign();
5967    Register rm = operand.GetOffsetRegister();
5968    if (IsUsingT32()) {
5969      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5970      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5971          sign.IsPlus() && operand.IsOffset()) {
5972        EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
5973                   (rm.GetCode() << 6));
5974        AdvanceIT();
5975        return;
5976      }
5977    } else {
5978      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5979      if (operand.IsOffset() && cond.IsNotNever()) {
5980        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5981        EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
5982                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5983                (sign_ << 23));
5984        return;
5985      }
5986      // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5987      if (operand.IsPostIndex() && cond.IsNotNever()) {
5988        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5989        EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
5990                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5991                (sign_ << 23));
5992        return;
5993      }
5994      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5995      if (operand.IsPreIndex() && cond.IsNotNever()) {
5996        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5997        EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
5998                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5999                (sign_ << 23));
6000        return;
6001      }
6002    }
6003  }
6004  if (operand.IsShiftedRegister()) {
6005    Register rn = operand.GetBaseRegister();
6006    Sign sign = operand.GetSign();
6007    Register rm = operand.GetOffsetRegister();
6008    Shift shift = operand.GetShift();
6009    uint32_t amount = operand.GetShiftAmount();
6010    if (IsUsingT32()) {
6011      // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6012      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6013          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
6014        EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6015                   rm.GetCode() | (amount << 4));
6016        AdvanceIT();
6017        return;
6018      }
6019    }
6020  }
6021  Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6022}
6023
6024void Assembler::ldrsh(Condition cond, Register rt, Label* label) {
6025  VIXL_ASSERT(AllowAssembler());
6026  CheckIT(cond);
6027  Label::Offset offset =
6028      label->IsBound()
6029          ? label->GetLocation() -
6030                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6031          : 0;
6032  if (IsUsingT32()) {
6033    // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6034    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6035         !label->IsBound()) &&
6036        !rt.Is(pc)) {
6037      static class EmitOp : public Label::LabelEmitOperator {
6038       public:
6039        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
6040        virtual uint32_t Encode(uint32_t instr,
6041                                Label::Offset pc,
6042                                const Label* label) const VIXL_OVERRIDE {
6043          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
6044          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
6045          uint32_t U = (offset >= 0) && !label->IsMinusZero();
6046          int32_t target = abs(offset) | (U << 12);
6047          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6048        }
6049      } immop;
6050      EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12), label, immop));
6051      AdvanceIT();
6052      return;
6053    }
6054  } else {
6055    // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6056    if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
6057         !label->IsBound()) &&
6058        cond.IsNotNever()) {
6059      static class EmitOp : public Label::LabelEmitOperator {
6060       public:
6061        EmitOp() : Label::LabelEmitOperator(-255, 255) {}
6062        virtual uint32_t Encode(uint32_t instr,
6063                                Label::Offset pc,
6064                                const Label* label) const VIXL_OVERRIDE {
6065          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
6066          VIXL_ASSERT((offset >= -255) && (offset <= 255));
6067          uint32_t U = (offset >= 0) && !label->IsMinusZero();
6068          int32_t target = abs(offset) | (U << 8);
6069          return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6070                 ((target & 0x100) << 15);
6071        }
6072      } immop;
6073      EmitA32(
6074          Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6075               label,
6076               immop));
6077      return;
6078    }
6079  }
6080  Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, label);
6081}
6082
6083void Assembler::lsl(Condition cond,
6084                    EncodingSize size,
6085                    Register rd,
6086                    Register rm,
6087                    const Operand& operand) {
6088  VIXL_ASSERT(AllowAssembler());
6089  CheckIT(cond);
6090  if (operand.IsImmediate()) {
6091    uint32_t imm = operand.GetImmediate();
6092    if (IsUsingT32()) {
6093      // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6094      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6095          (imm >= 1) && (imm <= 31)) {
6096        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6097        AdvanceIT();
6098        return;
6099      }
6100      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6101      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
6102        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6103                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6104        AdvanceIT();
6105        return;
6106      }
6107    } else {
6108      // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6109      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6110        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6111                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6112        return;
6113      }
6114    }
6115  }
6116  if (operand.IsPlainRegister()) {
6117    Register rs = operand.GetBaseRegister();
6118    if (IsUsingT32()) {
6119      // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6120      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6121          rs.IsLow()) {
6122        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6123        AdvanceIT();
6124        return;
6125      }
6126      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6127      if (!size.IsNarrow()) {
6128        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6129                   rs.GetCode());
6130        AdvanceIT();
6131        return;
6132      }
6133    } else {
6134      // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6135      if (cond.IsNotNever()) {
6136        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6137                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6138        return;
6139      }
6140    }
6141  }
6142  Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6143}
6144
6145void Assembler::lsls(Condition cond,
6146                     EncodingSize size,
6147                     Register rd,
6148                     Register rm,
6149                     const Operand& operand) {
6150  VIXL_ASSERT(AllowAssembler());
6151  CheckIT(cond);
6152  if (operand.IsImmediate()) {
6153    uint32_t imm = operand.GetImmediate();
6154    if (IsUsingT32()) {
6155      // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6156      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6157          (imm >= 1) && (imm <= 31)) {
6158        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6159        AdvanceIT();
6160        return;
6161      }
6162      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6163      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
6164        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6165                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6166        AdvanceIT();
6167        return;
6168      }
6169    } else {
6170      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6171      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6172        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6173                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6174        return;
6175      }
6176    }
6177  }
6178  if (operand.IsPlainRegister()) {
6179    Register rs = operand.GetBaseRegister();
6180    if (IsUsingT32()) {
6181      // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6182      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6183          rs.IsLow()) {
6184        EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6185        AdvanceIT();
6186        return;
6187      }
6188      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6189      if (!size.IsNarrow()) {
6190        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6191                   rs.GetCode());
6192        AdvanceIT();
6193        return;
6194      }
6195    } else {
6196      // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6197      if (cond.IsNotNever()) {
6198        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6199                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6200        return;
6201      }
6202    }
6203  }
6204  Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6205}
6206
6207void Assembler::lsr(Condition cond,
6208                    EncodingSize size,
6209                    Register rd,
6210                    Register rm,
6211                    const Operand& operand) {
6212  VIXL_ASSERT(AllowAssembler());
6213  CheckIT(cond);
6214  if (operand.IsImmediate()) {
6215    uint32_t imm = operand.GetImmediate();
6216    if (IsUsingT32()) {
6217      // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6218      if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6219          (imm >= 1) && (imm <= 32)) {
6220        uint32_t amount_ = imm % 32;
6221        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6222                   (amount_ << 6));
6223        AdvanceIT();
6224        return;
6225      }
6226      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6227      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
6228        uint32_t amount_ = imm % 32;
6229        EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6230                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6231        AdvanceIT();
6232        return;
6233      }
6234    } else {
6235      // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6236      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6237        uint32_t amount_ = imm % 32;
6238        EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6239                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6240        return;
6241      }
6242    }
6243  }
6244  if (operand.IsPlainRegister()) {
6245    Register rs = operand.GetBaseRegister();
6246    if (IsUsingT32()) {
6247      // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6248      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6249          rs.IsLow()) {
6250        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6251        AdvanceIT();
6252        return;
6253      }
6254      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6255      if (!size.IsNarrow()) {
6256        EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6257                   rs.GetCode());
6258        AdvanceIT();
6259        return;
6260      }
6261    } else {
6262      // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6263      if (cond.IsNotNever()) {
6264        EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6265                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6266        return;
6267      }
6268    }
6269  }
6270  Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6271}
6272
6273void Assembler::lsrs(Condition cond,
6274                     EncodingSize size,
6275                     Register rd,
6276                     Register rm,
6277                     const Operand& operand) {
6278  VIXL_ASSERT(AllowAssembler());
6279  CheckIT(cond);
6280  if (operand.IsImmediate()) {
6281    uint32_t imm = operand.GetImmediate();
6282    if (IsUsingT32()) {
6283      // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6284      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6285          (imm >= 1) && (imm <= 32)) {
6286        uint32_t amount_ = imm % 32;
6287        EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6288                   (amount_ << 6));
6289        AdvanceIT();
6290        return;
6291      }
6292      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6293      if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
6294        uint32_t amount_ = imm % 32;
6295        EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6296                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6297        AdvanceIT();
6298        return;
6299      }
6300    } else {
6301      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6302      if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6303        uint32_t amount_ = imm % 32;
6304        EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6305                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6306        return;
6307      }
6308    }
6309  }
6310  if (operand.IsPlainRegister()) {
6311    Register rs = operand.GetBaseRegister();
6312    if (IsUsingT32()) {
6313      // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6314      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6315          rs.IsLow()) {
6316        EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6317        AdvanceIT();
6318        return;
6319      }
6320      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6321      if (!size.IsNarrow()) {
6322        EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6323                   rs.GetCode());
6324        AdvanceIT();
6325        return;
6326      }
6327    } else {
6328      // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6329      if (cond.IsNotNever()) {
6330        EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6331                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6332        return;
6333      }
6334    }
6335  }
6336  Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6337}
6338
6339void Assembler::mla(
6340    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6341  VIXL_ASSERT(AllowAssembler());
6342  CheckIT(cond);
6343  if (IsUsingT32()) {
6344    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6345    if (!ra.Is(pc)) {
6346      EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6347                 rm.GetCode() | (ra.GetCode() << 12));
6348      AdvanceIT();
6349      return;
6350    }
6351  } else {
6352    // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6353    if (cond.IsNotNever()) {
6354      EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6355              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6356      return;
6357    }
6358  }
6359  Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
6360}
6361
6362void Assembler::mlas(
6363    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6364  VIXL_ASSERT(AllowAssembler());
6365  CheckIT(cond);
6366  if (IsUsingA32()) {
6367    // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6368    if (cond.IsNotNever()) {
6369      EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6370              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6371      return;
6372    }
6373  }
6374  Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
6375}
6376
6377void Assembler::mls(
6378    Condition cond, Register rd, Register rn, Register rm, Register ra) {
6379  VIXL_ASSERT(AllowAssembler());
6380  CheckIT(cond);
6381  if (IsUsingT32()) {
6382    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6383    EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6384               rm.GetCode() | (ra.GetCode() << 12));
6385    AdvanceIT();
6386    return;
6387  } else {
6388    // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6389    if (cond.IsNotNever()) {
6390      EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6391              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6392      return;
6393    }
6394  }
6395  Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
6396}
6397
6398void Assembler::mov(Condition cond,
6399                    EncodingSize size,
6400                    Register rd,
6401                    const Operand& operand) {
6402  VIXL_ASSERT(AllowAssembler());
6403  CheckIT(cond);
6404  if (operand.IsImmediateShiftedRegister()) {
6405    Register rm = operand.GetBaseRegister();
6406    if (operand.IsPlainRegister()) {
6407      if (IsUsingT32()) {
6408        // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
6409        if (!size.IsWide() &&
6410            ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
6411             AllowUnpredictable())) {
6412          EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
6413                     ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
6414          AdvanceIT();
6415          return;
6416        }
6417      }
6418    }
6419    Shift shift = operand.GetShift();
6420    uint32_t amount = operand.GetShiftAmount();
6421    if (IsUsingT32()) {
6422      // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6423      if (InITBlock() && !size.IsWide() && rd.IsLow() &&
6424          shift.IsValidAmount(amount) && rm.IsLow() &&
6425          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
6426          ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
6427        uint32_t amount_ = amount % 32;
6428        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
6429                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
6430        AdvanceIT();
6431        return;
6432      }
6433      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
6434      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
6435          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6436        uint32_t amount_ = amount % 32;
6437        EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6438                   (operand.GetTypeEncodingValue() << 4) |
6439                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6440        AdvanceIT();
6441        return;
6442      }
6443    } else {
6444      // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6445      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6446        uint32_t amount_ = amount % 32;
6447        EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6448                (rd.GetCode() << 12) | rm.GetCode() |
6449                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6450        return;
6451      }
6452    }
6453  }
6454  if (operand.IsRegisterShiftedRegister()) {
6455    Register rm = operand.GetBaseRegister();
6456    Shift shift = operand.GetShift();
6457    if (IsUsingT32()) {
6458      // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
6459      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6460          shift.IsASR() && operand.GetShiftRegister().IsLow()) {
6461        EmitT32_16(0x4100 | rd.GetCode() |
6462                   (operand.GetShiftRegister().GetCode() << 3));
6463        AdvanceIT();
6464        return;
6465      }
6466      // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
6467      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6468          shift.IsLSL() && operand.GetShiftRegister().IsLow()) {
6469        EmitT32_16(0x4080 | rd.GetCode() |
6470                   (operand.GetShiftRegister().GetCode() << 3));
6471        AdvanceIT();
6472        return;
6473      }
6474      // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
6475      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6476          shift.IsLSR() && operand.GetShiftRegister().IsLow()) {
6477        EmitT32_16(0x40c0 | rd.GetCode() |
6478                   (operand.GetShiftRegister().GetCode() << 3));
6479        AdvanceIT();
6480        return;
6481      }
6482      // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
6483      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6484          shift.IsROR() && operand.GetShiftRegister().IsLow()) {
6485        EmitT32_16(0x41c0 | rd.GetCode() |
6486                   (operand.GetShiftRegister().GetCode() << 3));
6487        AdvanceIT();
6488        return;
6489      }
6490      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
6491      if (!size.IsNarrow() &&
6492          ((!rd.IsPC() && !rm.IsPC() && !operand.GetShiftRegister().IsPC()) ||
6493           AllowUnpredictable())) {
6494        EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6495                   (shift.GetType() << 21) |
6496                   operand.GetShiftRegister().GetCode());
6497        AdvanceIT();
6498        return;
6499      }
6500    } else {
6501      // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6502      if (cond.IsNotNever() &&
6503          ((!rd.IsPC() && !rm.IsPC() && !operand.GetShiftRegister().IsPC()) ||
6504           AllowUnpredictable())) {
6505        EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6506                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6507                (operand.GetShiftRegister().GetCode() << 8));
6508        return;
6509      }
6510    }
6511  }
6512  if (operand.IsImmediate()) {
6513    uint32_t imm = operand.GetImmediate();
6514    if (IsUsingT32()) {
6515      ImmediateT32 immediate_t32(imm);
6516      // MOV<c>{<q>} <Rd>, #<imm8> ; T1
6517      if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
6518        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
6519        AdvanceIT();
6520        return;
6521      }
6522      // MOV{<c>}{<q>} <Rd>, #<const> ; T2
6523      if (!size.IsNarrow() && immediate_t32.IsValid() &&
6524          (!rd.IsPC() || AllowUnpredictable())) {
6525        EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
6526                   (immediate_t32.GetEncodingValue() & 0xff) |
6527                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6528                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6529        AdvanceIT();
6530        return;
6531      }
6532      // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
6533      if (!size.IsNarrow() && (imm <= 65535) &&
6534          (!rd.IsPC() || AllowUnpredictable())) {
6535        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
6536                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6537                   ((imm & 0xf000) << 4));
6538        AdvanceIT();
6539        return;
6540      }
6541    } else {
6542      ImmediateA32 immediate_a32(imm);
6543      // MOV{<c>}{<q>} <Rd>, #<const> ; A1
6544      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6545        EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
6546                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6547        return;
6548      }
6549      // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
6550      if ((imm <= 65535) && cond.IsNotNever() &&
6551          (!rd.IsPC() || AllowUnpredictable())) {
6552        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
6553                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6554        return;
6555      }
6556    }
6557  }
6558  Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
6559}
6560
6561void Assembler::movs(Condition cond,
6562                     EncodingSize size,
6563                     Register rd,
6564                     const Operand& operand) {
6565  VIXL_ASSERT(AllowAssembler());
6566  CheckIT(cond);
6567  if (operand.IsImmediateShiftedRegister()) {
6568    Register rm = operand.GetBaseRegister();
6569    Shift shift = operand.GetShift();
6570    uint32_t amount = operand.GetShiftAmount();
6571    if (IsUsingT32()) {
6572      // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6573      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
6574          shift.IsValidAmount(amount) && rm.IsLow() &&
6575          (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
6576        uint32_t amount_ = amount % 32;
6577        EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
6578                   (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
6579        AdvanceIT();
6580        return;
6581      }
6582      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
6583      if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
6584          ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
6585        uint32_t amount_ = amount % 32;
6586        EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6587                   (operand.GetTypeEncodingValue() << 4) |
6588                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6589        AdvanceIT();
6590        return;
6591      }
6592    } else {
6593      // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6594      if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
6595          (!rd.IsPC() || AllowUnpredictable())) {
6596        uint32_t amount_ = amount % 32;
6597        EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6598                (rd.GetCode() << 12) | rm.GetCode() |
6599                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6600        return;
6601      }
6602    }
6603  }
6604  if (operand.IsRegisterShiftedRegister()) {
6605    Register rm = operand.GetBaseRegister();
6606    Shift shift = operand.GetShift();
6607    if (IsUsingT32()) {
6608      // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
6609      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6610          shift.IsASR() && operand.GetShiftRegister().IsLow()) {
6611        EmitT32_16(0x4100 | rd.GetCode() |
6612                   (operand.GetShiftRegister().GetCode() << 3));
6613        AdvanceIT();
6614        return;
6615      }
6616      // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
6617      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6618          shift.IsLSL() && operand.GetShiftRegister().IsLow()) {
6619        EmitT32_16(0x4080 | rd.GetCode() |
6620                   (operand.GetShiftRegister().GetCode() << 3));
6621        AdvanceIT();
6622        return;
6623      }
6624      // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
6625      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6626          shift.IsLSR() && operand.GetShiftRegister().IsLow()) {
6627        EmitT32_16(0x40c0 | rd.GetCode() |
6628                   (operand.GetShiftRegister().GetCode() << 3));
6629        AdvanceIT();
6630        return;
6631      }
6632      // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
6633      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6634          shift.IsROR() && operand.GetShiftRegister().IsLow()) {
6635        EmitT32_16(0x41c0 | rd.GetCode() |
6636                   (operand.GetShiftRegister().GetCode() << 3));
6637        AdvanceIT();
6638        return;
6639      }
6640      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
6641      if (!size.IsNarrow() &&
6642          ((!rd.IsPC() && !rm.IsPC() && !operand.GetShiftRegister().IsPC()) ||
6643           AllowUnpredictable())) {
6644        EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6645                   (shift.GetType() << 21) |
6646                   operand.GetShiftRegister().GetCode());
6647        AdvanceIT();
6648        return;
6649      }
6650    } else {
6651      // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6652      if (cond.IsNotNever() &&
6653          ((!rd.IsPC() && !rm.IsPC() && !operand.GetShiftRegister().IsPC()) ||
6654           AllowUnpredictable())) {
6655        EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6656                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6657                (operand.GetShiftRegister().GetCode() << 8));
6658        return;
6659      }
6660    }
6661  }
6662  if (operand.IsImmediate()) {
6663    uint32_t imm = operand.GetImmediate();
6664    if (IsUsingT32()) {
6665      ImmediateT32 immediate_t32(imm);
6666      // MOVS{<q>} <Rd>, #<imm8> ; T1
6667      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
6668        EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
6669        AdvanceIT();
6670        return;
6671      }
6672      // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
6673      if (!size.IsNarrow() && immediate_t32.IsValid() &&
6674          (!rd.IsPC() || AllowUnpredictable())) {
6675        EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
6676                   (immediate_t32.GetEncodingValue() & 0xff) |
6677                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6678                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6679        AdvanceIT();
6680        return;
6681      }
6682    } else {
6683      ImmediateA32 immediate_a32(imm);
6684      // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
6685      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6686        EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
6687                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6688        return;
6689      }
6690    }
6691  }
6692  Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
6693}
6694
6695void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
6696  VIXL_ASSERT(AllowAssembler());
6697  CheckIT(cond);
6698  if (operand.IsImmediate()) {
6699    uint32_t imm = operand.GetImmediate();
6700    if (IsUsingT32()) {
6701      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
6702      if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
6703        EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
6704                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6705                   ((imm & 0xf000) << 4));
6706        AdvanceIT();
6707        return;
6708      }
6709    } else {
6710      // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
6711      if ((imm <= 65535) && cond.IsNotNever() &&
6712          (!rd.IsPC() || AllowUnpredictable())) {
6713        EmitA32(0x03400000U | (cond.GetCondition() << 28) |
6714                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6715        return;
6716      }
6717    }
6718  }
6719  Delegate(kMovt, &Assembler::movt, cond, rd, operand);
6720}
6721
6722void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
6723  VIXL_ASSERT(AllowAssembler());
6724  CheckIT(cond);
6725  if (operand.IsImmediate()) {
6726    uint32_t imm = operand.GetImmediate();
6727    if (IsUsingT32()) {
6728      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
6729      if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
6730        EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
6731                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6732                   ((imm & 0xf000) << 4));
6733        AdvanceIT();
6734        return;
6735      }
6736    } else {
6737      // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
6738      if ((imm <= 65535) && cond.IsNotNever() &&
6739          (!rd.IsPC() || AllowUnpredictable())) {
6740        EmitA32(0x03000000U | (cond.GetCondition() << 28) |
6741                (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6742        return;
6743      }
6744    }
6745  }
6746  Delegate(kMovw, &Assembler::movw, cond, rd, operand);
6747}
6748
6749void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
6750  VIXL_ASSERT(AllowAssembler());
6751  CheckIT(cond);
6752  if (IsUsingT32()) {
6753    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
6754    EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
6755    AdvanceIT();
6756    return;
6757  } else {
6758    // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
6759    if (cond.IsNotNever()) {
6760      EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
6761              (spec_reg.GetReg() << 22));
6762      return;
6763    }
6764  }
6765  Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
6766}
6767
6768void Assembler::msr(Condition cond,
6769                    MaskedSpecialRegister spec_reg,
6770                    const Operand& operand) {
6771  VIXL_ASSERT(AllowAssembler());
6772  CheckIT(cond);
6773  if (operand.IsImmediate()) {
6774    uint32_t imm = operand.GetImmediate();
6775    if (IsUsingA32()) {
6776      ImmediateA32 immediate_a32(imm);
6777      // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
6778      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6779        EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
6780                ((spec_reg.GetReg() & 0xf) << 16) |
6781                ((spec_reg.GetReg() & 0x10) << 18) |
6782                immediate_a32.GetEncodingValue());
6783        return;
6784      }
6785    }
6786  }
6787  if (operand.IsPlainRegister()) {
6788    Register rn = operand.GetBaseRegister();
6789    if (IsUsingT32()) {
6790      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
6791      EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
6792                 ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
6793      AdvanceIT();
6794      return;
6795    } else {
6796      // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
6797      if (cond.IsNotNever()) {
6798        EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
6799                ((spec_reg.GetReg() & 0xf) << 16) |
6800                ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
6801        return;
6802      }
6803    }
6804  }
6805  Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
6806}
6807
6808void Assembler::mul(
6809    Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
6810  VIXL_ASSERT(AllowAssembler());
6811  CheckIT(cond);
6812  if (IsUsingT32()) {
6813    // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
6814    if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
6815        rm.IsLow()) {
6816      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
6817      AdvanceIT();
6818      return;
6819    }
6820    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
6821    if (!size.IsNarrow()) {
6822      EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6823                 rm.GetCode());
6824      AdvanceIT();
6825      return;
6826    }
6827  } else {
6828    // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
6829    if (cond.IsNotNever()) {
6830      EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6831              rn.GetCode() | (rm.GetCode() << 8));
6832      return;
6833    }
6834  }
6835  Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
6836}
6837
6838void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
6839  VIXL_ASSERT(AllowAssembler());
6840  CheckIT(cond);
6841  if (IsUsingT32()) {
6842    // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
6843    if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
6844      EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
6845      AdvanceIT();
6846      return;
6847    }
6848  } else {
6849    // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
6850    if (cond.IsNotNever()) {
6851      EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6852              rn.GetCode() | (rm.GetCode() << 8));
6853      return;
6854    }
6855  }
6856  Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
6857}
6858
6859void Assembler::mvn(Condition cond,
6860                    EncodingSize size,
6861                    Register rd,
6862                    const Operand& operand) {
6863  VIXL_ASSERT(AllowAssembler());
6864  CheckIT(cond);
6865  if (operand.IsImmediate()) {
6866    uint32_t imm = operand.GetImmediate();
6867    if (IsUsingT32()) {
6868      ImmediateT32 immediate_t32(imm);
6869      // MVN{<c>}{<q>} <Rd>, #<const> ; T1
6870      if (!size.IsNarrow() && immediate_t32.IsValid()) {
6871        EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
6872                   (immediate_t32.GetEncodingValue() & 0xff) |
6873                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6874                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6875        AdvanceIT();
6876        return;
6877      }
6878    } else {
6879      ImmediateA32 immediate_a32(imm);
6880      // MVN{<c>}{<q>} <Rd>, #<const> ; A1
6881      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6882        EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
6883                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6884        return;
6885      }
6886    }
6887  }
6888  if (operand.IsImmediateShiftedRegister()) {
6889    Register rm = operand.GetBaseRegister();
6890    if (operand.IsPlainRegister()) {
6891      if (IsUsingT32()) {
6892        // MVN<c>{<q>} <Rd>, <Rm> ; T1
6893        if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
6894          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
6895          AdvanceIT();
6896          return;
6897        }
6898      }
6899    }
6900    Shift shift = operand.GetShift();
6901    uint32_t amount = operand.GetShiftAmount();
6902    if (IsUsingT32()) {
6903      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6904      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6905        uint32_t amount_ = amount % 32;
6906        EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6907                   (operand.GetTypeEncodingValue() << 4) |
6908                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6909        AdvanceIT();
6910        return;
6911      }
6912    } else {
6913      // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6914      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6915        uint32_t amount_ = amount % 32;
6916        EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
6917                (rd.GetCode() << 12) | rm.GetCode() |
6918                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6919        return;
6920      }
6921    }
6922  }
6923  if (operand.IsRegisterShiftedRegister()) {
6924    Register rm = operand.GetBaseRegister();
6925    Shift shift = operand.GetShift();
6926    if (IsUsingA32()) {
6927      // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6928      if (cond.IsNotNever()) {
6929        EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
6930                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6931                (operand.GetShiftRegister().GetCode() << 8));
6932        return;
6933      }
6934    }
6935  }
6936  Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
6937}
6938
6939void Assembler::mvns(Condition cond,
6940                     EncodingSize size,
6941                     Register rd,
6942                     const Operand& operand) {
6943  VIXL_ASSERT(AllowAssembler());
6944  CheckIT(cond);
6945  if (operand.IsImmediate()) {
6946    uint32_t imm = operand.GetImmediate();
6947    if (IsUsingT32()) {
6948      ImmediateT32 immediate_t32(imm);
6949      // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
6950      if (!size.IsNarrow() && immediate_t32.IsValid()) {
6951        EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
6952                   (immediate_t32.GetEncodingValue() & 0xff) |
6953                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6954                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6955        AdvanceIT();
6956        return;
6957      }
6958    } else {
6959      ImmediateA32 immediate_a32(imm);
6960      // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
6961      if (immediate_a32.IsValid() && cond.IsNotNever()) {
6962        EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
6963                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6964        return;
6965      }
6966    }
6967  }
6968  if (operand.IsImmediateShiftedRegister()) {
6969    Register rm = operand.GetBaseRegister();
6970    if (operand.IsPlainRegister()) {
6971      if (IsUsingT32()) {
6972        // MVNS{<q>} <Rd>, <Rm> ; T1
6973        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
6974          EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
6975          AdvanceIT();
6976          return;
6977        }
6978      }
6979    }
6980    Shift shift = operand.GetShift();
6981    uint32_t amount = operand.GetShiftAmount();
6982    if (IsUsingT32()) {
6983      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6984      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6985        uint32_t amount_ = amount % 32;
6986        EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6987                   (operand.GetTypeEncodingValue() << 4) |
6988                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6989        AdvanceIT();
6990        return;
6991      }
6992    } else {
6993      // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6994      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6995        uint32_t amount_ = amount % 32;
6996        EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
6997                (rd.GetCode() << 12) | rm.GetCode() |
6998                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6999        return;
7000      }
7001    }
7002  }
7003  if (operand.IsRegisterShiftedRegister()) {
7004    Register rm = operand.GetBaseRegister();
7005    Shift shift = operand.GetShift();
7006    if (IsUsingA32()) {
7007      // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7008      if (cond.IsNotNever()) {
7009        EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7010                (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7011                (operand.GetShiftRegister().GetCode() << 8));
7012        return;
7013      }
7014    }
7015  }
7016  Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7017}
7018
7019void Assembler::nop(Condition cond, EncodingSize size) {
7020  VIXL_ASSERT(AllowAssembler());
7021  CheckIT(cond);
7022  if (IsUsingT32()) {
7023    // NOP{<c>}{<q>} ; T1
7024    if (!size.IsWide()) {
7025      EmitT32_16(0xbf00);
7026      AdvanceIT();
7027      return;
7028    }
7029    // NOP{<c>}.W ; T2
7030    if (!size.IsNarrow()) {
7031      EmitT32_32(0xf3af8000U);
7032      AdvanceIT();
7033      return;
7034    }
7035  } else {
7036    // NOP{<c>}{<q>} ; A1
7037    if (cond.IsNotNever()) {
7038      EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7039      return;
7040    }
7041  }
7042  Delegate(kNop, &Assembler::nop, cond, size);
7043}
7044
7045void Assembler::orn(Condition cond,
7046                    Register rd,
7047                    Register rn,
7048                    const Operand& operand) {
7049  VIXL_ASSERT(AllowAssembler());
7050  CheckIT(cond);
7051  if (operand.IsImmediate()) {
7052    uint32_t imm = operand.GetImmediate();
7053    if (IsUsingT32()) {
7054      ImmediateT32 immediate_t32(imm);
7055      // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7056      if (immediate_t32.IsValid() && !rn.Is(pc)) {
7057        EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7058                   (immediate_t32.GetEncodingValue() & 0xff) |
7059                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7060                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7061        AdvanceIT();
7062        return;
7063      }
7064    }
7065  }
7066  if (operand.IsImmediateShiftedRegister()) {
7067    Register rm = operand.GetBaseRegister();
7068    Shift shift = operand.GetShift();
7069    uint32_t amount = operand.GetShiftAmount();
7070    if (IsUsingT32()) {
7071      // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7072      if (shift.IsValidAmount(amount) && !rn.Is(pc)) {
7073        uint32_t amount_ = amount % 32;
7074        EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7075                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7076                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7077        AdvanceIT();
7078        return;
7079      }
7080    }
7081  }
7082  Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7083}
7084
7085void Assembler::orns(Condition cond,
7086                     Register rd,
7087                     Register rn,
7088                     const Operand& operand) {
7089  VIXL_ASSERT(AllowAssembler());
7090  CheckIT(cond);
7091  if (operand.IsImmediate()) {
7092    uint32_t imm = operand.GetImmediate();
7093    if (IsUsingT32()) {
7094      ImmediateT32 immediate_t32(imm);
7095      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7096      if (immediate_t32.IsValid() && !rn.Is(pc)) {
7097        EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7098                   (immediate_t32.GetEncodingValue() & 0xff) |
7099                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7100                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7101        AdvanceIT();
7102        return;
7103      }
7104    }
7105  }
7106  if (operand.IsImmediateShiftedRegister()) {
7107    Register rm = operand.GetBaseRegister();
7108    Shift shift = operand.GetShift();
7109    uint32_t amount = operand.GetShiftAmount();
7110    if (IsUsingT32()) {
7111      // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7112      if (shift.IsValidAmount(amount) && !rn.Is(pc)) {
7113        uint32_t amount_ = amount % 32;
7114        EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7115                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7116                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7117        AdvanceIT();
7118        return;
7119      }
7120    }
7121  }
7122  Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7123}
7124
7125void Assembler::orr(Condition cond,
7126                    EncodingSize size,
7127                    Register rd,
7128                    Register rn,
7129                    const Operand& operand) {
7130  VIXL_ASSERT(AllowAssembler());
7131  CheckIT(cond);
7132  if (operand.IsImmediate()) {
7133    uint32_t imm = operand.GetImmediate();
7134    if (IsUsingT32()) {
7135      ImmediateT32 immediate_t32(imm);
7136      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7137      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc)) {
7138        EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7139                   (immediate_t32.GetEncodingValue() & 0xff) |
7140                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7141                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7142        AdvanceIT();
7143        return;
7144      }
7145    } else {
7146      ImmediateA32 immediate_a32(imm);
7147      // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7148      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7149        EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7150                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7151                immediate_a32.GetEncodingValue());
7152        return;
7153      }
7154    }
7155  }
7156  if (operand.IsImmediateShiftedRegister()) {
7157    Register rm = operand.GetBaseRegister();
7158    if (operand.IsPlainRegister()) {
7159      if (IsUsingT32()) {
7160        // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7161        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7162            rm.IsLow()) {
7163          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7164          AdvanceIT();
7165          return;
7166        }
7167      }
7168    }
7169    Shift shift = operand.GetShift();
7170    uint32_t amount = operand.GetShiftAmount();
7171    if (IsUsingT32()) {
7172      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7173      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc)) {
7174        uint32_t amount_ = amount % 32;
7175        EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7176                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7177                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7178        AdvanceIT();
7179        return;
7180      }
7181    } else {
7182      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7183      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7184        uint32_t amount_ = amount % 32;
7185        EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7186                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7187                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7188        return;
7189      }
7190    }
7191  }
7192  if (operand.IsRegisterShiftedRegister()) {
7193    Register rm = operand.GetBaseRegister();
7194    Shift shift = operand.GetShift();
7195    if (IsUsingA32()) {
7196      // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7197      if (cond.IsNotNever()) {
7198        EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7199                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7200                (shift.GetType() << 5) |
7201                (operand.GetShiftRegister().GetCode() << 8));
7202        return;
7203      }
7204    }
7205  }
7206  Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7207}
7208
7209void Assembler::orrs(Condition cond,
7210                     EncodingSize size,
7211                     Register rd,
7212                     Register rn,
7213                     const Operand& operand) {
7214  VIXL_ASSERT(AllowAssembler());
7215  CheckIT(cond);
7216  if (operand.IsImmediate()) {
7217    uint32_t imm = operand.GetImmediate();
7218    if (IsUsingT32()) {
7219      ImmediateT32 immediate_t32(imm);
7220      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7221      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc)) {
7222        EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7223                   (immediate_t32.GetEncodingValue() & 0xff) |
7224                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7225                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7226        AdvanceIT();
7227        return;
7228      }
7229    } else {
7230      ImmediateA32 immediate_a32(imm);
7231      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7232      if (immediate_a32.IsValid() && cond.IsNotNever()) {
7233        EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7234                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7235                immediate_a32.GetEncodingValue());
7236        return;
7237      }
7238    }
7239  }
7240  if (operand.IsImmediateShiftedRegister()) {
7241    Register rm = operand.GetBaseRegister();
7242    if (operand.IsPlainRegister()) {
7243      if (IsUsingT32()) {
7244        // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7245        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7246            rm.IsLow()) {
7247          EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7248          AdvanceIT();
7249          return;
7250        }
7251      }
7252    }
7253    Shift shift = operand.GetShift();
7254    uint32_t amount = operand.GetShiftAmount();
7255    if (IsUsingT32()) {
7256      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7257      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc)) {
7258        uint32_t amount_ = amount % 32;
7259        EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7260                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7261                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7262        AdvanceIT();
7263        return;
7264      }
7265    } else {
7266      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7267      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7268        uint32_t amount_ = amount % 32;
7269        EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7270                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7271                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7272        return;
7273      }
7274    }
7275  }
7276  if (operand.IsRegisterShiftedRegister()) {
7277    Register rm = operand.GetBaseRegister();
7278    Shift shift = operand.GetShift();
7279    if (IsUsingA32()) {
7280      // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7281      if (cond.IsNotNever()) {
7282        EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7283                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7284                (shift.GetType() << 5) |
7285                (operand.GetShiftRegister().GetCode() << 8));
7286        return;
7287      }
7288    }
7289  }
7290  Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7291}
7292
7293void Assembler::pkhbt(Condition cond,
7294                      Register rd,
7295                      Register rn,
7296                      const Operand& operand) {
7297  VIXL_ASSERT(AllowAssembler());
7298  CheckIT(cond);
7299  if (operand.IsImmediateShiftedRegister()) {
7300    Register rm = operand.GetBaseRegister();
7301    Shift shift = operand.GetShift();
7302    uint32_t amount = operand.GetShiftAmount();
7303    if (IsUsingT32()) {
7304      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
7305      if (shift.IsLSL() && shift.IsValidAmount(amount)) {
7306        EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7307                   rm.GetCode() | ((amount & 0x3) << 6) |
7308                   ((amount & 0x1c) << 10));
7309        AdvanceIT();
7310        return;
7311      }
7312    } else {
7313      // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
7314      if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever()) {
7315        EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7316                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7317                (amount << 7));
7318        return;
7319      }
7320    }
7321  }
7322  Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7323}
7324
7325void Assembler::pkhtb(Condition cond,
7326                      Register rd,
7327                      Register rn,
7328                      const Operand& operand) {
7329  VIXL_ASSERT(AllowAssembler());
7330  CheckIT(cond);
7331  if (operand.IsImmediateShiftedRegister()) {
7332    Register rm = operand.GetBaseRegister();
7333    Shift shift = operand.GetShift();
7334    uint32_t amount = operand.GetShiftAmount();
7335    if (IsUsingT32()) {
7336      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
7337      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount)) {
7338        uint32_t amount_ = amount % 32;
7339        EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7340                   rm.GetCode() | ((amount_ & 0x3) << 6) |
7341                   ((amount_ & 0x1c) << 10));
7342        AdvanceIT();
7343        return;
7344      }
7345    } else {
7346      // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
7347      if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7348          cond.IsNotNever()) {
7349        uint32_t amount_ = amount % 32;
7350        EmitA32(0x06800050U | (cond.GetCondition() << 28) |
7351                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7352                (amount_ << 7));
7353        return;
7354      }
7355    }
7356  }
7357  Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
7358}
7359
7360void Assembler::pld(Condition cond, Label* label) {
7361  VIXL_ASSERT(AllowAssembler());
7362  CheckIT(cond);
7363  Label::Offset offset =
7364      label->IsBound()
7365          ? label->GetLocation() -
7366                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
7367          : 0;
7368  if (IsUsingT32()) {
7369    // PLD{<c>}{<q>} <label> ; T1
7370    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7371         !label->IsBound())) {
7372      static class EmitOp : public Label::LabelEmitOperator {
7373       public:
7374        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7375        virtual uint32_t Encode(uint32_t instr,
7376                                Label::Offset pc,
7377                                const Label* label) const VIXL_OVERRIDE {
7378          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7379          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7380          uint32_t U = (offset >= 0) && !label->IsMinusZero();
7381          int32_t target = abs(offset) | (U << 12);
7382          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7383        }
7384      } immop;
7385      EmitT32_32(Link(0xf81ff000U, label, immop));
7386      AdvanceIT();
7387      return;
7388    }
7389  } else {
7390    // PLD{<c>}{<q>} <label> ; A1
7391    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7392         !label->IsBound())) {
7393      if (cond.Is(al)) {
7394        static class EmitOp : public Label::LabelEmitOperator {
7395         public:
7396          EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7397          virtual uint32_t Encode(uint32_t instr,
7398                                  Label::Offset pc,
7399                                  const Label* label) const VIXL_OVERRIDE {
7400            Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7401            VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7402            uint32_t U = (offset >= 0) && !label->IsMinusZero();
7403            int32_t target = abs(offset) | (U << 12);
7404            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7405          }
7406        } immop;
7407        EmitA32(Link(0xf55ff000U, label, immop));
7408        return;
7409      }
7410    }
7411  }
7412  Delegate(kPld, &Assembler::pld, cond, label);
7413}
7414
7415void Assembler::pld(Condition cond, const MemOperand& operand) {
7416  VIXL_ASSERT(AllowAssembler());
7417  CheckIT(cond);
7418  if (operand.IsImmediate()) {
7419    Register rn = operand.GetBaseRegister();
7420    int32_t offset = operand.GetOffsetImmediate();
7421    if (IsUsingT32()) {
7422      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
7423      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
7424          operand.IsOffset()) {
7425        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7426        uint32_t offset_ = abs(offset);
7427        EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
7428        AdvanceIT();
7429        return;
7430      }
7431    } else {
7432      // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
7433      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
7434          operand.IsOffset()) {
7435        if (cond.Is(al)) {
7436          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7437          uint32_t offset_ = abs(offset);
7438          EmitA32(0xf55ff000U | offset_ | (sign << 23));
7439          return;
7440        }
7441      }
7442    }
7443  }
7444  if (operand.IsImmediate()) {
7445    Register rn = operand.GetBaseRegister();
7446    int32_t offset = operand.GetOffsetImmediate();
7447    if (IsUsingT32()) {
7448      // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7449      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
7450          ((rn.GetCode() & 0xf) != 0xf)) {
7451        EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7452        AdvanceIT();
7453        return;
7454      }
7455      // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7456      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
7457          ((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) && operand.IsOffset() &&
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.IsOffset() &&
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) && operand.IsOffset()) {
7493        if (cond.Is(al)) {
7494          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7495          uint32_t amount_ = amount % 32;
7496          EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
7497                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7498          return;
7499        }
7500      }
7501      // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7502      if (shift.IsRRX() && operand.IsOffset()) {
7503        if (cond.Is(al)) {
7504          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7505          EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
7506                  (sign_ << 23));
7507          return;
7508        }
7509      }
7510    }
7511  }
7512  Delegate(kPld, &Assembler::pld, cond, operand);
7513}
7514
7515void Assembler::pldw(Condition cond, const MemOperand& operand) {
7516  VIXL_ASSERT(AllowAssembler());
7517  CheckIT(cond);
7518  if (operand.IsImmediate()) {
7519    Register rn = operand.GetBaseRegister();
7520    int32_t offset = operand.GetOffsetImmediate();
7521    if (IsUsingT32()) {
7522      // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7523      if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
7524          ((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) && operand.IsOffset() &&
7531          ((rn.GetCode() & 0xf) != 0xf)) {
7532        EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7533        AdvanceIT();
7534        return;
7535      }
7536    } else {
7537      // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
7538      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
7539          ((rn.GetCode() & 0xf) != 0xf)) {
7540        if (cond.Is(al)) {
7541          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7542          uint32_t offset_ = abs(offset);
7543          EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7544          return;
7545        }
7546      }
7547    }
7548  }
7549  if (operand.IsShiftedRegister()) {
7550    Register rn = operand.GetBaseRegister();
7551    Sign sign = operand.GetSign();
7552    Register rm = operand.GetOffsetRegister();
7553    Shift shift = operand.GetShift();
7554    uint32_t amount = operand.GetShiftAmount();
7555    if (IsUsingT32()) {
7556      // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7557      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
7558          ((rn.GetCode() & 0xf) != 0xf)) {
7559        EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
7560                   (amount << 4));
7561        AdvanceIT();
7562        return;
7563      }
7564    } else {
7565      // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7566      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset()) {
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.IsOffset()) {
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) && operand.IsOffset() &&
7598          ((rn.GetCode() & 0xf) != 0xf)) {
7599        EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7600        AdvanceIT();
7601        return;
7602      }
7603      // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7604      if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
7605          ((rn.GetCode() & 0xf) != 0xf)) {
7606        EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7607        AdvanceIT();
7608        return;
7609      }
7610    } else {
7611      // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
7612      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
7613          ((rn.GetCode() & 0xf) != 0xf)) {
7614        if (cond.Is(al)) {
7615          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7616          uint32_t offset_ = abs(offset);
7617          EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7618          return;
7619        }
7620      }
7621    }
7622  }
7623  if (operand.IsImmediate()) {
7624    Register rn = operand.GetBaseRegister();
7625    int32_t offset = operand.GetOffsetImmediate();
7626    if (IsUsingT32()) {
7627      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
7628      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
7629          operand.IsOffset()) {
7630        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7631        uint32_t offset_ = abs(offset);
7632        EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
7633        AdvanceIT();
7634        return;
7635      }
7636    } else {
7637      // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
7638      if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
7639          operand.IsOffset()) {
7640        if (cond.Is(al)) {
7641          uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7642          uint32_t offset_ = abs(offset);
7643          EmitA32(0xf45ff000U | offset_ | (sign << 23));
7644          return;
7645        }
7646      }
7647    }
7648  }
7649  if (operand.IsShiftedRegister()) {
7650    Register rn = operand.GetBaseRegister();
7651    Sign sign = operand.GetSign();
7652    Register rm = operand.GetOffsetRegister();
7653    Shift shift = operand.GetShift();
7654    uint32_t amount = operand.GetShiftAmount();
7655    if (IsUsingT32()) {
7656      // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7657      if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
7658          ((rn.GetCode() & 0xf) != 0xf)) {
7659        EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
7660                   (amount << 4));
7661        AdvanceIT();
7662        return;
7663      }
7664    } else {
7665      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7666      if (shift.IsRRX() && operand.IsOffset()) {
7667        if (cond.Is(al)) {
7668          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7669          EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
7670                  (sign_ << 23));
7671          return;
7672        }
7673      }
7674      // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7675      if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset()) {
7676        if (cond.Is(al)) {
7677          uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7678          uint32_t amount_ = amount % 32;
7679          EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
7680                  (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7681          return;
7682        }
7683      }
7684    }
7685  }
7686  Delegate(kPli, &Assembler::pli, cond, operand);
7687}
7688
7689void Assembler::pli(Condition cond, Label* label) {
7690  VIXL_ASSERT(AllowAssembler());
7691  CheckIT(cond);
7692  Label::Offset offset =
7693      label->IsBound()
7694          ? label->GetLocation() -
7695                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
7696          : 0;
7697  if (IsUsingT32()) {
7698    // PLI{<c>}{<q>} <label> ; T3
7699    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7700         !label->IsBound())) {
7701      static class EmitOp : public Label::LabelEmitOperator {
7702       public:
7703        EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7704        virtual uint32_t Encode(uint32_t instr,
7705                                Label::Offset pc,
7706                                const Label* label) const VIXL_OVERRIDE {
7707          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7708          VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7709          uint32_t U = (offset >= 0) && !label->IsMinusZero();
7710          int32_t target = abs(offset) | (U << 12);
7711          return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7712        }
7713      } immop;
7714      EmitT32_32(Link(0xf91ff000U, label, immop));
7715      AdvanceIT();
7716      return;
7717    }
7718  } else {
7719    // PLI{<c>}{<q>} <label> ; A1
7720    if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7721         !label->IsBound())) {
7722      if (cond.Is(al)) {
7723        static class EmitOp : public Label::LabelEmitOperator {
7724         public:
7725          EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
7726          virtual uint32_t Encode(uint32_t instr,
7727                                  Label::Offset pc,
7728                                  const Label* label) const VIXL_OVERRIDE {
7729            Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7730            VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7731            uint32_t U = (offset >= 0) && !label->IsMinusZero();
7732            int32_t target = abs(offset) | (U << 12);
7733            return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7734          }
7735        } immop;
7736        EmitA32(Link(0xf45ff000U, label, immop));
7737        return;
7738      }
7739    }
7740  }
7741  Delegate(kPli, &Assembler::pli, cond, label);
7742}
7743
7744void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
7745  VIXL_ASSERT(AllowAssembler());
7746  CheckIT(cond);
7747  if (IsUsingT32()) {
7748    // POP{<c>}{<q>} <registers> ; T1
7749    if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
7750      EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
7751                 GetRegisterListEncoding(registers, 0, 8));
7752      AdvanceIT();
7753      return;
7754    }
7755    // POP{<c>}{<q>} <registers> ; T2
7756    if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
7757      EmitT32_32(0xe8bd0000U |
7758                 (GetRegisterListEncoding(registers, 15, 1) << 15) |
7759                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
7760                 GetRegisterListEncoding(registers, 0, 13));
7761      AdvanceIT();
7762      return;
7763    }
7764  } else {
7765    // POP{<c>}{<q>} <registers> ; A1
7766    if (cond.IsNotNever()) {
7767      EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
7768              GetRegisterListEncoding(registers, 0, 16));
7769      return;
7770    }
7771  }
7772  Delegate(kPop, &Assembler::pop, cond, size, registers);
7773}
7774
7775void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
7776  VIXL_ASSERT(AllowAssembler());
7777  CheckIT(cond);
7778  if (IsUsingT32()) {
7779    // POP{<c>}{<q>} <single_register_list> ; T4
7780    if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) {
7781      EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
7782      AdvanceIT();
7783      return;
7784    }
7785  } else {
7786    // POP{<c>}{<q>} <single_register_list> ; A1
7787    if (cond.IsNotNever()) {
7788      EmitA32(0x049d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
7789      return;
7790    }
7791  }
7792  Delegate(kPop, &Assembler::pop, cond, size, rt);
7793}
7794
7795void Assembler::push(Condition cond,
7796                     EncodingSize size,
7797                     RegisterList registers) {
7798  VIXL_ASSERT(AllowAssembler());
7799  CheckIT(cond);
7800  if (IsUsingT32()) {
7801    // PUSH{<c>}{<q>} <registers> ; T1
7802    if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
7803      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
7804                 GetRegisterListEncoding(registers, 0, 8));
7805      AdvanceIT();
7806      return;
7807    }
7808    // PUSH{<c>}{<q>} <registers> ; T1
7809    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
7810      EmitT32_32(0xe92d0000U |
7811                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
7812                 GetRegisterListEncoding(registers, 0, 13));
7813      AdvanceIT();
7814      return;
7815    }
7816  } else {
7817    // PUSH{<c>}{<q>} <registers> ; A1
7818    if (cond.IsNotNever()) {
7819      EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
7820              GetRegisterListEncoding(registers, 0, 16));
7821      return;
7822    }
7823  }
7824  Delegate(kPush, &Assembler::push, cond, size, registers);
7825}
7826
7827void Assembler::push(Condition cond, EncodingSize size, Register rt) {
7828  VIXL_ASSERT(AllowAssembler());
7829  CheckIT(cond);
7830  if (IsUsingT32()) {
7831    // PUSH{<c>}{<q>} <single_register_list> ; T4
7832    if (!size.IsNarrow()) {
7833      EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
7834      AdvanceIT();
7835      return;
7836    }
7837  } else {
7838    // PUSH{<c>}{<q>} <single_register_list> ; A1
7839    if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
7840      EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
7841      return;
7842    }
7843  }
7844  Delegate(kPush, &Assembler::push, cond, size, rt);
7845}
7846
7847void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
7848  VIXL_ASSERT(AllowAssembler());
7849  CheckIT(cond);
7850  if (IsUsingT32()) {
7851    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7852    EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
7853               (rn.GetCode() << 16));
7854    AdvanceIT();
7855    return;
7856  } else {
7857    // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7858    if (cond.IsNotNever()) {
7859      EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7860              rm.GetCode() | (rn.GetCode() << 16));
7861      return;
7862    }
7863  }
7864  Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
7865}
7866
7867void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
7868  VIXL_ASSERT(AllowAssembler());
7869  CheckIT(cond);
7870  if (IsUsingT32()) {
7871    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7872    EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7873               rm.GetCode());
7874    AdvanceIT();
7875    return;
7876  } else {
7877    // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7878    if (cond.IsNotNever()) {
7879      EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7880              (rn.GetCode() << 16) | rm.GetCode());
7881      return;
7882    }
7883  }
7884  Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
7885}
7886
7887void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
7888  VIXL_ASSERT(AllowAssembler());
7889  CheckIT(cond);
7890  if (IsUsingT32()) {
7891    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7892    EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7893               rm.GetCode());
7894    AdvanceIT();
7895    return;
7896  } else {
7897    // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7898    if (cond.IsNotNever()) {
7899      EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7900              (rn.GetCode() << 16) | rm.GetCode());
7901      return;
7902    }
7903  }
7904  Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
7905}
7906
7907void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
7908  VIXL_ASSERT(AllowAssembler());
7909  CheckIT(cond);
7910  if (IsUsingT32()) {
7911    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7912    EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7913               rm.GetCode());
7914    AdvanceIT();
7915    return;
7916  } else {
7917    // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7918    if (cond.IsNotNever()) {
7919      EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7920              (rn.GetCode() << 16) | rm.GetCode());
7921      return;
7922    }
7923  }
7924  Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
7925}
7926
7927void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
7928  VIXL_ASSERT(AllowAssembler());
7929  CheckIT(cond);
7930  if (IsUsingT32()) {
7931    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7932    EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
7933               (rn.GetCode() << 16));
7934    AdvanceIT();
7935    return;
7936  } else {
7937    // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7938    if (cond.IsNotNever()) {
7939      EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7940              rm.GetCode() | (rn.GetCode() << 16));
7941      return;
7942    }
7943  }
7944  Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
7945}
7946
7947void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
7948  VIXL_ASSERT(AllowAssembler());
7949  CheckIT(cond);
7950  if (IsUsingT32()) {
7951    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7952    EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
7953               (rn.GetCode() << 16));
7954    AdvanceIT();
7955    return;
7956  } else {
7957    // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7958    if (cond.IsNotNever()) {
7959      EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7960              rm.GetCode() | (rn.GetCode() << 16));
7961      return;
7962    }
7963  }
7964  Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
7965}
7966
7967void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
7968  VIXL_ASSERT(AllowAssembler());
7969  CheckIT(cond);
7970  if (IsUsingT32()) {
7971    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7972    EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7973               rm.GetCode());
7974    AdvanceIT();
7975    return;
7976  } else {
7977    // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7978    if (cond.IsNotNever()) {
7979      EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7980              (rn.GetCode() << 16) | rm.GetCode());
7981      return;
7982    }
7983  }
7984  Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
7985}
7986
7987void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
7988  VIXL_ASSERT(AllowAssembler());
7989  CheckIT(cond);
7990  if (IsUsingT32()) {
7991    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7992    EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
7993               (rn.GetCode() << 16));
7994    AdvanceIT();
7995    return;
7996  } else {
7997    // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7998    if (cond.IsNotNever()) {
7999      EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8000              rm.GetCode() | (rn.GetCode() << 16));
8001      return;
8002    }
8003  }
8004  Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8005}
8006
8007void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
8008  VIXL_ASSERT(AllowAssembler());
8009  CheckIT(cond);
8010  if (IsUsingT32()) {
8011    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8012    EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8013               rm.GetCode());
8014    AdvanceIT();
8015    return;
8016  } else {
8017    // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8018    if (cond.IsNotNever()) {
8019      EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8020              (rn.GetCode() << 16) | rm.GetCode());
8021      return;
8022    }
8023  }
8024  Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8025}
8026
8027void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
8028  VIXL_ASSERT(AllowAssembler());
8029  CheckIT(cond);
8030  if (IsUsingT32()) {
8031    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8032    EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8033               rm.GetCode());
8034    AdvanceIT();
8035    return;
8036  } else {
8037    // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8038    if (cond.IsNotNever()) {
8039      EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8040              (rn.GetCode() << 16) | rm.GetCode());
8041      return;
8042    }
8043  }
8044  Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8045}
8046
8047void Assembler::rbit(Condition cond, Register rd, Register rm) {
8048  VIXL_ASSERT(AllowAssembler());
8049  CheckIT(cond);
8050  if (IsUsingT32()) {
8051    // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
8052    EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8053               (rm.GetCode() << 16));
8054    AdvanceIT();
8055    return;
8056  } else {
8057    // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
8058    if (cond.IsNotNever()) {
8059      EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8060              rm.GetCode());
8061      return;
8062    }
8063  }
8064  Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8065}
8066
8067void Assembler::rev(Condition cond,
8068                    EncodingSize size,
8069                    Register rd,
8070                    Register rm) {
8071  VIXL_ASSERT(AllowAssembler());
8072  CheckIT(cond);
8073  if (IsUsingT32()) {
8074    // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8075    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8076      EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8077      AdvanceIT();
8078      return;
8079    }
8080    // REV{<c>}{<q>} <Rd>, <Rm> ; T2
8081    if (!size.IsNarrow()) {
8082      EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8083                 (rm.GetCode() << 16));
8084      AdvanceIT();
8085      return;
8086    }
8087  } else {
8088    // REV{<c>}{<q>} <Rd>, <Rm> ; A1
8089    if (cond.IsNotNever()) {
8090      EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8091              rm.GetCode());
8092      return;
8093    }
8094  }
8095  Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8096}
8097
8098void Assembler::rev16(Condition cond,
8099                      EncodingSize size,
8100                      Register rd,
8101                      Register rm) {
8102  VIXL_ASSERT(AllowAssembler());
8103  CheckIT(cond);
8104  if (IsUsingT32()) {
8105    // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8106    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8107      EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8108      AdvanceIT();
8109      return;
8110    }
8111    // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
8112    if (!size.IsNarrow()) {
8113      EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8114                 (rm.GetCode() << 16));
8115      AdvanceIT();
8116      return;
8117    }
8118  } else {
8119    // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
8120    if (cond.IsNotNever()) {
8121      EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8122              rm.GetCode());
8123      return;
8124    }
8125  }
8126  Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8127}
8128
8129void Assembler::revsh(Condition cond,
8130                      EncodingSize size,
8131                      Register rd,
8132                      Register rm) {
8133  VIXL_ASSERT(AllowAssembler());
8134  CheckIT(cond);
8135  if (IsUsingT32()) {
8136    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8137    if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8138      EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8139      AdvanceIT();
8140      return;
8141    }
8142    // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
8143    if (!size.IsNarrow()) {
8144      EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8145                 (rm.GetCode() << 16));
8146      AdvanceIT();
8147      return;
8148    }
8149  } else {
8150    // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
8151    if (cond.IsNotNever()) {
8152      EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8153              rm.GetCode());
8154      return;
8155    }
8156  }
8157  Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8158}
8159
8160void Assembler::ror(Condition cond,
8161                    EncodingSize size,
8162                    Register rd,
8163                    Register rm,
8164                    const Operand& operand) {
8165  VIXL_ASSERT(AllowAssembler());
8166  CheckIT(cond);
8167  if (operand.IsImmediate()) {
8168    uint32_t imm = operand.GetImmediate();
8169    if (IsUsingT32()) {
8170      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8171      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
8172        EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8173                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8174        AdvanceIT();
8175        return;
8176      }
8177    } else {
8178      // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8179      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8180        EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8181                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8182        return;
8183      }
8184    }
8185  }
8186  if (operand.IsPlainRegister()) {
8187    Register rs = operand.GetBaseRegister();
8188    if (IsUsingT32()) {
8189      // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8190      if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8191          rs.IsLow()) {
8192        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8193        AdvanceIT();
8194        return;
8195      }
8196      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8197      if (!size.IsNarrow()) {
8198        EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8199                   rs.GetCode());
8200        AdvanceIT();
8201        return;
8202      }
8203    } else {
8204      // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8205      if (cond.IsNotNever()) {
8206        EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
8207                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8208        return;
8209      }
8210    }
8211  }
8212  Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
8213}
8214
8215void Assembler::rors(Condition cond,
8216                     EncodingSize size,
8217                     Register rd,
8218                     Register rm,
8219                     const Operand& operand) {
8220  VIXL_ASSERT(AllowAssembler());
8221  CheckIT(cond);
8222  if (operand.IsImmediate()) {
8223    uint32_t imm = operand.GetImmediate();
8224    if (IsUsingT32()) {
8225      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8226      if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
8227        EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8228                   ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8229        AdvanceIT();
8230        return;
8231      }
8232    } else {
8233      // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8234      if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8235        EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
8236                (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8237        return;
8238      }
8239    }
8240  }
8241  if (operand.IsPlainRegister()) {
8242    Register rs = operand.GetBaseRegister();
8243    if (IsUsingT32()) {
8244      // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8245      if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8246          rs.IsLow()) {
8247        EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8248        AdvanceIT();
8249        return;
8250      }
8251      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8252      if (!size.IsNarrow()) {
8253        EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8254                   rs.GetCode());
8255        AdvanceIT();
8256        return;
8257      }
8258    } else {
8259      // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8260      if (cond.IsNotNever()) {
8261        EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
8262                (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8263        return;
8264      }
8265    }
8266  }
8267  Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
8268}
8269
8270void Assembler::rrx(Condition cond, Register rd, Register rm) {
8271  VIXL_ASSERT(AllowAssembler());
8272  CheckIT(cond);
8273  if (IsUsingT32()) {
8274    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
8275    EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
8276    AdvanceIT();
8277    return;
8278  } else {
8279    // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
8280    if (cond.IsNotNever()) {
8281      EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8282              rm.GetCode());
8283      return;
8284    }
8285  }
8286  Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
8287}
8288
8289void Assembler::rrxs(Condition cond, Register rd, Register rm) {
8290  VIXL_ASSERT(AllowAssembler());
8291  CheckIT(cond);
8292  if (IsUsingT32()) {
8293    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
8294    EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
8295    AdvanceIT();
8296    return;
8297  } else {
8298    // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
8299    if (cond.IsNotNever()) {
8300      EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8301              rm.GetCode());
8302      return;
8303    }
8304  }
8305  Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
8306}
8307
8308void Assembler::rsb(Condition cond,
8309                    EncodingSize size,
8310                    Register rd,
8311                    Register rn,
8312                    const Operand& operand) {
8313  VIXL_ASSERT(AllowAssembler());
8314  CheckIT(cond);
8315  if (operand.IsImmediate()) {
8316    uint32_t imm = operand.GetImmediate();
8317    if (IsUsingT32()) {
8318      ImmediateT32 immediate_t32(imm);
8319      // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
8320      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
8321          (imm == 0)) {
8322        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
8323        AdvanceIT();
8324        return;
8325      }
8326      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
8327      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8328        EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8329                   (immediate_t32.GetEncodingValue() & 0xff) |
8330                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8331                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8332        AdvanceIT();
8333        return;
8334      }
8335    } else {
8336      ImmediateA32 immediate_a32(imm);
8337      // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8338      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8339        EmitA32(0x02600000U | (cond.GetCondition() << 28) |
8340                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8341                immediate_a32.GetEncodingValue());
8342        return;
8343      }
8344    }
8345  }
8346  if (operand.IsImmediateShiftedRegister()) {
8347    Register rm = operand.GetBaseRegister();
8348    Shift shift = operand.GetShift();
8349    uint32_t amount = operand.GetShiftAmount();
8350    if (IsUsingT32()) {
8351      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
8352      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8353        uint32_t amount_ = amount % 32;
8354        EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8355                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8356                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8357        AdvanceIT();
8358        return;
8359      }
8360    } else {
8361      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8362      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8363        uint32_t amount_ = amount % 32;
8364        EmitA32(0x00600000U | (cond.GetCondition() << 28) |
8365                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8366                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8367        return;
8368      }
8369    }
8370  }
8371  if (operand.IsRegisterShiftedRegister()) {
8372    Register rm = operand.GetBaseRegister();
8373    Shift shift = operand.GetShift();
8374    if (IsUsingA32()) {
8375      // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8376      if (cond.IsNotNever()) {
8377        EmitA32(0x00600010U | (cond.GetCondition() << 28) |
8378                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8379                (shift.GetType() << 5) |
8380                (operand.GetShiftRegister().GetCode() << 8));
8381        return;
8382      }
8383    }
8384  }
8385  Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
8386}
8387
8388void Assembler::rsbs(Condition cond,
8389                     EncodingSize size,
8390                     Register rd,
8391                     Register rn,
8392                     const Operand& operand) {
8393  VIXL_ASSERT(AllowAssembler());
8394  CheckIT(cond);
8395  if (operand.IsImmediate()) {
8396    uint32_t imm = operand.GetImmediate();
8397    if (IsUsingT32()) {
8398      ImmediateT32 immediate_t32(imm);
8399      // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
8400      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
8401          (imm == 0)) {
8402        EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
8403        AdvanceIT();
8404        return;
8405      }
8406      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
8407      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8408        EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8409                   (immediate_t32.GetEncodingValue() & 0xff) |
8410                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8411                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8412        AdvanceIT();
8413        return;
8414      }
8415    } else {
8416      ImmediateA32 immediate_a32(imm);
8417      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8418      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8419        EmitA32(0x02700000U | (cond.GetCondition() << 28) |
8420                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8421                immediate_a32.GetEncodingValue());
8422        return;
8423      }
8424    }
8425  }
8426  if (operand.IsImmediateShiftedRegister()) {
8427    Register rm = operand.GetBaseRegister();
8428    Shift shift = operand.GetShift();
8429    uint32_t amount = operand.GetShiftAmount();
8430    if (IsUsingT32()) {
8431      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
8432      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8433        uint32_t amount_ = amount % 32;
8434        EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8435                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8436                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8437        AdvanceIT();
8438        return;
8439      }
8440    } else {
8441      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8442      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8443        uint32_t amount_ = amount % 32;
8444        EmitA32(0x00700000U | (cond.GetCondition() << 28) |
8445                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8446                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8447        return;
8448      }
8449    }
8450  }
8451  if (operand.IsRegisterShiftedRegister()) {
8452    Register rm = operand.GetBaseRegister();
8453    Shift shift = operand.GetShift();
8454    if (IsUsingA32()) {
8455      // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8456      if (cond.IsNotNever()) {
8457        EmitA32(0x00700010U | (cond.GetCondition() << 28) |
8458                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8459                (shift.GetType() << 5) |
8460                (operand.GetShiftRegister().GetCode() << 8));
8461        return;
8462      }
8463    }
8464  }
8465  Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
8466}
8467
8468void Assembler::rsc(Condition cond,
8469                    Register rd,
8470                    Register rn,
8471                    const Operand& operand) {
8472  VIXL_ASSERT(AllowAssembler());
8473  CheckIT(cond);
8474  if (operand.IsImmediate()) {
8475    uint32_t imm = operand.GetImmediate();
8476    if (IsUsingA32()) {
8477      ImmediateA32 immediate_a32(imm);
8478      // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8479      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8480        EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
8481                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8482                immediate_a32.GetEncodingValue());
8483        return;
8484      }
8485    }
8486  }
8487  if (operand.IsImmediateShiftedRegister()) {
8488    Register rm = operand.GetBaseRegister();
8489    Shift shift = operand.GetShift();
8490    uint32_t amount = operand.GetShiftAmount();
8491    if (IsUsingA32()) {
8492      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8493      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8494        uint32_t amount_ = amount % 32;
8495        EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
8496                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8497                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8498        return;
8499      }
8500    }
8501  }
8502  if (operand.IsRegisterShiftedRegister()) {
8503    Register rm = operand.GetBaseRegister();
8504    Shift shift = operand.GetShift();
8505    if (IsUsingA32()) {
8506      // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8507      if (cond.IsNotNever()) {
8508        EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
8509                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8510                (shift.GetType() << 5) |
8511                (operand.GetShiftRegister().GetCode() << 8));
8512        return;
8513      }
8514    }
8515  }
8516  Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
8517}
8518
8519void Assembler::rscs(Condition cond,
8520                     Register rd,
8521                     Register rn,
8522                     const Operand& operand) {
8523  VIXL_ASSERT(AllowAssembler());
8524  CheckIT(cond);
8525  if (operand.IsImmediate()) {
8526    uint32_t imm = operand.GetImmediate();
8527    if (IsUsingA32()) {
8528      ImmediateA32 immediate_a32(imm);
8529      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8530      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8531        EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
8532                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8533                immediate_a32.GetEncodingValue());
8534        return;
8535      }
8536    }
8537  }
8538  if (operand.IsImmediateShiftedRegister()) {
8539    Register rm = operand.GetBaseRegister();
8540    Shift shift = operand.GetShift();
8541    uint32_t amount = operand.GetShiftAmount();
8542    if (IsUsingA32()) {
8543      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8544      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8545        uint32_t amount_ = amount % 32;
8546        EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
8547                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8548                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8549        return;
8550      }
8551    }
8552  }
8553  if (operand.IsRegisterShiftedRegister()) {
8554    Register rm = operand.GetBaseRegister();
8555    Shift shift = operand.GetShift();
8556    if (IsUsingA32()) {
8557      // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8558      if (cond.IsNotNever()) {
8559        EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
8560                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8561                (shift.GetType() << 5) |
8562                (operand.GetShiftRegister().GetCode() << 8));
8563        return;
8564      }
8565    }
8566  }
8567  Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
8568}
8569
8570void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
8571  VIXL_ASSERT(AllowAssembler());
8572  CheckIT(cond);
8573  if (IsUsingT32()) {
8574    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8575    EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8576               rm.GetCode());
8577    AdvanceIT();
8578    return;
8579  } else {
8580    // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8581    if (cond.IsNotNever()) {
8582      EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8583              (rn.GetCode() << 16) | rm.GetCode());
8584      return;
8585    }
8586  }
8587  Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
8588}
8589
8590void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
8591  VIXL_ASSERT(AllowAssembler());
8592  CheckIT(cond);
8593  if (IsUsingT32()) {
8594    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8595    EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8596               rm.GetCode());
8597    AdvanceIT();
8598    return;
8599  } else {
8600    // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8601    if (cond.IsNotNever()) {
8602      EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8603              (rn.GetCode() << 16) | rm.GetCode());
8604      return;
8605    }
8606  }
8607  Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
8608}
8609
8610void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
8611  VIXL_ASSERT(AllowAssembler());
8612  CheckIT(cond);
8613  if (IsUsingT32()) {
8614    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8615    EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8616               rm.GetCode());
8617    AdvanceIT();
8618    return;
8619  } else {
8620    // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8621    if (cond.IsNotNever()) {
8622      EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8623              (rn.GetCode() << 16) | rm.GetCode());
8624      return;
8625    }
8626  }
8627  Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
8628}
8629
8630void Assembler::sbc(Condition cond,
8631                    EncodingSize size,
8632                    Register rd,
8633                    Register rn,
8634                    const Operand& operand) {
8635  VIXL_ASSERT(AllowAssembler());
8636  CheckIT(cond);
8637  if (operand.IsImmediate()) {
8638    uint32_t imm = operand.GetImmediate();
8639    if (IsUsingT32()) {
8640      ImmediateT32 immediate_t32(imm);
8641      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
8642      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8643        EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8644                   (immediate_t32.GetEncodingValue() & 0xff) |
8645                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8646                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8647        AdvanceIT();
8648        return;
8649      }
8650    } else {
8651      ImmediateA32 immediate_a32(imm);
8652      // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8653      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8654        EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
8655                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8656                immediate_a32.GetEncodingValue());
8657        return;
8658      }
8659    }
8660  }
8661  if (operand.IsImmediateShiftedRegister()) {
8662    Register rm = operand.GetBaseRegister();
8663    if (operand.IsPlainRegister()) {
8664      if (IsUsingT32()) {
8665        // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
8666        if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
8667            rm.IsLow()) {
8668          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
8669          AdvanceIT();
8670          return;
8671        }
8672      }
8673    }
8674    Shift shift = operand.GetShift();
8675    uint32_t amount = operand.GetShiftAmount();
8676    if (IsUsingT32()) {
8677      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
8678      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8679        uint32_t amount_ = amount % 32;
8680        EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8681                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8682                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8683        AdvanceIT();
8684        return;
8685      }
8686    } else {
8687      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8688      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8689        uint32_t amount_ = amount % 32;
8690        EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
8691                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8692                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8693        return;
8694      }
8695    }
8696  }
8697  if (operand.IsRegisterShiftedRegister()) {
8698    Register rm = operand.GetBaseRegister();
8699    Shift shift = operand.GetShift();
8700    if (IsUsingA32()) {
8701      // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8702      if (cond.IsNotNever()) {
8703        EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
8704                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8705                (shift.GetType() << 5) |
8706                (operand.GetShiftRegister().GetCode() << 8));
8707        return;
8708      }
8709    }
8710  }
8711  Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
8712}
8713
8714void Assembler::sbcs(Condition cond,
8715                     EncodingSize size,
8716                     Register rd,
8717                     Register rn,
8718                     const Operand& operand) {
8719  VIXL_ASSERT(AllowAssembler());
8720  CheckIT(cond);
8721  if (operand.IsImmediate()) {
8722    uint32_t imm = operand.GetImmediate();
8723    if (IsUsingT32()) {
8724      ImmediateT32 immediate_t32(imm);
8725      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
8726      if (!size.IsNarrow() && immediate_t32.IsValid()) {
8727        EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8728                   (immediate_t32.GetEncodingValue() & 0xff) |
8729                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8730                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8731        AdvanceIT();
8732        return;
8733      }
8734    } else {
8735      ImmediateA32 immediate_a32(imm);
8736      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8737      if (immediate_a32.IsValid() && cond.IsNotNever()) {
8738        EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
8739                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8740                immediate_a32.GetEncodingValue());
8741        return;
8742      }
8743    }
8744  }
8745  if (operand.IsImmediateShiftedRegister()) {
8746    Register rm = operand.GetBaseRegister();
8747    if (operand.IsPlainRegister()) {
8748      if (IsUsingT32()) {
8749        // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
8750        if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
8751            rm.IsLow()) {
8752          EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
8753          AdvanceIT();
8754          return;
8755        }
8756      }
8757    }
8758    Shift shift = operand.GetShift();
8759    uint32_t amount = operand.GetShiftAmount();
8760    if (IsUsingT32()) {
8761      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
8762      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8763        uint32_t amount_ = amount % 32;
8764        EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8765                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8766                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8767        AdvanceIT();
8768        return;
8769      }
8770    } else {
8771      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8772      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8773        uint32_t amount_ = amount % 32;
8774        EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
8775                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8776                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8777        return;
8778      }
8779    }
8780  }
8781  if (operand.IsRegisterShiftedRegister()) {
8782    Register rm = operand.GetBaseRegister();
8783    Shift shift = operand.GetShift();
8784    if (IsUsingA32()) {
8785      // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8786      if (cond.IsNotNever()) {
8787        EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
8788                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8789                (shift.GetType() << 5) |
8790                (operand.GetShiftRegister().GetCode() << 8));
8791        return;
8792      }
8793    }
8794  }
8795  Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
8796}
8797
8798void Assembler::sbfx(Condition cond,
8799                     Register rd,
8800                     Register rn,
8801                     uint32_t lsb,
8802                     const Operand& operand) {
8803  VIXL_ASSERT(AllowAssembler());
8804  CheckIT(cond);
8805  if (operand.IsImmediate()) {
8806    uint32_t width = operand.GetImmediate();
8807    if (IsUsingT32()) {
8808      // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
8809      if ((lsb <= 31) &&
8810          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
8811        uint32_t widthm1 = width - 1;
8812        EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8813                   ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
8814        AdvanceIT();
8815        return;
8816      }
8817    } else {
8818      // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
8819      if ((lsb <= 31) && cond.IsNotNever() &&
8820          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
8821        uint32_t widthm1 = width - 1;
8822        EmitA32(0x07a00050U | (cond.GetCondition() << 28) |
8823                (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) |
8824                (widthm1 << 16));
8825        return;
8826      }
8827    }
8828  }
8829  Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, operand);
8830}
8831
8832void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
8833  VIXL_ASSERT(AllowAssembler());
8834  CheckIT(cond);
8835  if (IsUsingT32()) {
8836    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8837    EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8838               rm.GetCode());
8839    AdvanceIT();
8840    return;
8841  } else {
8842    // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8843    if (cond.IsNotNever()) {
8844      EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
8845              rn.GetCode() | (rm.GetCode() << 8));
8846      return;
8847    }
8848  }
8849  Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
8850}
8851
8852void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
8853  VIXL_ASSERT(AllowAssembler());
8854  CheckIT(cond);
8855  if (IsUsingT32()) {
8856    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8857    EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8858               rm.GetCode());
8859    AdvanceIT();
8860    return;
8861  } else {
8862    // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8863    if (cond.IsNotNever()) {
8864      EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8865              (rn.GetCode() << 16) | rm.GetCode());
8866      return;
8867    }
8868  }
8869  Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
8870}
8871
8872void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
8873  VIXL_ASSERT(AllowAssembler());
8874  CheckIT(cond);
8875  if (IsUsingT32()) {
8876    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8877    EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8878               rm.GetCode());
8879    AdvanceIT();
8880    return;
8881  } else {
8882    // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8883    if (cond.IsNotNever()) {
8884      EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8885              (rn.GetCode() << 16) | rm.GetCode());
8886      return;
8887    }
8888  }
8889  Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
8890}
8891
8892void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
8893  VIXL_ASSERT(AllowAssembler());
8894  CheckIT(cond);
8895  if (IsUsingT32()) {
8896    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8897    EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8898               rm.GetCode());
8899    AdvanceIT();
8900    return;
8901  } else {
8902    // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8903    if (cond.IsNotNever()) {
8904      EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8905              (rn.GetCode() << 16) | rm.GetCode());
8906      return;
8907    }
8908  }
8909  Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
8910}
8911
8912void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
8913  VIXL_ASSERT(AllowAssembler());
8914  CheckIT(cond);
8915  if (IsUsingT32()) {
8916    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8917    EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8918               rm.GetCode());
8919    AdvanceIT();
8920    return;
8921  } else {
8922    // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8923    if (cond.IsNotNever()) {
8924      EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8925              (rn.GetCode() << 16) | rm.GetCode());
8926      return;
8927    }
8928  }
8929  Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
8930}
8931
8932void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
8933  VIXL_ASSERT(AllowAssembler());
8934  CheckIT(cond);
8935  if (IsUsingT32()) {
8936    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8937    EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8938               rm.GetCode());
8939    AdvanceIT();
8940    return;
8941  } else {
8942    // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8943    if (cond.IsNotNever()) {
8944      EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8945              (rn.GetCode() << 16) | rm.GetCode());
8946      return;
8947    }
8948  }
8949  Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
8950}
8951
8952void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
8953  VIXL_ASSERT(AllowAssembler());
8954  CheckIT(cond);
8955  if (IsUsingT32()) {
8956    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8957    EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8958               rm.GetCode());
8959    AdvanceIT();
8960    return;
8961  } else {
8962    // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8963    if (cond.IsNotNever()) {
8964      EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8965              (rn.GetCode() << 16) | rm.GetCode());
8966      return;
8967    }
8968  }
8969  Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
8970}
8971
8972void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
8973  VIXL_ASSERT(AllowAssembler());
8974  CheckIT(cond);
8975  if (IsUsingT32()) {
8976    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8977    EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8978               rm.GetCode());
8979    AdvanceIT();
8980    return;
8981  } else {
8982    // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8983    if (cond.IsNotNever()) {
8984      EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8985              (rn.GetCode() << 16) | rm.GetCode());
8986      return;
8987    }
8988  }
8989  Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
8990}
8991
8992void Assembler::smlabb(
8993    Condition cond, Register rd, Register rn, Register rm, Register ra) {
8994  VIXL_ASSERT(AllowAssembler());
8995  CheckIT(cond);
8996  if (IsUsingT32()) {
8997    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
8998    if (!ra.Is(pc)) {
8999      EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9000                 rm.GetCode() | (ra.GetCode() << 12));
9001      AdvanceIT();
9002      return;
9003    }
9004  } else {
9005    // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9006    if (cond.IsNotNever()) {
9007      EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9008              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9009      return;
9010    }
9011  }
9012  Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9013}
9014
9015void Assembler::smlabt(
9016    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9017  VIXL_ASSERT(AllowAssembler());
9018  CheckIT(cond);
9019  if (IsUsingT32()) {
9020    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9021    if (!ra.Is(pc)) {
9022      EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9023                 rm.GetCode() | (ra.GetCode() << 12));
9024      AdvanceIT();
9025      return;
9026    }
9027  } else {
9028    // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9029    if (cond.IsNotNever()) {
9030      EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9031              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9032      return;
9033    }
9034  }
9035  Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9036}
9037
9038void Assembler::smlad(
9039    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9040  VIXL_ASSERT(AllowAssembler());
9041  CheckIT(cond);
9042  if (IsUsingT32()) {
9043    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9044    if (!ra.Is(pc)) {
9045      EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9046                 rm.GetCode() | (ra.GetCode() << 12));
9047      AdvanceIT();
9048      return;
9049    }
9050  } else {
9051    // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9052    if (cond.IsNotNever() && !ra.Is(pc)) {
9053      EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9054              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9055      return;
9056    }
9057  }
9058  Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9059}
9060
9061void Assembler::smladx(
9062    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9063  VIXL_ASSERT(AllowAssembler());
9064  CheckIT(cond);
9065  if (IsUsingT32()) {
9066    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9067    if (!ra.Is(pc)) {
9068      EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9069                 rm.GetCode() | (ra.GetCode() << 12));
9070      AdvanceIT();
9071      return;
9072    }
9073  } else {
9074    // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9075    if (cond.IsNotNever() && !ra.Is(pc)) {
9076      EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9077              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9078      return;
9079    }
9080  }
9081  Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9082}
9083
9084void Assembler::smlal(
9085    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9086  VIXL_ASSERT(AllowAssembler());
9087  CheckIT(cond);
9088  if (IsUsingT32()) {
9089    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9090    EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9091               (rn.GetCode() << 16) | rm.GetCode());
9092    AdvanceIT();
9093    return;
9094  } else {
9095    // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9096    if (cond.IsNotNever()) {
9097      EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9098              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9099              (rm.GetCode() << 8));
9100      return;
9101    }
9102  }
9103  Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9104}
9105
9106void Assembler::smlalbb(
9107    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9108  VIXL_ASSERT(AllowAssembler());
9109  CheckIT(cond);
9110  if (IsUsingT32()) {
9111    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9112    EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9113               (rn.GetCode() << 16) | rm.GetCode());
9114    AdvanceIT();
9115    return;
9116  } else {
9117    // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9118    if (cond.IsNotNever()) {
9119      EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9120              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9121              (rm.GetCode() << 8));
9122      return;
9123    }
9124  }
9125  Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9126}
9127
9128void Assembler::smlalbt(
9129    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9130  VIXL_ASSERT(AllowAssembler());
9131  CheckIT(cond);
9132  if (IsUsingT32()) {
9133    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9134    EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9135               (rn.GetCode() << 16) | rm.GetCode());
9136    AdvanceIT();
9137    return;
9138  } else {
9139    // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9140    if (cond.IsNotNever()) {
9141      EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
9142              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9143              (rm.GetCode() << 8));
9144      return;
9145    }
9146  }
9147  Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
9148}
9149
9150void Assembler::smlald(
9151    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9152  VIXL_ASSERT(AllowAssembler());
9153  CheckIT(cond);
9154  if (IsUsingT32()) {
9155    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9156    EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9157               (rn.GetCode() << 16) | rm.GetCode());
9158    AdvanceIT();
9159    return;
9160  } else {
9161    // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9162    if (cond.IsNotNever()) {
9163      EmitA32(0x07400010U | (cond.GetCondition() << 28) |
9164              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9165              (rm.GetCode() << 8));
9166      return;
9167    }
9168  }
9169  Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
9170}
9171
9172void Assembler::smlaldx(
9173    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9174  VIXL_ASSERT(AllowAssembler());
9175  CheckIT(cond);
9176  if (IsUsingT32()) {
9177    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9178    EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9179               (rn.GetCode() << 16) | rm.GetCode());
9180    AdvanceIT();
9181    return;
9182  } else {
9183    // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9184    if (cond.IsNotNever()) {
9185      EmitA32(0x07400030U | (cond.GetCondition() << 28) |
9186              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9187              (rm.GetCode() << 8));
9188      return;
9189    }
9190  }
9191  Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
9192}
9193
9194void Assembler::smlals(
9195    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9196  VIXL_ASSERT(AllowAssembler());
9197  CheckIT(cond);
9198  if (IsUsingA32()) {
9199    // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9200    if (cond.IsNotNever()) {
9201      EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
9202              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9203              (rm.GetCode() << 8));
9204      return;
9205    }
9206  }
9207  Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
9208}
9209
9210void Assembler::smlaltb(
9211    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9212  VIXL_ASSERT(AllowAssembler());
9213  CheckIT(cond);
9214  if (IsUsingT32()) {
9215    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9216    EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9217               (rn.GetCode() << 16) | rm.GetCode());
9218    AdvanceIT();
9219    return;
9220  } else {
9221    // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9222    if (cond.IsNotNever()) {
9223      EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
9224              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9225              (rm.GetCode() << 8));
9226      return;
9227    }
9228  }
9229  Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
9230}
9231
9232void Assembler::smlaltt(
9233    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9234  VIXL_ASSERT(AllowAssembler());
9235  CheckIT(cond);
9236  if (IsUsingT32()) {
9237    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9238    EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9239               (rn.GetCode() << 16) | rm.GetCode());
9240    AdvanceIT();
9241    return;
9242  } else {
9243    // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9244    if (cond.IsNotNever()) {
9245      EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
9246              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9247              (rm.GetCode() << 8));
9248      return;
9249    }
9250  }
9251  Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
9252}
9253
9254void Assembler::smlatb(
9255    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9256  VIXL_ASSERT(AllowAssembler());
9257  CheckIT(cond);
9258  if (IsUsingT32()) {
9259    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9260    if (!ra.Is(pc)) {
9261      EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9262                 rm.GetCode() | (ra.GetCode() << 12));
9263      AdvanceIT();
9264      return;
9265    }
9266  } else {
9267    // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9268    if (cond.IsNotNever()) {
9269      EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9270              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9271      return;
9272    }
9273  }
9274  Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
9275}
9276
9277void Assembler::smlatt(
9278    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9279  VIXL_ASSERT(AllowAssembler());
9280  CheckIT(cond);
9281  if (IsUsingT32()) {
9282    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9283    if (!ra.Is(pc)) {
9284      EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9285                 rm.GetCode() | (ra.GetCode() << 12));
9286      AdvanceIT();
9287      return;
9288    }
9289  } else {
9290    // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9291    if (cond.IsNotNever()) {
9292      EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9293              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9294      return;
9295    }
9296  }
9297  Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
9298}
9299
9300void Assembler::smlawb(
9301    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9302  VIXL_ASSERT(AllowAssembler());
9303  CheckIT(cond);
9304  if (IsUsingT32()) {
9305    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9306    if (!ra.Is(pc)) {
9307      EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9308                 rm.GetCode() | (ra.GetCode() << 12));
9309      AdvanceIT();
9310      return;
9311    }
9312  } else {
9313    // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9314    if (cond.IsNotNever()) {
9315      EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9316              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9317      return;
9318    }
9319  }
9320  Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
9321}
9322
9323void Assembler::smlawt(
9324    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9325  VIXL_ASSERT(AllowAssembler());
9326  CheckIT(cond);
9327  if (IsUsingT32()) {
9328    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9329    if (!ra.Is(pc)) {
9330      EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9331                 rm.GetCode() | (ra.GetCode() << 12));
9332      AdvanceIT();
9333      return;
9334    }
9335  } else {
9336    // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9337    if (cond.IsNotNever()) {
9338      EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9339              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9340      return;
9341    }
9342  }
9343  Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
9344}
9345
9346void Assembler::smlsd(
9347    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9348  VIXL_ASSERT(AllowAssembler());
9349  CheckIT(cond);
9350  if (IsUsingT32()) {
9351    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9352    if (!ra.Is(pc)) {
9353      EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9354                 rm.GetCode() | (ra.GetCode() << 12));
9355      AdvanceIT();
9356      return;
9357    }
9358  } else {
9359    // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9360    if (cond.IsNotNever() && !ra.Is(pc)) {
9361      EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9362              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9363      return;
9364    }
9365  }
9366  Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
9367}
9368
9369void Assembler::smlsdx(
9370    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9371  VIXL_ASSERT(AllowAssembler());
9372  CheckIT(cond);
9373  if (IsUsingT32()) {
9374    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9375    if (!ra.Is(pc)) {
9376      EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9377                 rm.GetCode() | (ra.GetCode() << 12));
9378      AdvanceIT();
9379      return;
9380    }
9381  } else {
9382    // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9383    if (cond.IsNotNever() && !ra.Is(pc)) {
9384      EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9385              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9386      return;
9387    }
9388  }
9389  Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
9390}
9391
9392void Assembler::smlsld(
9393    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9394  VIXL_ASSERT(AllowAssembler());
9395  CheckIT(cond);
9396  if (IsUsingT32()) {
9397    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9398    EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9399               (rn.GetCode() << 16) | rm.GetCode());
9400    AdvanceIT();
9401    return;
9402  } else {
9403    // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9404    if (cond.IsNotNever()) {
9405      EmitA32(0x07400050U | (cond.GetCondition() << 28) |
9406              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9407              (rm.GetCode() << 8));
9408      return;
9409    }
9410  }
9411  Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
9412}
9413
9414void Assembler::smlsldx(
9415    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9416  VIXL_ASSERT(AllowAssembler());
9417  CheckIT(cond);
9418  if (IsUsingT32()) {
9419    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9420    EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9421               (rn.GetCode() << 16) | rm.GetCode());
9422    AdvanceIT();
9423    return;
9424  } else {
9425    // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9426    if (cond.IsNotNever()) {
9427      EmitA32(0x07400070U | (cond.GetCondition() << 28) |
9428              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9429              (rm.GetCode() << 8));
9430      return;
9431    }
9432  }
9433  Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
9434}
9435
9436void Assembler::smmla(
9437    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9438  VIXL_ASSERT(AllowAssembler());
9439  CheckIT(cond);
9440  if (IsUsingT32()) {
9441    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9442    if (!ra.Is(pc)) {
9443      EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9444                 rm.GetCode() | (ra.GetCode() << 12));
9445      AdvanceIT();
9446      return;
9447    }
9448  } else {
9449    // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9450    if (cond.IsNotNever() && !ra.Is(pc)) {
9451      EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9452              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9453      return;
9454    }
9455  }
9456  Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
9457}
9458
9459void Assembler::smmlar(
9460    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9461  VIXL_ASSERT(AllowAssembler());
9462  CheckIT(cond);
9463  if (IsUsingT32()) {
9464    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9465    if (!ra.Is(pc)) {
9466      EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9467                 rm.GetCode() | (ra.GetCode() << 12));
9468      AdvanceIT();
9469      return;
9470    }
9471  } else {
9472    // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9473    if (cond.IsNotNever() && !ra.Is(pc)) {
9474      EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9475              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9476      return;
9477    }
9478  }
9479  Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
9480}
9481
9482void Assembler::smmls(
9483    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9484  VIXL_ASSERT(AllowAssembler());
9485  CheckIT(cond);
9486  if (IsUsingT32()) {
9487    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9488    EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9489               rm.GetCode() | (ra.GetCode() << 12));
9490    AdvanceIT();
9491    return;
9492  } else {
9493    // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9494    if (cond.IsNotNever()) {
9495      EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9496              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9497      return;
9498    }
9499  }
9500  Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
9501}
9502
9503void Assembler::smmlsr(
9504    Condition cond, Register rd, Register rn, Register rm, Register ra) {
9505  VIXL_ASSERT(AllowAssembler());
9506  CheckIT(cond);
9507  if (IsUsingT32()) {
9508    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9509    EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9510               rm.GetCode() | (ra.GetCode() << 12));
9511    AdvanceIT();
9512    return;
9513  } else {
9514    // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9515    if (cond.IsNotNever()) {
9516      EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9517              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9518      return;
9519    }
9520  }
9521  Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
9522}
9523
9524void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
9525  VIXL_ASSERT(AllowAssembler());
9526  CheckIT(cond);
9527  if (IsUsingT32()) {
9528    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9529    EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9530               rm.GetCode());
9531    AdvanceIT();
9532    return;
9533  } else {
9534    // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9535    if (cond.IsNotNever()) {
9536      EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9537              rn.GetCode() | (rm.GetCode() << 8));
9538      return;
9539    }
9540  }
9541  Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
9542}
9543
9544void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
9545  VIXL_ASSERT(AllowAssembler());
9546  CheckIT(cond);
9547  if (IsUsingT32()) {
9548    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9549    EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9550               rm.GetCode());
9551    AdvanceIT();
9552    return;
9553  } else {
9554    // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9555    if (cond.IsNotNever()) {
9556      EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9557              rn.GetCode() | (rm.GetCode() << 8));
9558      return;
9559    }
9560  }
9561  Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
9562}
9563
9564void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
9565  VIXL_ASSERT(AllowAssembler());
9566  CheckIT(cond);
9567  if (IsUsingT32()) {
9568    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9569    EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9570               rm.GetCode());
9571    AdvanceIT();
9572    return;
9573  } else {
9574    // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9575    if (cond.IsNotNever()) {
9576      EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9577              rn.GetCode() | (rm.GetCode() << 8));
9578      return;
9579    }
9580  }
9581  Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
9582}
9583
9584void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
9585  VIXL_ASSERT(AllowAssembler());
9586  CheckIT(cond);
9587  if (IsUsingT32()) {
9588    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9589    EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9590               rm.GetCode());
9591    AdvanceIT();
9592    return;
9593  } else {
9594    // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9595    if (cond.IsNotNever()) {
9596      EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9597              rn.GetCode() | (rm.GetCode() << 8));
9598      return;
9599    }
9600  }
9601  Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
9602}
9603
9604void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
9605  VIXL_ASSERT(AllowAssembler());
9606  CheckIT(cond);
9607  if (IsUsingT32()) {
9608    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9609    EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9610               rm.GetCode());
9611    AdvanceIT();
9612    return;
9613  } else {
9614    // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9615    if (cond.IsNotNever()) {
9616      EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9617              rn.GetCode() | (rm.GetCode() << 8));
9618      return;
9619    }
9620  }
9621  Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
9622}
9623
9624void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
9625  VIXL_ASSERT(AllowAssembler());
9626  CheckIT(cond);
9627  if (IsUsingT32()) {
9628    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9629    EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9630               rm.GetCode());
9631    AdvanceIT();
9632    return;
9633  } else {
9634    // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9635    if (cond.IsNotNever()) {
9636      EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9637              rn.GetCode() | (rm.GetCode() << 8));
9638      return;
9639    }
9640  }
9641  Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
9642}
9643
9644void Assembler::smull(
9645    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9646  VIXL_ASSERT(AllowAssembler());
9647  CheckIT(cond);
9648  if (IsUsingT32()) {
9649    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9650    EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9651               (rn.GetCode() << 16) | rm.GetCode());
9652    AdvanceIT();
9653    return;
9654  } else {
9655    // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9656    if (cond.IsNotNever()) {
9657      EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
9658              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9659              (rm.GetCode() << 8));
9660      return;
9661    }
9662  }
9663  Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
9664}
9665
9666void Assembler::smulls(
9667    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
9668  VIXL_ASSERT(AllowAssembler());
9669  CheckIT(cond);
9670  if (IsUsingA32()) {
9671    // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9672    if (cond.IsNotNever()) {
9673      EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
9674              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9675              (rm.GetCode() << 8));
9676      return;
9677    }
9678  }
9679  Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
9680}
9681
9682void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
9683  VIXL_ASSERT(AllowAssembler());
9684  CheckIT(cond);
9685  if (IsUsingT32()) {
9686    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9687    EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9688               rm.GetCode());
9689    AdvanceIT();
9690    return;
9691  } else {
9692    // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9693    if (cond.IsNotNever()) {
9694      EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9695              rn.GetCode() | (rm.GetCode() << 8));
9696      return;
9697    }
9698  }
9699  Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
9700}
9701
9702void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
9703  VIXL_ASSERT(AllowAssembler());
9704  CheckIT(cond);
9705  if (IsUsingT32()) {
9706    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9707    EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9708               rm.GetCode());
9709    AdvanceIT();
9710    return;
9711  } else {
9712    // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9713    if (cond.IsNotNever()) {
9714      EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9715              rn.GetCode() | (rm.GetCode() << 8));
9716      return;
9717    }
9718  }
9719  Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
9720}
9721
9722void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
9723  VIXL_ASSERT(AllowAssembler());
9724  CheckIT(cond);
9725  if (IsUsingT32()) {
9726    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9727    EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9728               rm.GetCode());
9729    AdvanceIT();
9730    return;
9731  } else {
9732    // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9733    if (cond.IsNotNever()) {
9734      EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9735              rn.GetCode() | (rm.GetCode() << 8));
9736      return;
9737    }
9738  }
9739  Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
9740}
9741
9742void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
9743  VIXL_ASSERT(AllowAssembler());
9744  CheckIT(cond);
9745  if (IsUsingT32()) {
9746    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9747    EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9748               rm.GetCode());
9749    AdvanceIT();
9750    return;
9751  } else {
9752    // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9753    if (cond.IsNotNever()) {
9754      EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9755              rn.GetCode() | (rm.GetCode() << 8));
9756      return;
9757    }
9758  }
9759  Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
9760}
9761
9762void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
9763  VIXL_ASSERT(AllowAssembler());
9764  CheckIT(cond);
9765  if (IsUsingT32()) {
9766    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9767    EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9768               rm.GetCode());
9769    AdvanceIT();
9770    return;
9771  } else {
9772    // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9773    if (cond.IsNotNever()) {
9774      EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9775              rn.GetCode() | (rm.GetCode() << 8));
9776      return;
9777    }
9778  }
9779  Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
9780}
9781
9782void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
9783  VIXL_ASSERT(AllowAssembler());
9784  CheckIT(cond);
9785  if (IsUsingT32()) {
9786    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9787    EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9788               rm.GetCode());
9789    AdvanceIT();
9790    return;
9791  } else {
9792    // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9793    if (cond.IsNotNever()) {
9794      EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9795              rn.GetCode() | (rm.GetCode() << 8));
9796      return;
9797    }
9798  }
9799  Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
9800}
9801
9802void Assembler::ssat(Condition cond,
9803                     Register rd,
9804                     uint32_t imm,
9805                     const Operand& operand) {
9806  VIXL_ASSERT(AllowAssembler());
9807  CheckIT(cond);
9808  if (operand.IsImmediateShiftedRegister()) {
9809    Register rn = operand.GetBaseRegister();
9810    Shift shift = operand.GetShift();
9811    uint32_t amount = operand.GetShiftAmount();
9812    if (IsUsingT32()) {
9813      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
9814      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
9815          (amount <= 31)) {
9816        uint32_t imm_ = imm - 1;
9817        EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
9818                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
9819                   ((amount & 0x1c) << 10));
9820        AdvanceIT();
9821        return;
9822      }
9823      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
9824      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31)) {
9825        uint32_t imm_ = imm - 1;
9826        EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
9827                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
9828                   ((amount & 0x1c) << 10));
9829        AdvanceIT();
9830        return;
9831      }
9832    } else {
9833      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
9834      if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
9835          (amount <= 32) && cond.IsNotNever()) {
9836        uint32_t imm_ = imm - 1;
9837        uint32_t amount_ = amount % 32;
9838        EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
9839                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
9840                (amount_ << 7));
9841        return;
9842      }
9843      // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
9844      if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
9845          cond.IsNotNever()) {
9846        uint32_t imm_ = imm - 1;
9847        EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
9848                (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
9849                (amount << 7));
9850        return;
9851      }
9852    }
9853  }
9854  Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
9855}
9856
9857void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
9858  VIXL_ASSERT(AllowAssembler());
9859  CheckIT(cond);
9860  if (IsUsingT32()) {
9861    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
9862    if ((imm >= 1) && (imm <= 16)) {
9863      uint32_t imm_ = imm - 1;
9864      EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
9865                 (rn.GetCode() << 16));
9866      AdvanceIT();
9867      return;
9868    }
9869  } else {
9870    // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
9871    if ((imm >= 1) && (imm <= 16) && cond.IsNotNever()) {
9872      uint32_t imm_ = imm - 1;
9873      EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9874              (imm_ << 16) | rn.GetCode());
9875      return;
9876    }
9877  }
9878  Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
9879}
9880
9881void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
9882  VIXL_ASSERT(AllowAssembler());
9883  CheckIT(cond);
9884  if (IsUsingT32()) {
9885    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9886    EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9887               rm.GetCode());
9888    AdvanceIT();
9889    return;
9890  } else {
9891    // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9892    if (cond.IsNotNever()) {
9893      EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9894              (rn.GetCode() << 16) | rm.GetCode());
9895      return;
9896    }
9897  }
9898  Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
9899}
9900
9901void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
9902  VIXL_ASSERT(AllowAssembler());
9903  CheckIT(cond);
9904  if (IsUsingT32()) {
9905    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9906    EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9907               rm.GetCode());
9908    AdvanceIT();
9909    return;
9910  } else {
9911    // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9912    if (cond.IsNotNever()) {
9913      EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9914              (rn.GetCode() << 16) | rm.GetCode());
9915      return;
9916    }
9917  }
9918  Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
9919}
9920
9921void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
9922  VIXL_ASSERT(AllowAssembler());
9923  CheckIT(cond);
9924  if (IsUsingT32()) {
9925    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9926    EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9927               rm.GetCode());
9928    AdvanceIT();
9929    return;
9930  } else {
9931    // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9932    if (cond.IsNotNever()) {
9933      EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9934              (rn.GetCode() << 16) | rm.GetCode());
9935      return;
9936    }
9937  }
9938  Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
9939}
9940
9941void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
9942  VIXL_ASSERT(AllowAssembler());
9943  CheckIT(cond);
9944  if (operand.IsImmediateZero()) {
9945    Register rn = operand.GetBaseRegister();
9946    if (IsUsingT32()) {
9947      // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
9948      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
9949        EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
9950        AdvanceIT();
9951        return;
9952      }
9953    } else {
9954      // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
9955      if (operand.IsOffset() && cond.IsNotNever() &&
9956          (!rn.IsPC() || AllowUnpredictable())) {
9957        EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
9958                (rn.GetCode() << 16));
9959        return;
9960      }
9961    }
9962  }
9963  Delegate(kStl, &Assembler::stl, cond, rt, operand);
9964}
9965
9966void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
9967  VIXL_ASSERT(AllowAssembler());
9968  CheckIT(cond);
9969  if (operand.IsImmediateZero()) {
9970    Register rn = operand.GetBaseRegister();
9971    if (IsUsingT32()) {
9972      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
9973      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
9974        EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
9975        AdvanceIT();
9976        return;
9977      }
9978    } else {
9979      // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
9980      if (operand.IsOffset() && cond.IsNotNever() &&
9981          (!rn.IsPC() || AllowUnpredictable())) {
9982        EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
9983                (rn.GetCode() << 16));
9984        return;
9985      }
9986    }
9987  }
9988  Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
9989}
9990
9991void Assembler::stlex(Condition cond,
9992                      Register rd,
9993                      Register rt,
9994                      const MemOperand& operand) {
9995  VIXL_ASSERT(AllowAssembler());
9996  CheckIT(cond);
9997  if (operand.IsImmediateZero()) {
9998    Register rn = operand.GetBaseRegister();
9999    if (IsUsingT32()) {
10000      // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10001      if (operand.IsOffset() && (!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.IsOffset() && 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.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10031        EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
10032                   (rn.GetCode() << 16));
10033        AdvanceIT();
10034        return;
10035      }
10036    } else {
10037      // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10038      if (operand.IsOffset() && cond.IsNotNever() &&
10039          (!rn.IsPC() || AllowUnpredictable())) {
10040        EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
10041                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10042        return;
10043      }
10044    }
10045  }
10046  Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
10047}
10048
10049void Assembler::stlexd(Condition cond,
10050                       Register rd,
10051                       Register rt,
10052                       Register rt2,
10053                       const MemOperand& operand) {
10054  VIXL_ASSERT(AllowAssembler());
10055  CheckIT(cond);
10056  if (operand.IsImmediateZero()) {
10057    Register rn = operand.GetBaseRegister();
10058    if (IsUsingT32()) {
10059      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
10060      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10061        EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
10062                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
10063        AdvanceIT();
10064        return;
10065      }
10066    } else {
10067      // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
10068      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10069          operand.IsOffset() && cond.IsNotNever() &&
10070          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
10071           AllowUnpredictable())) {
10072        EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
10073                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10074        return;
10075      }
10076    }
10077  }
10078  Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
10079}
10080
10081void Assembler::stlexh(Condition cond,
10082                       Register rd,
10083                       Register rt,
10084                       const MemOperand& operand) {
10085  VIXL_ASSERT(AllowAssembler());
10086  CheckIT(cond);
10087  if (operand.IsImmediateZero()) {
10088    Register rn = operand.GetBaseRegister();
10089    if (IsUsingT32()) {
10090      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10091      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10092        EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
10093                   (rn.GetCode() << 16));
10094        AdvanceIT();
10095        return;
10096      }
10097    } else {
10098      // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10099      if (operand.IsOffset() && cond.IsNotNever() &&
10100          (!rn.IsPC() || AllowUnpredictable())) {
10101        EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
10102                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10103        return;
10104      }
10105    }
10106  }
10107  Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
10108}
10109
10110void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
10111  VIXL_ASSERT(AllowAssembler());
10112  CheckIT(cond);
10113  if (operand.IsImmediateZero()) {
10114    Register rn = operand.GetBaseRegister();
10115    if (IsUsingT32()) {
10116      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
10117      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10118        EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10119        AdvanceIT();
10120        return;
10121      }
10122    } else {
10123      // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
10124      if (operand.IsOffset() && cond.IsNotNever() &&
10125          (!rn.IsPC() || AllowUnpredictable())) {
10126        EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10127                (rn.GetCode() << 16));
10128        return;
10129      }
10130    }
10131  }
10132  Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
10133}
10134
10135void Assembler::stm(Condition cond,
10136                    EncodingSize size,
10137                    Register rn,
10138                    WriteBack write_back,
10139                    RegisterList registers) {
10140  VIXL_ASSERT(AllowAssembler());
10141  CheckIT(cond);
10142  if (IsUsingT32()) {
10143    // STM{<c>}{<q>} <Rn>!, <registers> ; T1
10144    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
10145        ((registers.GetList() & ~0xff) == 0)) {
10146      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
10147                 GetRegisterListEncoding(registers, 0, 8));
10148      AdvanceIT();
10149      return;
10150    }
10151    // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
10152    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10153      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10154                 (write_back.GetWriteBackUint32() << 21) |
10155                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10156                 GetRegisterListEncoding(registers, 0, 13));
10157      AdvanceIT();
10158      return;
10159    }
10160  } else {
10161    // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
10162    if (cond.IsNotNever()) {
10163      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10164              (write_back.GetWriteBackUint32() << 21) |
10165              GetRegisterListEncoding(registers, 0, 16));
10166      return;
10167    }
10168  }
10169  Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
10170}
10171
10172void Assembler::stmda(Condition cond,
10173                      Register rn,
10174                      WriteBack write_back,
10175                      RegisterList registers) {
10176  VIXL_ASSERT(AllowAssembler());
10177  CheckIT(cond);
10178  if (IsUsingA32()) {
10179    // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10180    if (cond.IsNotNever()) {
10181      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10182              (write_back.GetWriteBackUint32() << 21) |
10183              GetRegisterListEncoding(registers, 0, 16));
10184      return;
10185    }
10186  }
10187  Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
10188}
10189
10190void Assembler::stmdb(Condition cond,
10191                      EncodingSize size,
10192                      Register rn,
10193                      WriteBack write_back,
10194                      RegisterList registers) {
10195  VIXL_ASSERT(AllowAssembler());
10196  CheckIT(cond);
10197  if (IsUsingT32()) {
10198    // STMDB{<c>}{<q>} SP!, <registers> ; T1
10199    if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
10200        ((registers.GetList() & ~0x40ff) == 0)) {
10201      EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
10202                 GetRegisterListEncoding(registers, 0, 8));
10203      AdvanceIT();
10204      return;
10205    }
10206    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
10207    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10208      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
10209                 (write_back.GetWriteBackUint32() << 21) |
10210                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10211                 GetRegisterListEncoding(registers, 0, 13));
10212      AdvanceIT();
10213      return;
10214    }
10215  } else {
10216    // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
10217    if (cond.IsNotNever()) {
10218      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10219              (write_back.GetWriteBackUint32() << 21) |
10220              GetRegisterListEncoding(registers, 0, 16));
10221      return;
10222    }
10223  }
10224  Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
10225}
10226
10227void Assembler::stmea(Condition cond,
10228                      EncodingSize size,
10229                      Register rn,
10230                      WriteBack write_back,
10231                      RegisterList registers) {
10232  VIXL_ASSERT(AllowAssembler());
10233  CheckIT(cond);
10234  if (IsUsingT32()) {
10235    // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
10236    if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
10237        ((registers.GetList() & ~0xff) == 0)) {
10238      EmitT32_16(0xc000 | (rn.GetCode() << 8) |
10239                 GetRegisterListEncoding(registers, 0, 8));
10240      AdvanceIT();
10241      return;
10242    }
10243    // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
10244    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10245      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10246                 (write_back.GetWriteBackUint32() << 21) |
10247                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10248                 GetRegisterListEncoding(registers, 0, 13));
10249      AdvanceIT();
10250      return;
10251    }
10252    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
10253    if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10254      EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10255                 (write_back.GetWriteBackUint32() << 21) |
10256                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10257                 GetRegisterListEncoding(registers, 0, 13));
10258      AdvanceIT();
10259      return;
10260    }
10261  } else {
10262    // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10263    if (cond.IsNotNever()) {
10264      EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10265              (write_back.GetWriteBackUint32() << 21) |
10266              GetRegisterListEncoding(registers, 0, 16));
10267      return;
10268    }
10269  }
10270  Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
10271}
10272
10273void Assembler::stmed(Condition cond,
10274                      Register rn,
10275                      WriteBack write_back,
10276                      RegisterList registers) {
10277  VIXL_ASSERT(AllowAssembler());
10278  CheckIT(cond);
10279  if (IsUsingA32()) {
10280    // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
10281    if (cond.IsNotNever()) {
10282      EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10283              (write_back.GetWriteBackUint32() << 21) |
10284              GetRegisterListEncoding(registers, 0, 16));
10285      return;
10286    }
10287  }
10288  Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
10289}
10290
10291void Assembler::stmfa(Condition cond,
10292                      Register rn,
10293                      WriteBack write_back,
10294                      RegisterList registers) {
10295  VIXL_ASSERT(AllowAssembler());
10296  CheckIT(cond);
10297  if (IsUsingA32()) {
10298    // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10299    if (cond.IsNotNever()) {
10300      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10301              (write_back.GetWriteBackUint32() << 21) |
10302              GetRegisterListEncoding(registers, 0, 16));
10303      return;
10304    }
10305  }
10306  Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
10307}
10308
10309void Assembler::stmfd(Condition cond,
10310                      Register rn,
10311                      WriteBack write_back,
10312                      RegisterList registers) {
10313  VIXL_ASSERT(AllowAssembler());
10314  CheckIT(cond);
10315  if (IsUsingT32()) {
10316    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
10317    if (((registers.GetList() & ~0x5fff) == 0)) {
10318      EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
10319                 (write_back.GetWriteBackUint32() << 21) |
10320                 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10321                 GetRegisterListEncoding(registers, 0, 13));
10322      AdvanceIT();
10323      return;
10324    }
10325  } else {
10326    // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
10327    if (cond.IsNotNever()) {
10328      EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10329              (write_back.GetWriteBackUint32() << 21) |
10330              GetRegisterListEncoding(registers, 0, 16));
10331      return;
10332    }
10333  }
10334  Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
10335}
10336
10337void Assembler::stmib(Condition cond,
10338                      Register rn,
10339                      WriteBack write_back,
10340                      RegisterList registers) {
10341  VIXL_ASSERT(AllowAssembler());
10342  CheckIT(cond);
10343  if (IsUsingA32()) {
10344    // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
10345    if (cond.IsNotNever()) {
10346      EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10347              (write_back.GetWriteBackUint32() << 21) |
10348              GetRegisterListEncoding(registers, 0, 16));
10349      return;
10350    }
10351  }
10352  Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
10353}
10354
10355void Assembler::str(Condition cond,
10356                    EncodingSize size,
10357                    Register rt,
10358                    const MemOperand& operand) {
10359  VIXL_ASSERT(AllowAssembler());
10360  CheckIT(cond);
10361  if (operand.IsImmediate()) {
10362    Register rn = operand.GetBaseRegister();
10363    int32_t offset = operand.GetOffsetImmediate();
10364    if (IsUsingT32()) {
10365      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10366      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10367          (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
10368        int32_t offset_ = offset >> 2;
10369        EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
10370                   ((offset_ & 0x1f) << 6));
10371        AdvanceIT();
10372        return;
10373      }
10374      // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
10375      if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
10376          ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
10377        int32_t offset_ = offset >> 2;
10378        EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
10379        AdvanceIT();
10380        return;
10381      }
10382      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
10383      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10384          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10385        EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10386                   (offset & 0xfff));
10387        AdvanceIT();
10388        return;
10389      }
10390      // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
10391      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10392          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10393        EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10394                   (-offset & 0xff));
10395        AdvanceIT();
10396        return;
10397      }
10398      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
10399      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10400          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10401        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10402        uint32_t offset_ = abs(offset);
10403        EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10404                   offset_ | (sign << 9));
10405        AdvanceIT();
10406        return;
10407      }
10408      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
10409      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10410          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10411        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10412        uint32_t offset_ = abs(offset);
10413        EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10414                   offset_ | (sign << 9));
10415        AdvanceIT();
10416        return;
10417      }
10418    } else {
10419      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10420      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
10421          cond.IsNotNever()) {
10422        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10423        uint32_t offset_ = abs(offset);
10424        EmitA32(0x05000000U | (cond.GetCondition() << 28) |
10425                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10426                (sign << 23));
10427        return;
10428      }
10429      // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10430      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
10431          cond.IsNotNever()) {
10432        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10433        uint32_t offset_ = abs(offset);
10434        EmitA32(0x04000000U | (cond.GetCondition() << 28) |
10435                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10436                (sign << 23));
10437        return;
10438      }
10439      // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10440      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
10441          cond.IsNotNever()) {
10442        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10443        uint32_t offset_ = abs(offset);
10444        EmitA32(0x05200000U | (cond.GetCondition() << 28) |
10445                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10446                (sign << 23));
10447        return;
10448      }
10449    }
10450  }
10451  if (operand.IsPlainRegister()) {
10452    Register rn = operand.GetBaseRegister();
10453    Sign sign = operand.GetSign();
10454    Register rm = operand.GetOffsetRegister();
10455    if (IsUsingT32()) {
10456      // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
10457      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
10458          sign.IsPlus() && operand.IsOffset()) {
10459        EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
10460                   (rm.GetCode() << 6));
10461        AdvanceIT();
10462        return;
10463      }
10464    }
10465  }
10466  if (operand.IsShiftedRegister()) {
10467    Register rn = operand.GetBaseRegister();
10468    Sign sign = operand.GetSign();
10469    Register rm = operand.GetOffsetRegister();
10470    Shift shift = operand.GetShift();
10471    uint32_t amount = operand.GetShiftAmount();
10472    if (IsUsingT32()) {
10473      // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
10474      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
10475          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10476        EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10477                   rm.GetCode() | (amount << 4));
10478        AdvanceIT();
10479        return;
10480      }
10481    } else {
10482      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
10483      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever()) {
10484        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10485        uint32_t shift_ = TypeEncodingValue(shift);
10486        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10487        EmitA32(0x07000000U | (cond.GetCondition() << 28) |
10488                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10489                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10490        return;
10491      }
10492      // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
10493      if (operand.IsShiftValid() && operand.IsPostIndex() &&
10494          cond.IsNotNever()) {
10495        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10496        uint32_t shift_ = TypeEncodingValue(shift);
10497        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10498        EmitA32(0x06000000U | (cond.GetCondition() << 28) |
10499                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10500                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10501        return;
10502      }
10503      // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
10504      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever()) {
10505        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10506        uint32_t shift_ = TypeEncodingValue(shift);
10507        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10508        EmitA32(0x07200000U | (cond.GetCondition() << 28) |
10509                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10510                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10511        return;
10512      }
10513    }
10514  }
10515  Delegate(kStr, &Assembler::str, cond, size, rt, operand);
10516}
10517
10518void Assembler::strb(Condition cond,
10519                     EncodingSize size,
10520                     Register rt,
10521                     const MemOperand& operand) {
10522  VIXL_ASSERT(AllowAssembler());
10523  CheckIT(cond);
10524  if (operand.IsImmediate()) {
10525    Register rn = operand.GetBaseRegister();
10526    int32_t offset = operand.GetOffsetImmediate();
10527    if (IsUsingT32()) {
10528      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10529      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10530          (offset <= 31) && operand.IsOffset()) {
10531        EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
10532                   ((offset & 0x1f) << 6));
10533        AdvanceIT();
10534        return;
10535      }
10536      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
10537      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10538          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10539        EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10540                   (offset & 0xfff));
10541        AdvanceIT();
10542        return;
10543      }
10544      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
10545      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10546          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10547        EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10548                   (-offset & 0xff));
10549        AdvanceIT();
10550        return;
10551      }
10552      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
10553      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10554          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10555        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10556        uint32_t offset_ = abs(offset);
10557        EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10558                   offset_ | (sign << 9));
10559        AdvanceIT();
10560        return;
10561      }
10562      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
10563      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10564          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10565        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10566        uint32_t offset_ = abs(offset);
10567        EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10568                   offset_ | (sign << 9));
10569        AdvanceIT();
10570        return;
10571      }
10572    } else {
10573      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10574      if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
10575          cond.IsNotNever()) {
10576        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10577        uint32_t offset_ = abs(offset);
10578        EmitA32(0x05400000U | (cond.GetCondition() << 28) |
10579                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10580                (sign << 23));
10581        return;
10582      }
10583      // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10584      if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
10585          cond.IsNotNever()) {
10586        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10587        uint32_t offset_ = abs(offset);
10588        EmitA32(0x04400000U | (cond.GetCondition() << 28) |
10589                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10590                (sign << 23));
10591        return;
10592      }
10593      // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10594      if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
10595          cond.IsNotNever()) {
10596        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10597        uint32_t offset_ = abs(offset);
10598        EmitA32(0x05600000U | (cond.GetCondition() << 28) |
10599                (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10600                (sign << 23));
10601        return;
10602      }
10603    }
10604  }
10605  if (operand.IsPlainRegister()) {
10606    Register rn = operand.GetBaseRegister();
10607    Sign sign = operand.GetSign();
10608    Register rm = operand.GetOffsetRegister();
10609    if (IsUsingT32()) {
10610      // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
10611      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
10612          sign.IsPlus() && operand.IsOffset()) {
10613        EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
10614                   (rm.GetCode() << 6));
10615        AdvanceIT();
10616        return;
10617      }
10618    }
10619  }
10620  if (operand.IsShiftedRegister()) {
10621    Register rn = operand.GetBaseRegister();
10622    Sign sign = operand.GetSign();
10623    Register rm = operand.GetOffsetRegister();
10624    Shift shift = operand.GetShift();
10625    uint32_t amount = operand.GetShiftAmount();
10626    if (IsUsingT32()) {
10627      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
10628      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
10629          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10630        EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10631                   rm.GetCode() | (amount << 4));
10632        AdvanceIT();
10633        return;
10634      }
10635    } else {
10636      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
10637      if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever()) {
10638        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10639        uint32_t shift_ = TypeEncodingValue(shift);
10640        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10641        EmitA32(0x07400000U | (cond.GetCondition() << 28) |
10642                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10643                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10644        return;
10645      }
10646      // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
10647      if (operand.IsShiftValid() && operand.IsPostIndex() &&
10648          cond.IsNotNever()) {
10649        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10650        uint32_t shift_ = TypeEncodingValue(shift);
10651        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10652        EmitA32(0x06400000U | (cond.GetCondition() << 28) |
10653                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10654                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10655        return;
10656      }
10657      // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
10658      if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever()) {
10659        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10660        uint32_t shift_ = TypeEncodingValue(shift);
10661        uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10662        EmitA32(0x07600000U | (cond.GetCondition() << 28) |
10663                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10664                (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10665        return;
10666      }
10667    }
10668  }
10669  Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
10670}
10671
10672void Assembler::strd(Condition cond,
10673                     Register rt,
10674                     Register rt2,
10675                     const MemOperand& operand) {
10676  VIXL_ASSERT(AllowAssembler());
10677  CheckIT(cond);
10678  if (operand.IsImmediate()) {
10679    Register rn = operand.GetBaseRegister();
10680    int32_t offset = operand.GetOffsetImmediate();
10681    if (IsUsingT32()) {
10682      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
10683      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10684          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10685        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10686        uint32_t offset_ = abs(offset) >> 2;
10687        EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10688                   (rn.GetCode() << 16) | offset_ | (sign << 23));
10689        AdvanceIT();
10690        return;
10691      }
10692      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
10693      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10694          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10695        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10696        uint32_t offset_ = abs(offset) >> 2;
10697        EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10698                   (rn.GetCode() << 16) | offset_ | (sign << 23));
10699        AdvanceIT();
10700        return;
10701      }
10702      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
10703      if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10704          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10705        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10706        uint32_t offset_ = abs(offset) >> 2;
10707        EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10708                   (rn.GetCode() << 16) | offset_ | (sign << 23));
10709        AdvanceIT();
10710        return;
10711      }
10712    } else {
10713      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
10714      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10715          (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
10716          cond.IsNotNever() &&
10717          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10718        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10719        uint32_t offset_ = abs(offset);
10720        EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
10721                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10722                ((offset_ & 0xf0) << 4) | (sign << 23));
10723        return;
10724      }
10725      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
10726      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10727          (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
10728          cond.IsNotNever() &&
10729          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10730        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10731        uint32_t offset_ = abs(offset);
10732        EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
10733                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10734                ((offset_ & 0xf0) << 4) | (sign << 23));
10735        return;
10736      }
10737      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
10738      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10739          (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
10740          cond.IsNotNever() &&
10741          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10742        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10743        uint32_t offset_ = abs(offset);
10744        EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
10745                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10746                ((offset_ & 0xf0) << 4) | (sign << 23));
10747        return;
10748      }
10749    }
10750  }
10751  if (operand.IsPlainRegister()) {
10752    Register rn = operand.GetBaseRegister();
10753    Sign sign = operand.GetSign();
10754    Register rm = operand.GetOffsetRegister();
10755    if (IsUsingA32()) {
10756      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
10757      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10758          operand.IsOffset() && cond.IsNotNever() &&
10759          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10760        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10761        EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
10762                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10763                (sign_ << 23));
10764        return;
10765      }
10766      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
10767      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10768          operand.IsPostIndex() && cond.IsNotNever() &&
10769          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10770        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10771        EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
10772                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10773                (sign_ << 23));
10774        return;
10775      }
10776      // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
10777      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10778          operand.IsPreIndex() && cond.IsNotNever() &&
10779          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10780        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10781        EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
10782                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10783                (sign_ << 23));
10784        return;
10785      }
10786    }
10787  }
10788  Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
10789}
10790
10791void Assembler::strex(Condition cond,
10792                      Register rd,
10793                      Register rt,
10794                      const MemOperand& operand) {
10795  VIXL_ASSERT(AllowAssembler());
10796  CheckIT(cond);
10797  if (operand.IsImmediate()) {
10798    Register rn = operand.GetBaseRegister();
10799    int32_t offset = operand.GetOffsetImmediate();
10800    if (IsUsingT32()) {
10801      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
10802      if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
10803          operand.IsOffset()) {
10804        int32_t offset_ = offset >> 2;
10805        EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
10806                   (rn.GetCode() << 16) | (offset_ & 0xff));
10807        AdvanceIT();
10808        return;
10809      }
10810    } else {
10811      // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
10812      if ((offset == 0) && operand.IsOffset() && cond.IsNotNever()) {
10813        EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
10814                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10815        return;
10816      }
10817    }
10818  }
10819  Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
10820}
10821
10822void Assembler::strexb(Condition cond,
10823                       Register rd,
10824                       Register rt,
10825                       const MemOperand& operand) {
10826  VIXL_ASSERT(AllowAssembler());
10827  CheckIT(cond);
10828  if (operand.IsImmediateZero()) {
10829    Register rn = operand.GetBaseRegister();
10830    if (IsUsingT32()) {
10831      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10832      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10833        EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
10834                   (rn.GetCode() << 16));
10835        AdvanceIT();
10836        return;
10837      }
10838    } else {
10839      // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10840      if (operand.IsOffset() && cond.IsNotNever() &&
10841          (!rn.IsPC() || AllowUnpredictable())) {
10842        EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
10843                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10844        return;
10845      }
10846    }
10847  }
10848  Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
10849}
10850
10851void Assembler::strexd(Condition cond,
10852                       Register rd,
10853                       Register rt,
10854                       Register rt2,
10855                       const MemOperand& operand) {
10856  VIXL_ASSERT(AllowAssembler());
10857  CheckIT(cond);
10858  if (operand.IsImmediateZero()) {
10859    Register rn = operand.GetBaseRegister();
10860    if (IsUsingT32()) {
10861      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
10862      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10863        EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
10864                   (rt2.GetCode() << 8) | (rn.GetCode() << 16));
10865        AdvanceIT();
10866        return;
10867      }
10868    } else {
10869      // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
10870      if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10871          operand.IsOffset() && cond.IsNotNever() &&
10872          ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
10873           AllowUnpredictable())) {
10874        EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
10875                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10876        return;
10877      }
10878    }
10879  }
10880  Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
10881}
10882
10883void Assembler::strexh(Condition cond,
10884                       Register rd,
10885                       Register rt,
10886                       const MemOperand& operand) {
10887  VIXL_ASSERT(AllowAssembler());
10888  CheckIT(cond);
10889  if (operand.IsImmediateZero()) {
10890    Register rn = operand.GetBaseRegister();
10891    if (IsUsingT32()) {
10892      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10893      if (operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
10894        EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
10895                   (rn.GetCode() << 16));
10896        AdvanceIT();
10897        return;
10898      }
10899    } else {
10900      // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10901      if (operand.IsOffset() && cond.IsNotNever() &&
10902          (!rn.IsPC() || AllowUnpredictable())) {
10903        EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
10904                (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10905        return;
10906      }
10907    }
10908  }
10909  Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
10910}
10911
10912void Assembler::strh(Condition cond,
10913                     EncodingSize size,
10914                     Register rt,
10915                     const MemOperand& operand) {
10916  VIXL_ASSERT(AllowAssembler());
10917  CheckIT(cond);
10918  if (operand.IsImmediate()) {
10919    Register rn = operand.GetBaseRegister();
10920    int32_t offset = operand.GetOffsetImmediate();
10921    if (IsUsingT32()) {
10922      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10923      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10924          (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
10925        int32_t offset_ = offset >> 1;
10926        EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
10927                   ((offset_ & 0x1f) << 6));
10928        AdvanceIT();
10929        return;
10930      }
10931      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
10932      if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10933          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10934        EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10935                   (offset & 0xfff));
10936        AdvanceIT();
10937        return;
10938      }
10939      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
10940      if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10941          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
10942        EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10943                   (-offset & 0xff));
10944        AdvanceIT();
10945        return;
10946      }
10947      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
10948      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10949          operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10950        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10951        uint32_t offset_ = abs(offset);
10952        EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10953                   offset_ | (sign << 9));
10954        AdvanceIT();
10955        return;
10956      }
10957      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
10958      if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10959          operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
10960        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10961        uint32_t offset_ = abs(offset);
10962        EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10963                   offset_ | (sign << 9));
10964        AdvanceIT();
10965        return;
10966      }
10967    } else {
10968      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10969      if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
10970          cond.IsNotNever()) {
10971        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10972        uint32_t offset_ = abs(offset);
10973        EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
10974                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10975                ((offset_ & 0xf0) << 4) | (sign << 23));
10976        return;
10977      }
10978      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10979      if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
10980          cond.IsNotNever()) {
10981        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10982        uint32_t offset_ = abs(offset);
10983        EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
10984                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10985                ((offset_ & 0xf0) << 4) | (sign << 23));
10986        return;
10987      }
10988      // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10989      if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
10990          cond.IsNotNever()) {
10991        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10992        uint32_t offset_ = abs(offset);
10993        EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
10994                (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10995                ((offset_ & 0xf0) << 4) | (sign << 23));
10996        return;
10997      }
10998    }
10999  }
11000  if (operand.IsPlainRegister()) {
11001    Register rn = operand.GetBaseRegister();
11002    Sign sign = operand.GetSign();
11003    Register rm = operand.GetOffsetRegister();
11004    if (IsUsingT32()) {
11005      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11006      if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11007          sign.IsPlus() && operand.IsOffset()) {
11008        EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
11009                   (rm.GetCode() << 6));
11010        AdvanceIT();
11011        return;
11012      }
11013    } else {
11014      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
11015      if (operand.IsOffset() && cond.IsNotNever()) {
11016        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11017        EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
11018                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11019                (sign_ << 23));
11020        return;
11021      }
11022      // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
11023      if (operand.IsPostIndex() && cond.IsNotNever()) {
11024        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11025        EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
11026                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11027                (sign_ << 23));
11028        return;
11029      }
11030      // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
11031      if (operand.IsPreIndex() && cond.IsNotNever()) {
11032        uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11033        EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
11034                (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11035                (sign_ << 23));
11036        return;
11037      }
11038    }
11039  }
11040  if (operand.IsShiftedRegister()) {
11041    Register rn = operand.GetBaseRegister();
11042    Sign sign = operand.GetSign();
11043    Register rm = operand.GetOffsetRegister();
11044    Shift shift = operand.GetShift();
11045    uint32_t amount = operand.GetShiftAmount();
11046    if (IsUsingT32()) {
11047      // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11048      if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11049          operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf)) {
11050        EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11051                   rm.GetCode() | (amount << 4));
11052        AdvanceIT();
11053        return;
11054      }
11055    }
11056  }
11057  Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
11058}
11059
11060void Assembler::sub(Condition cond,
11061                    EncodingSize size,
11062                    Register rd,
11063                    Register rn,
11064                    const Operand& operand) {
11065  VIXL_ASSERT(AllowAssembler());
11066  CheckIT(cond);
11067  if (operand.IsImmediate()) {
11068    uint32_t imm = operand.GetImmediate();
11069    if (IsUsingT32()) {
11070      ImmediateT32 immediate_t32(imm);
11071      // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
11072      if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11073          (imm <= 7)) {
11074        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
11075        AdvanceIT();
11076        return;
11077      }
11078      // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
11079      if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
11080          (imm <= 255)) {
11081        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11082        AdvanceIT();
11083        return;
11084      }
11085      // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
11086      if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
11087          ((imm % 4) == 0)) {
11088        uint32_t imm_ = imm >> 2;
11089        EmitT32_16(0xb080 | imm_);
11090        AdvanceIT();
11091        return;
11092      }
11093      // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
11094      if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) {
11095        EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11096                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11097        AdvanceIT();
11098        return;
11099      }
11100      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
11101      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp)) {
11102        EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11103                   (immediate_t32.GetEncodingValue() & 0xff) |
11104                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11105                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11106        AdvanceIT();
11107        return;
11108      }
11109      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
11110      if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
11111        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11112                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11113        AdvanceIT();
11114        return;
11115      }
11116      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
11117      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid()) {
11118        EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
11119                   (immediate_t32.GetEncodingValue() & 0xff) |
11120                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11121                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11122        AdvanceIT();
11123        return;
11124      }
11125      // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
11126      if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095)) {
11127        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11128                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11129        AdvanceIT();
11130        return;
11131      }
11132    } else {
11133      ImmediateA32 immediate_a32(imm);
11134      // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
11135      if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
11136        EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
11137                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11138        return;
11139      }
11140      // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
11141      if (immediate_a32.IsValid() && cond.IsNotNever() &&
11142          ((rn.GetCode() & 0xd) != 0xd)) {
11143        EmitA32(0x02400000U | (cond.GetCondition() << 28) |
11144                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
11145                immediate_a32.GetEncodingValue());
11146        return;
11147      }
11148      // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
11149      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
11150        EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
11151                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11152        return;
11153      }
11154    }
11155  }
11156  if (operand.IsImmediateShiftedRegister()) {
11157    Register rm = operand.GetBaseRegister();
11158    if (operand.IsPlainRegister()) {
11159      if (IsUsingT32()) {
11160        // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
11161        if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11162            rm.IsLow()) {
11163          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
11164                     (rm.GetCode() << 6));
11165          AdvanceIT();
11166          return;
11167        }
11168        // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
11169        if (rn.Is(sp)) {
11170          EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
11171          AdvanceIT();
11172          return;
11173        }
11174      }
11175    }
11176    Shift shift = operand.GetShift();
11177    uint32_t amount = operand.GetShiftAmount();
11178    if (IsUsingT32()) {
11179      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
11180      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp)) {
11181        uint32_t amount_ = amount % 32;
11182        EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11183                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
11184                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11185        AdvanceIT();
11186        return;
11187      }
11188      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
11189      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount)) {
11190        uint32_t amount_ = amount % 32;
11191        EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
11192                   (operand.GetTypeEncodingValue() << 4) |
11193                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11194        AdvanceIT();
11195        return;
11196      }
11197    } else {
11198      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
11199      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
11200        uint32_t amount_ = amount % 32;
11201        EmitA32(0x00400000U | (cond.GetCondition() << 28) |
11202                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11203                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11204        return;
11205      }
11206      // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
11207      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
11208        uint32_t amount_ = amount % 32;
11209        EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
11210                (rd.GetCode() << 12) | rm.GetCode() |
11211                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11212        return;
11213      }
11214    }
11215  }
11216  if (operand.IsRegisterShiftedRegister()) {
11217    Register rm = operand.GetBaseRegister();
11218    Shift shift = operand.GetShift();
11219    if (IsUsingA32()) {
11220      // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
11221      if (cond.IsNotNever()) {
11222        EmitA32(0x00400010U | (cond.GetCondition() << 28) |
11223                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11224                (shift.GetType() << 5) |
11225                (operand.GetShiftRegister().GetCode() << 8));
11226        return;
11227      }
11228    }
11229  }
11230  Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
11231}
11232
11233void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
11234  VIXL_ASSERT(AllowAssembler());
11235  CheckIT(cond);
11236  if (operand.IsImmediate()) {
11237    uint32_t imm = operand.GetImmediate();
11238    if (IsUsingT32()) {
11239      // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
11240      if (InITBlock() && rd.IsLow() && (imm <= 255)) {
11241        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11242        AdvanceIT();
11243        return;
11244      }
11245    }
11246  }
11247  Delegate(kSub, &Assembler::sub, cond, rd, operand);
11248}
11249
11250void Assembler::subs(Condition cond,
11251                     EncodingSize size,
11252                     Register rd,
11253                     Register rn,
11254                     const Operand& operand) {
11255  VIXL_ASSERT(AllowAssembler());
11256  CheckIT(cond);
11257  if (operand.IsImmediate()) {
11258    uint32_t imm = operand.GetImmediate();
11259    if (IsUsingT32()) {
11260      ImmediateT32 immediate_t32(imm);
11261      // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
11262      if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11263          (imm <= 7)) {
11264        EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
11265        AdvanceIT();
11266        return;
11267      }
11268      // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
11269      if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
11270          (imm <= 255)) {
11271        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11272        AdvanceIT();
11273        return;
11274      }
11275      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
11276      if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
11277          !rd.Is(pc)) {
11278        EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11279                   (immediate_t32.GetEncodingValue() & 0xff) |
11280                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11281                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11282        AdvanceIT();
11283        return;
11284      }
11285      // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
11286      if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255)) {
11287        EmitT32_32(0xf3de8f00U | imm);
11288        AdvanceIT();
11289        return;
11290      }
11291      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
11292      if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
11293          !rd.Is(pc)) {
11294        EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
11295                   (immediate_t32.GetEncodingValue() & 0xff) |
11296                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11297                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11298        AdvanceIT();
11299        return;
11300      }
11301    } else {
11302      ImmediateA32 immediate_a32(imm);
11303      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
11304      if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
11305        EmitA32(0x02500000U | (cond.GetCondition() << 28) |
11306                (rd.GetCode() << 12) | (rn.GetCode() << 16) |
11307                immediate_a32.GetEncodingValue());
11308        return;
11309      }
11310      // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
11311      if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
11312        EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
11313                (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11314        return;
11315      }
11316    }
11317  }
11318  if (operand.IsImmediateShiftedRegister()) {
11319    Register rm = operand.GetBaseRegister();
11320    if (operand.IsPlainRegister()) {
11321      if (IsUsingT32()) {
11322        // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11323        if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11324            rm.IsLow()) {
11325          EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
11326                     (rm.GetCode() << 6));
11327          AdvanceIT();
11328          return;
11329        }
11330      }
11331    }
11332    Shift shift = operand.GetShift();
11333    uint32_t amount = operand.GetShiftAmount();
11334    if (IsUsingT32()) {
11335      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
11336      if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
11337          !rd.Is(pc)) {
11338        uint32_t amount_ = amount % 32;
11339        EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11340                   rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
11341                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11342        AdvanceIT();
11343        return;
11344      }
11345      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
11346      if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
11347          !rd.Is(pc)) {
11348        uint32_t amount_ = amount % 32;
11349        EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
11350                   (operand.GetTypeEncodingValue() << 4) |
11351                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11352        AdvanceIT();
11353        return;
11354      }
11355    } else {
11356      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
11357      if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
11358        uint32_t amount_ = amount % 32;
11359        EmitA32(0x00500000U | (cond.GetCondition() << 28) |
11360                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11361                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11362        return;
11363      }
11364      // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
11365      if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
11366        uint32_t amount_ = amount % 32;
11367        EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
11368                (rd.GetCode() << 12) | rm.GetCode() |
11369                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11370        return;
11371      }
11372    }
11373  }
11374  if (operand.IsRegisterShiftedRegister()) {
11375    Register rm = operand.GetBaseRegister();
11376    Shift shift = operand.GetShift();
11377    if (IsUsingA32()) {
11378      // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
11379      if (cond.IsNotNever()) {
11380        EmitA32(0x00500010U | (cond.GetCondition() << 28) |
11381                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11382                (shift.GetType() << 5) |
11383                (operand.GetShiftRegister().GetCode() << 8));
11384        return;
11385      }
11386    }
11387  }
11388  Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
11389}
11390
11391void Assembler::subs(Register rd, const Operand& operand) {
11392  VIXL_ASSERT(AllowAssembler());
11393  CheckIT(al);
11394  if (operand.IsImmediate()) {
11395    uint32_t imm = operand.GetImmediate();
11396    if (IsUsingT32()) {
11397      // SUBS{<q>} <Rdn>, #<imm8> ; T2
11398      if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
11399        EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11400        AdvanceIT();
11401        return;
11402      }
11403    }
11404  }
11405  Delegate(kSubs, &Assembler::subs, rd, operand);
11406}
11407
11408void Assembler::subw(Condition cond,
11409                     Register rd,
11410                     Register rn,
11411                     const Operand& operand) {
11412  VIXL_ASSERT(AllowAssembler());
11413  CheckIT(cond);
11414  if (operand.IsImmediate()) {
11415    uint32_t imm = operand.GetImmediate();
11416    if (IsUsingT32()) {
11417      // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
11418      if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
11419        EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11420                   (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11421        AdvanceIT();
11422        return;
11423      }
11424      // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
11425      if (rn.Is(sp) && (imm <= 4095)) {
11426        EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11427                   ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11428        AdvanceIT();
11429        return;
11430      }
11431    }
11432  }
11433  Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
11434}
11435
11436void Assembler::svc(Condition cond, uint32_t imm) {
11437  VIXL_ASSERT(AllowAssembler());
11438  CheckIT(cond);
11439  if (IsUsingT32()) {
11440    // SVC{<c>}{<q>} {#}<imm> ; T1
11441    if ((imm <= 255)) {
11442      EmitT32_16(0xdf00 | imm);
11443      AdvanceIT();
11444      return;
11445    }
11446  } else {
11447    // SVC{<c>}{<q>} {#}<imm> ; A1
11448    if ((imm <= 16777215) && cond.IsNotNever()) {
11449      EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
11450      return;
11451    }
11452  }
11453  Delegate(kSvc, &Assembler::svc, cond, imm);
11454}
11455
11456void Assembler::sxtab(Condition cond,
11457                      Register rd,
11458                      Register rn,
11459                      const Operand& operand) {
11460  VIXL_ASSERT(AllowAssembler());
11461  CheckIT(cond);
11462  if (operand.IsImmediateShiftedRegister()) {
11463    Register rm = operand.GetBaseRegister();
11464    Shift shift = operand.GetShift();
11465    uint32_t amount = operand.GetShiftAmount();
11466    if (IsUsingT32()) {
11467      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11468      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11469          ((amount % 8) == 0) && !rn.Is(pc)) {
11470        uint32_t amount_ = amount / 8;
11471        EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11472                   rm.GetCode() | (amount_ << 4));
11473        AdvanceIT();
11474        return;
11475      }
11476    } else {
11477      // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11478      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11479          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11480        uint32_t amount_ = amount / 8;
11481        EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
11482                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11483                (amount_ << 10));
11484        return;
11485      }
11486    }
11487  }
11488  Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
11489}
11490
11491void Assembler::sxtab16(Condition cond,
11492                        Register rd,
11493                        Register rn,
11494                        const Operand& operand) {
11495  VIXL_ASSERT(AllowAssembler());
11496  CheckIT(cond);
11497  if (operand.IsImmediateShiftedRegister()) {
11498    Register rm = operand.GetBaseRegister();
11499    Shift shift = operand.GetShift();
11500    uint32_t amount = operand.GetShiftAmount();
11501    if (IsUsingT32()) {
11502      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11503      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11504          ((amount % 8) == 0) && !rn.Is(pc)) {
11505        uint32_t amount_ = amount / 8;
11506        EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11507                   rm.GetCode() | (amount_ << 4));
11508        AdvanceIT();
11509        return;
11510      }
11511    } else {
11512      // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11513      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11514          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11515        uint32_t amount_ = amount / 8;
11516        EmitA32(0x06800070U | (cond.GetCondition() << 28) |
11517                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11518                (amount_ << 10));
11519        return;
11520      }
11521    }
11522  }
11523  Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
11524}
11525
11526void Assembler::sxtah(Condition cond,
11527                      Register rd,
11528                      Register rn,
11529                      const Operand& operand) {
11530  VIXL_ASSERT(AllowAssembler());
11531  CheckIT(cond);
11532  if (operand.IsImmediateShiftedRegister()) {
11533    Register rm = operand.GetBaseRegister();
11534    Shift shift = operand.GetShift();
11535    uint32_t amount = operand.GetShiftAmount();
11536    if (IsUsingT32()) {
11537      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11538      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11539          ((amount % 8) == 0) && !rn.Is(pc)) {
11540        uint32_t amount_ = amount / 8;
11541        EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11542                   rm.GetCode() | (amount_ << 4));
11543        AdvanceIT();
11544        return;
11545      }
11546    } else {
11547      // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11548      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11549          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11550        uint32_t amount_ = amount / 8;
11551        EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
11552                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11553                (amount_ << 10));
11554        return;
11555      }
11556    }
11557  }
11558  Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
11559}
11560
11561void Assembler::sxtb(Condition cond,
11562                     EncodingSize size,
11563                     Register rd,
11564                     const Operand& operand) {
11565  VIXL_ASSERT(AllowAssembler());
11566  CheckIT(cond);
11567  if (operand.IsImmediateShiftedRegister()) {
11568    Register rm = operand.GetBaseRegister();
11569    if (operand.IsPlainRegister()) {
11570      if (IsUsingT32()) {
11571        // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
11572        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
11573          EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
11574          AdvanceIT();
11575          return;
11576        }
11577      }
11578    }
11579    Shift shift = operand.GetShift();
11580    uint32_t amount = operand.GetShiftAmount();
11581    if (IsUsingT32()) {
11582      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
11583      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
11584          (amount <= 24) && ((amount % 8) == 0)) {
11585        uint32_t amount_ = amount / 8;
11586        EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11587                   (amount_ << 4));
11588        AdvanceIT();
11589        return;
11590      }
11591    } else {
11592      // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11593      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11594          ((amount % 8) == 0) && cond.IsNotNever()) {
11595        uint32_t amount_ = amount / 8;
11596        EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
11597                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11598        return;
11599      }
11600    }
11601  }
11602  Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
11603}
11604
11605void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
11606  VIXL_ASSERT(AllowAssembler());
11607  CheckIT(cond);
11608  if (operand.IsImmediateShiftedRegister()) {
11609    Register rm = operand.GetBaseRegister();
11610    Shift shift = operand.GetShift();
11611    uint32_t amount = operand.GetShiftAmount();
11612    if (IsUsingT32()) {
11613      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
11614      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11615          ((amount % 8) == 0)) {
11616        uint32_t amount_ = amount / 8;
11617        EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11618                   (amount_ << 4));
11619        AdvanceIT();
11620        return;
11621      }
11622    } else {
11623      // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11624      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11625          ((amount % 8) == 0) && cond.IsNotNever()) {
11626        uint32_t amount_ = amount / 8;
11627        EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
11628                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11629        return;
11630      }
11631    }
11632  }
11633  Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
11634}
11635
11636void Assembler::sxth(Condition cond,
11637                     EncodingSize size,
11638                     Register rd,
11639                     const Operand& operand) {
11640  VIXL_ASSERT(AllowAssembler());
11641  CheckIT(cond);
11642  if (operand.IsImmediateShiftedRegister()) {
11643    Register rm = operand.GetBaseRegister();
11644    if (operand.IsPlainRegister()) {
11645      if (IsUsingT32()) {
11646        // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
11647        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
11648          EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
11649          AdvanceIT();
11650          return;
11651        }
11652      }
11653    }
11654    Shift shift = operand.GetShift();
11655    uint32_t amount = operand.GetShiftAmount();
11656    if (IsUsingT32()) {
11657      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
11658      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
11659          (amount <= 24) && ((amount % 8) == 0)) {
11660        uint32_t amount_ = amount / 8;
11661        EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11662                   (amount_ << 4));
11663        AdvanceIT();
11664        return;
11665      }
11666    } else {
11667      // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11668      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11669          ((amount % 8) == 0) && cond.IsNotNever()) {
11670        uint32_t amount_ = amount / 8;
11671        EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
11672                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11673        return;
11674      }
11675    }
11676  }
11677  Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
11678}
11679
11680void Assembler::tbb(Condition cond, Register rn, Register rm) {
11681  VIXL_ASSERT(AllowAssembler());
11682  CheckIT(cond);
11683  if (IsUsingT32()) {
11684    // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
11685    if (OutsideITBlockAndAlOrLast(cond) &&
11686        (!rm.IsPC() || AllowUnpredictable())) {
11687      EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
11688      AdvanceIT();
11689      return;
11690    }
11691  }
11692  Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
11693}
11694
11695void Assembler::tbh(Condition cond, Register rn, Register rm) {
11696  VIXL_ASSERT(AllowAssembler());
11697  CheckIT(cond);
11698  if (IsUsingT32()) {
11699    // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
11700    if (OutsideITBlockAndAlOrLast(cond) &&
11701        (!rm.IsPC() || AllowUnpredictable())) {
11702      EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
11703      AdvanceIT();
11704      return;
11705    }
11706  }
11707  Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
11708}
11709
11710void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
11711  VIXL_ASSERT(AllowAssembler());
11712  CheckIT(cond);
11713  if (operand.IsImmediate()) {
11714    uint32_t imm = operand.GetImmediate();
11715    if (IsUsingT32()) {
11716      ImmediateT32 immediate_t32(imm);
11717      // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
11718      if (immediate_t32.IsValid()) {
11719        EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
11720                   (immediate_t32.GetEncodingValue() & 0xff) |
11721                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11722                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11723        AdvanceIT();
11724        return;
11725      }
11726    } else {
11727      ImmediateA32 immediate_a32(imm);
11728      // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
11729      if (immediate_a32.IsValid() && cond.IsNotNever()) {
11730        EmitA32(0x03300000U | (cond.GetCondition() << 28) |
11731                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
11732        return;
11733      }
11734    }
11735  }
11736  if (operand.IsImmediateShiftedRegister()) {
11737    Register rm = operand.GetBaseRegister();
11738    Shift shift = operand.GetShift();
11739    uint32_t amount = operand.GetShiftAmount();
11740    if (IsUsingT32()) {
11741      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
11742      if (shift.IsValidAmount(amount)) {
11743        uint32_t amount_ = amount % 32;
11744        EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
11745                   (operand.GetTypeEncodingValue() << 4) |
11746                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11747        AdvanceIT();
11748        return;
11749      }
11750    } else {
11751      // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
11752      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
11753        uint32_t amount_ = amount % 32;
11754        EmitA32(0x01300000U | (cond.GetCondition() << 28) |
11755                (rn.GetCode() << 16) | rm.GetCode() |
11756                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11757        return;
11758      }
11759    }
11760  }
11761  if (operand.IsRegisterShiftedRegister()) {
11762    Register rm = operand.GetBaseRegister();
11763    Shift shift = operand.GetShift();
11764    if (IsUsingA32()) {
11765      // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
11766      if (cond.IsNotNever()) {
11767        EmitA32(0x01300010U | (cond.GetCondition() << 28) |
11768                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
11769                (operand.GetShiftRegister().GetCode() << 8));
11770        return;
11771      }
11772    }
11773  }
11774  Delegate(kTeq, &Assembler::teq, cond, rn, operand);
11775}
11776
11777void Assembler::tst(Condition cond,
11778                    EncodingSize size,
11779                    Register rn,
11780                    const Operand& operand) {
11781  VIXL_ASSERT(AllowAssembler());
11782  CheckIT(cond);
11783  if (operand.IsImmediate()) {
11784    uint32_t imm = operand.GetImmediate();
11785    if (IsUsingT32()) {
11786      ImmediateT32 immediate_t32(imm);
11787      // TST{<c>}{<q>} <Rn>, #<const> ; T1
11788      if (!size.IsNarrow() && immediate_t32.IsValid()) {
11789        EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
11790                   (immediate_t32.GetEncodingValue() & 0xff) |
11791                   ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11792                   ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11793        AdvanceIT();
11794        return;
11795      }
11796    } else {
11797      ImmediateA32 immediate_a32(imm);
11798      // TST{<c>}{<q>} <Rn>, #<const> ; A1
11799      if (immediate_a32.IsValid() && cond.IsNotNever()) {
11800        EmitA32(0x03100000U | (cond.GetCondition() << 28) |
11801                (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
11802        return;
11803      }
11804    }
11805  }
11806  if (operand.IsImmediateShiftedRegister()) {
11807    Register rm = operand.GetBaseRegister();
11808    if (operand.IsPlainRegister()) {
11809      if (IsUsingT32()) {
11810        // TST{<c>}{<q>} <Rn>, <Rm> ; T1
11811        if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
11812          EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
11813          AdvanceIT();
11814          return;
11815        }
11816      }
11817    }
11818    Shift shift = operand.GetShift();
11819    uint32_t amount = operand.GetShiftAmount();
11820    if (IsUsingT32()) {
11821      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
11822      if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
11823        uint32_t amount_ = amount % 32;
11824        EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
11825                   (operand.GetTypeEncodingValue() << 4) |
11826                   ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11827        AdvanceIT();
11828        return;
11829      }
11830    } else {
11831      // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
11832      if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
11833        uint32_t amount_ = amount % 32;
11834        EmitA32(0x01100000U | (cond.GetCondition() << 28) |
11835                (rn.GetCode() << 16) | rm.GetCode() |
11836                (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11837        return;
11838      }
11839    }
11840  }
11841  if (operand.IsRegisterShiftedRegister()) {
11842    Register rm = operand.GetBaseRegister();
11843    Shift shift = operand.GetShift();
11844    if (IsUsingA32()) {
11845      // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
11846      if (cond.IsNotNever()) {
11847        EmitA32(0x01100010U | (cond.GetCondition() << 28) |
11848                (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
11849                (operand.GetShiftRegister().GetCode() << 8));
11850        return;
11851      }
11852    }
11853  }
11854  Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
11855}
11856
11857void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
11858  VIXL_ASSERT(AllowAssembler());
11859  CheckIT(cond);
11860  if (IsUsingT32()) {
11861    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11862    EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11863               rm.GetCode());
11864    AdvanceIT();
11865    return;
11866  } else {
11867    // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11868    if (cond.IsNotNever()) {
11869      EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11870              (rn.GetCode() << 16) | rm.GetCode());
11871      return;
11872    }
11873  }
11874  Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
11875}
11876
11877void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
11878  VIXL_ASSERT(AllowAssembler());
11879  CheckIT(cond);
11880  if (IsUsingT32()) {
11881    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11882    EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11883               rm.GetCode());
11884    AdvanceIT();
11885    return;
11886  } else {
11887    // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11888    if (cond.IsNotNever()) {
11889      EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11890              (rn.GetCode() << 16) | rm.GetCode());
11891      return;
11892    }
11893  }
11894  Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
11895}
11896
11897void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
11898  VIXL_ASSERT(AllowAssembler());
11899  CheckIT(cond);
11900  if (IsUsingT32()) {
11901    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11902    EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11903               rm.GetCode());
11904    AdvanceIT();
11905    return;
11906  } else {
11907    // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11908    if (cond.IsNotNever()) {
11909      EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11910              (rn.GetCode() << 16) | rm.GetCode());
11911      return;
11912    }
11913  }
11914  Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
11915}
11916
11917void Assembler::ubfx(Condition cond,
11918                     Register rd,
11919                     Register rn,
11920                     uint32_t lsb,
11921                     const Operand& operand) {
11922  VIXL_ASSERT(AllowAssembler());
11923  CheckIT(cond);
11924  if (operand.IsImmediate()) {
11925    uint32_t width = operand.GetImmediate();
11926    if (IsUsingT32()) {
11927      // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
11928      if ((lsb <= 31) &&
11929          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
11930        uint32_t widthm1 = width - 1;
11931        EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11932                   ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
11933        AdvanceIT();
11934        return;
11935      }
11936    } else {
11937      // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
11938      if ((lsb <= 31) && cond.IsNotNever() &&
11939          (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
11940        uint32_t widthm1 = width - 1;
11941        EmitA32(0x07e00050U | (cond.GetCondition() << 28) |
11942                (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) |
11943                (widthm1 << 16));
11944        return;
11945      }
11946    }
11947  }
11948  Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, operand);
11949}
11950
11951void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
11952  VIXL_ASSERT(AllowAssembler());
11953  CheckIT(cond);
11954  if (IsUsingT32()) {
11955    // UDF{<c>}{<q>} {#}<imm> ; T1
11956    if (!size.IsWide() && (imm <= 255)) {
11957      if (cond.Is(al) || AllowStronglyDiscouraged()) {
11958        EmitT32_16(0xde00 | imm);
11959        AdvanceIT();
11960        return;
11961      }
11962    }
11963    // UDF{<c>}{<q>} {#}<imm> ; T2
11964    if (!size.IsNarrow() && (imm <= 65535)) {
11965      if (cond.Is(al) || AllowStronglyDiscouraged()) {
11966        EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
11967        AdvanceIT();
11968        return;
11969      }
11970    }
11971  } else {
11972    // UDF{<c>}{<q>} {#}<imm> ; A1
11973    if ((imm <= 65535)) {
11974      if (cond.Is(al) || AllowStronglyDiscouraged()) {
11975        EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
11976        return;
11977      }
11978    }
11979  }
11980  Delegate(kUdf, &Assembler::udf, cond, size, imm);
11981}
11982
11983void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
11984  VIXL_ASSERT(AllowAssembler());
11985  CheckIT(cond);
11986  if (IsUsingT32()) {
11987    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11988    EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11989               rm.GetCode());
11990    AdvanceIT();
11991    return;
11992  } else {
11993    // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11994    if (cond.IsNotNever()) {
11995      EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
11996              rn.GetCode() | (rm.GetCode() << 8));
11997      return;
11998    }
11999  }
12000  Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
12001}
12002
12003void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
12004  VIXL_ASSERT(AllowAssembler());
12005  CheckIT(cond);
12006  if (IsUsingT32()) {
12007    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12008    EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12009               rm.GetCode());
12010    AdvanceIT();
12011    return;
12012  } else {
12013    // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12014    if (cond.IsNotNever()) {
12015      EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12016              (rn.GetCode() << 16) | rm.GetCode());
12017      return;
12018    }
12019  }
12020  Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
12021}
12022
12023void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
12024  VIXL_ASSERT(AllowAssembler());
12025  CheckIT(cond);
12026  if (IsUsingT32()) {
12027    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12028    EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12029               rm.GetCode());
12030    AdvanceIT();
12031    return;
12032  } else {
12033    // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12034    if (cond.IsNotNever()) {
12035      EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12036              (rn.GetCode() << 16) | rm.GetCode());
12037      return;
12038    }
12039  }
12040  Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
12041}
12042
12043void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
12044  VIXL_ASSERT(AllowAssembler());
12045  CheckIT(cond);
12046  if (IsUsingT32()) {
12047    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12048    EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12049               rm.GetCode());
12050    AdvanceIT();
12051    return;
12052  } else {
12053    // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12054    if (cond.IsNotNever()) {
12055      EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12056              (rn.GetCode() << 16) | rm.GetCode());
12057      return;
12058    }
12059  }
12060  Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
12061}
12062
12063void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
12064  VIXL_ASSERT(AllowAssembler());
12065  CheckIT(cond);
12066  if (IsUsingT32()) {
12067    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12068    EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12069               rm.GetCode());
12070    AdvanceIT();
12071    return;
12072  } else {
12073    // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12074    if (cond.IsNotNever()) {
12075      EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12076              (rn.GetCode() << 16) | rm.GetCode());
12077      return;
12078    }
12079  }
12080  Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
12081}
12082
12083void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
12084  VIXL_ASSERT(AllowAssembler());
12085  CheckIT(cond);
12086  if (IsUsingT32()) {
12087    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12088    EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12089               rm.GetCode());
12090    AdvanceIT();
12091    return;
12092  } else {
12093    // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12094    if (cond.IsNotNever()) {
12095      EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12096              (rn.GetCode() << 16) | rm.GetCode());
12097      return;
12098    }
12099  }
12100  Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
12101}
12102
12103void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
12104  VIXL_ASSERT(AllowAssembler());
12105  CheckIT(cond);
12106  if (IsUsingT32()) {
12107    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12108    EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12109               rm.GetCode());
12110    AdvanceIT();
12111    return;
12112  } else {
12113    // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12114    if (cond.IsNotNever()) {
12115      EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12116              (rn.GetCode() << 16) | rm.GetCode());
12117      return;
12118    }
12119  }
12120  Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
12121}
12122
12123void Assembler::umaal(
12124    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12125  VIXL_ASSERT(AllowAssembler());
12126  CheckIT(cond);
12127  if (IsUsingT32()) {
12128    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12129    EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12130               (rn.GetCode() << 16) | rm.GetCode());
12131    AdvanceIT();
12132    return;
12133  } else {
12134    // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12135    if (cond.IsNotNever()) {
12136      EmitA32(0x00400090U | (cond.GetCondition() << 28) |
12137              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12138              (rm.GetCode() << 8));
12139      return;
12140    }
12141  }
12142  Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
12143}
12144
12145void Assembler::umlal(
12146    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12147  VIXL_ASSERT(AllowAssembler());
12148  CheckIT(cond);
12149  if (IsUsingT32()) {
12150    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12151    EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12152               (rn.GetCode() << 16) | rm.GetCode());
12153    AdvanceIT();
12154    return;
12155  } else {
12156    // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12157    if (cond.IsNotNever()) {
12158      EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
12159              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12160              (rm.GetCode() << 8));
12161      return;
12162    }
12163  }
12164  Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
12165}
12166
12167void Assembler::umlals(
12168    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12169  VIXL_ASSERT(AllowAssembler());
12170  CheckIT(cond);
12171  if (IsUsingA32()) {
12172    // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12173    if (cond.IsNotNever()) {
12174      EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
12175              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12176              (rm.GetCode() << 8));
12177      return;
12178    }
12179  }
12180  Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
12181}
12182
12183void Assembler::umull(
12184    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12185  VIXL_ASSERT(AllowAssembler());
12186  CheckIT(cond);
12187  if (IsUsingT32()) {
12188    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12189    EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12190               (rn.GetCode() << 16) | rm.GetCode());
12191    AdvanceIT();
12192    return;
12193  } else {
12194    // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12195    if (cond.IsNotNever()) {
12196      EmitA32(0x00800090U | (cond.GetCondition() << 28) |
12197              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12198              (rm.GetCode() << 8));
12199      return;
12200    }
12201  }
12202  Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
12203}
12204
12205void Assembler::umulls(
12206    Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
12207  VIXL_ASSERT(AllowAssembler());
12208  CheckIT(cond);
12209  if (IsUsingA32()) {
12210    // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12211    if (cond.IsNotNever()) {
12212      EmitA32(0x00900090U | (cond.GetCondition() << 28) |
12213              (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12214              (rm.GetCode() << 8));
12215      return;
12216    }
12217  }
12218  Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
12219}
12220
12221void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
12222  VIXL_ASSERT(AllowAssembler());
12223  CheckIT(cond);
12224  if (IsUsingT32()) {
12225    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12226    EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12227               rm.GetCode());
12228    AdvanceIT();
12229    return;
12230  } else {
12231    // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12232    if (cond.IsNotNever()) {
12233      EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12234              (rn.GetCode() << 16) | rm.GetCode());
12235      return;
12236    }
12237  }
12238  Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
12239}
12240
12241void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
12242  VIXL_ASSERT(AllowAssembler());
12243  CheckIT(cond);
12244  if (IsUsingT32()) {
12245    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12246    EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12247               rm.GetCode());
12248    AdvanceIT();
12249    return;
12250  } else {
12251    // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12252    if (cond.IsNotNever()) {
12253      EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12254              (rn.GetCode() << 16) | rm.GetCode());
12255      return;
12256    }
12257  }
12258  Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
12259}
12260
12261void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
12262  VIXL_ASSERT(AllowAssembler());
12263  CheckIT(cond);
12264  if (IsUsingT32()) {
12265    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12266    EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12267               rm.GetCode());
12268    AdvanceIT();
12269    return;
12270  } else {
12271    // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12272    if (cond.IsNotNever()) {
12273      EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12274              (rn.GetCode() << 16) | rm.GetCode());
12275      return;
12276    }
12277  }
12278  Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
12279}
12280
12281void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
12282  VIXL_ASSERT(AllowAssembler());
12283  CheckIT(cond);
12284  if (IsUsingT32()) {
12285    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12286    EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12287               rm.GetCode());
12288    AdvanceIT();
12289    return;
12290  } else {
12291    // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12292    if (cond.IsNotNever()) {
12293      EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12294              (rn.GetCode() << 16) | rm.GetCode());
12295      return;
12296    }
12297  }
12298  Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
12299}
12300
12301void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
12302  VIXL_ASSERT(AllowAssembler());
12303  CheckIT(cond);
12304  if (IsUsingT32()) {
12305    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12306    EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12307               rm.GetCode());
12308    AdvanceIT();
12309    return;
12310  } else {
12311    // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12312    if (cond.IsNotNever()) {
12313      EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12314              (rn.GetCode() << 16) | rm.GetCode());
12315      return;
12316    }
12317  }
12318  Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
12319}
12320
12321void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
12322  VIXL_ASSERT(AllowAssembler());
12323  CheckIT(cond);
12324  if (IsUsingT32()) {
12325    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12326    EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12327               rm.GetCode());
12328    AdvanceIT();
12329    return;
12330  } else {
12331    // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12332    if (cond.IsNotNever()) {
12333      EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12334              (rn.GetCode() << 16) | rm.GetCode());
12335      return;
12336    }
12337  }
12338  Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
12339}
12340
12341void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
12342  VIXL_ASSERT(AllowAssembler());
12343  CheckIT(cond);
12344  if (IsUsingT32()) {
12345    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12346    EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12347               rm.GetCode());
12348    AdvanceIT();
12349    return;
12350  } else {
12351    // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12352    if (cond.IsNotNever()) {
12353      EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12354              rn.GetCode() | (rm.GetCode() << 8));
12355      return;
12356    }
12357  }
12358  Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
12359}
12360
12361void Assembler::usada8(
12362    Condition cond, Register rd, Register rn, Register rm, Register ra) {
12363  VIXL_ASSERT(AllowAssembler());
12364  CheckIT(cond);
12365  if (IsUsingT32()) {
12366    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
12367    if (!ra.Is(pc)) {
12368      EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12369                 rm.GetCode() | (ra.GetCode() << 12));
12370      AdvanceIT();
12371      return;
12372    }
12373  } else {
12374    // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
12375    if (cond.IsNotNever() && !ra.Is(pc)) {
12376      EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12377              rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
12378      return;
12379    }
12380  }
12381  Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
12382}
12383
12384void Assembler::usat(Condition cond,
12385                     Register rd,
12386                     uint32_t imm,
12387                     const Operand& operand) {
12388  VIXL_ASSERT(AllowAssembler());
12389  CheckIT(cond);
12390  if (operand.IsImmediateShiftedRegister()) {
12391    Register rn = operand.GetBaseRegister();
12392    Shift shift = operand.GetShift();
12393    uint32_t amount = operand.GetShiftAmount();
12394    if (IsUsingT32()) {
12395      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
12396      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31)) {
12397        EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
12398                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
12399                   ((amount & 0x1c) << 10));
12400        AdvanceIT();
12401        return;
12402      }
12403      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
12404      if ((imm <= 31) && shift.IsLSL() && (amount <= 31)) {
12405        EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
12406                   (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
12407                   ((amount & 0x1c) << 10));
12408        AdvanceIT();
12409        return;
12410      }
12411    } else {
12412      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
12413      if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
12414          cond.IsNotNever()) {
12415        uint32_t amount_ = amount % 32;
12416        EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
12417                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
12418                (amount_ << 7));
12419        return;
12420      }
12421      // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
12422      if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever()) {
12423        EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
12424                (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
12425                (amount << 7));
12426        return;
12427      }
12428    }
12429  }
12430  Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
12431}
12432
12433void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
12434  VIXL_ASSERT(AllowAssembler());
12435  CheckIT(cond);
12436  if (IsUsingT32()) {
12437    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
12438    if ((imm <= 15)) {
12439      EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
12440                 (rn.GetCode() << 16));
12441      AdvanceIT();
12442      return;
12443    }
12444  } else {
12445    // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
12446    if ((imm <= 15) && cond.IsNotNever()) {
12447      EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12448              (imm << 16) | rn.GetCode());
12449      return;
12450    }
12451  }
12452  Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
12453}
12454
12455void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
12456  VIXL_ASSERT(AllowAssembler());
12457  CheckIT(cond);
12458  if (IsUsingT32()) {
12459    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12460    EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12461               rm.GetCode());
12462    AdvanceIT();
12463    return;
12464  } else {
12465    // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12466    if (cond.IsNotNever()) {
12467      EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12468              (rn.GetCode() << 16) | rm.GetCode());
12469      return;
12470    }
12471  }
12472  Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
12473}
12474
12475void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
12476  VIXL_ASSERT(AllowAssembler());
12477  CheckIT(cond);
12478  if (IsUsingT32()) {
12479    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12480    EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12481               rm.GetCode());
12482    AdvanceIT();
12483    return;
12484  } else {
12485    // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12486    if (cond.IsNotNever()) {
12487      EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12488              (rn.GetCode() << 16) | rm.GetCode());
12489      return;
12490    }
12491  }
12492  Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
12493}
12494
12495void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
12496  VIXL_ASSERT(AllowAssembler());
12497  CheckIT(cond);
12498  if (IsUsingT32()) {
12499    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12500    EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12501               rm.GetCode());
12502    AdvanceIT();
12503    return;
12504  } else {
12505    // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12506    if (cond.IsNotNever()) {
12507      EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12508              (rn.GetCode() << 16) | rm.GetCode());
12509      return;
12510    }
12511  }
12512  Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
12513}
12514
12515void Assembler::uxtab(Condition cond,
12516                      Register rd,
12517                      Register rn,
12518                      const Operand& operand) {
12519  VIXL_ASSERT(AllowAssembler());
12520  CheckIT(cond);
12521  if (operand.IsImmediateShiftedRegister()) {
12522    Register rm = operand.GetBaseRegister();
12523    Shift shift = operand.GetShift();
12524    uint32_t amount = operand.GetShiftAmount();
12525    if (IsUsingT32()) {
12526      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12527      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12528          ((amount % 8) == 0) && !rn.Is(pc)) {
12529        uint32_t amount_ = amount / 8;
12530        EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12531                   rm.GetCode() | (amount_ << 4));
12532        AdvanceIT();
12533        return;
12534      }
12535    } else {
12536      // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12537      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12538          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12539        uint32_t amount_ = amount / 8;
12540        EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
12541                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12542                (amount_ << 10));
12543        return;
12544      }
12545    }
12546  }
12547  Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
12548}
12549
12550void Assembler::uxtab16(Condition cond,
12551                        Register rd,
12552                        Register rn,
12553                        const Operand& operand) {
12554  VIXL_ASSERT(AllowAssembler());
12555  CheckIT(cond);
12556  if (operand.IsImmediateShiftedRegister()) {
12557    Register rm = operand.GetBaseRegister();
12558    Shift shift = operand.GetShift();
12559    uint32_t amount = operand.GetShiftAmount();
12560    if (IsUsingT32()) {
12561      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12562      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12563          ((amount % 8) == 0) && !rn.Is(pc)) {
12564        uint32_t amount_ = amount / 8;
12565        EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12566                   rm.GetCode() | (amount_ << 4));
12567        AdvanceIT();
12568        return;
12569      }
12570    } else {
12571      // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12572      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12573          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12574        uint32_t amount_ = amount / 8;
12575        EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
12576                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12577                (amount_ << 10));
12578        return;
12579      }
12580    }
12581  }
12582  Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
12583}
12584
12585void Assembler::uxtah(Condition cond,
12586                      Register rd,
12587                      Register rn,
12588                      const Operand& operand) {
12589  VIXL_ASSERT(AllowAssembler());
12590  CheckIT(cond);
12591  if (operand.IsImmediateShiftedRegister()) {
12592    Register rm = operand.GetBaseRegister();
12593    Shift shift = operand.GetShift();
12594    uint32_t amount = operand.GetShiftAmount();
12595    if (IsUsingT32()) {
12596      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12597      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12598          ((amount % 8) == 0) && !rn.Is(pc)) {
12599        uint32_t amount_ = amount / 8;
12600        EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12601                   rm.GetCode() | (amount_ << 4));
12602        AdvanceIT();
12603        return;
12604      }
12605    } else {
12606      // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12607      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12608          ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12609        uint32_t amount_ = amount / 8;
12610        EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
12611                (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12612                (amount_ << 10));
12613        return;
12614      }
12615    }
12616  }
12617  Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
12618}
12619
12620void Assembler::uxtb(Condition cond,
12621                     EncodingSize size,
12622                     Register rd,
12623                     const Operand& operand) {
12624  VIXL_ASSERT(AllowAssembler());
12625  CheckIT(cond);
12626  if (operand.IsImmediateShiftedRegister()) {
12627    Register rm = operand.GetBaseRegister();
12628    if (operand.IsPlainRegister()) {
12629      if (IsUsingT32()) {
12630        // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12631        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12632          EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
12633          AdvanceIT();
12634          return;
12635        }
12636      }
12637    }
12638    Shift shift = operand.GetShift();
12639    uint32_t amount = operand.GetShiftAmount();
12640    if (IsUsingT32()) {
12641      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12642      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12643          (amount <= 24) && ((amount % 8) == 0)) {
12644        uint32_t amount_ = amount / 8;
12645        EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12646                   (amount_ << 4));
12647        AdvanceIT();
12648        return;
12649      }
12650    } else {
12651      // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12652      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12653          ((amount % 8) == 0) && cond.IsNotNever()) {
12654        uint32_t amount_ = amount / 8;
12655        EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
12656                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12657        return;
12658      }
12659    }
12660  }
12661  Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
12662}
12663
12664void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
12665  VIXL_ASSERT(AllowAssembler());
12666  CheckIT(cond);
12667  if (operand.IsImmediateShiftedRegister()) {
12668    Register rm = operand.GetBaseRegister();
12669    Shift shift = operand.GetShift();
12670    uint32_t amount = operand.GetShiftAmount();
12671    if (IsUsingT32()) {
12672      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12673      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12674          ((amount % 8) == 0)) {
12675        uint32_t amount_ = amount / 8;
12676        EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12677                   (amount_ << 4));
12678        AdvanceIT();
12679        return;
12680      }
12681    } else {
12682      // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12683      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12684          ((amount % 8) == 0) && cond.IsNotNever()) {
12685        uint32_t amount_ = amount / 8;
12686        EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
12687                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12688        return;
12689      }
12690    }
12691  }
12692  Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
12693}
12694
12695void Assembler::uxth(Condition cond,
12696                     EncodingSize size,
12697                     Register rd,
12698                     const Operand& operand) {
12699  VIXL_ASSERT(AllowAssembler());
12700  CheckIT(cond);
12701  if (operand.IsImmediateShiftedRegister()) {
12702    Register rm = operand.GetBaseRegister();
12703    if (operand.IsPlainRegister()) {
12704      if (IsUsingT32()) {
12705        // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12706        if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12707          EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
12708          AdvanceIT();
12709          return;
12710        }
12711      }
12712    }
12713    Shift shift = operand.GetShift();
12714    uint32_t amount = operand.GetShiftAmount();
12715    if (IsUsingT32()) {
12716      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12717      if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12718          (amount <= 24) && ((amount % 8) == 0)) {
12719        uint32_t amount_ = amount / 8;
12720        EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12721                   (amount_ << 4));
12722        AdvanceIT();
12723        return;
12724      }
12725    } else {
12726      // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12727      if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12728          ((amount % 8) == 0) && cond.IsNotNever()) {
12729        uint32_t amount_ = amount / 8;
12730        EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
12731                (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12732        return;
12733      }
12734    }
12735  }
12736  Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
12737}
12738
12739void Assembler::vaba(
12740    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
12741  VIXL_ASSERT(AllowAssembler());
12742  CheckIT(cond);
12743  Dt_U_size_1 encoded_dt(dt);
12744  if (IsUsingT32()) {
12745    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
12746    if (encoded_dt.IsValid()) {
12747      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12748        EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12749                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12750                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12751        AdvanceIT();
12752        return;
12753      }
12754    }
12755  } else {
12756    // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
12757    if (encoded_dt.IsValid()) {
12758      if (cond.Is(al)) {
12759        EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12760                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12761                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12762        return;
12763      }
12764    }
12765  }
12766  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
12767}
12768
12769void Assembler::vaba(
12770    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
12771  VIXL_ASSERT(AllowAssembler());
12772  CheckIT(cond);
12773  Dt_U_size_1 encoded_dt(dt);
12774  if (IsUsingT32()) {
12775    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
12776    if (encoded_dt.IsValid()) {
12777      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12778        EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12779                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12780                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12781        AdvanceIT();
12782        return;
12783      }
12784    }
12785  } else {
12786    // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
12787    if (encoded_dt.IsValid()) {
12788      if (cond.Is(al)) {
12789        EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12790                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12791                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12792        return;
12793      }
12794    }
12795  }
12796  Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
12797}
12798
12799void Assembler::vabal(
12800    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
12801  VIXL_ASSERT(AllowAssembler());
12802  CheckIT(cond);
12803  Dt_U_size_1 encoded_dt(dt);
12804  if (IsUsingT32()) {
12805    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
12806    if (encoded_dt.IsValid()) {
12807      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12808        EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12809                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12810                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12811        AdvanceIT();
12812        return;
12813      }
12814    }
12815  } else {
12816    // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
12817    if (encoded_dt.IsValid()) {
12818      if (cond.Is(al)) {
12819        EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12820                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12821                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12822        return;
12823      }
12824    }
12825  }
12826  Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
12827}
12828
12829void Assembler::vabd(
12830    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
12831  VIXL_ASSERT(AllowAssembler());
12832  CheckIT(cond);
12833  Dt_U_size_1 encoded_dt(dt);
12834  if (IsUsingT32()) {
12835    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
12836    if (dt.Is(F32)) {
12837      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12838        EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12839                   rm.Encode(5, 0));
12840        AdvanceIT();
12841        return;
12842      }
12843    }
12844    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
12845    if (encoded_dt.IsValid()) {
12846      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12847        EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12848                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12849                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12850        AdvanceIT();
12851        return;
12852      }
12853    }
12854  } else {
12855    // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
12856    if (dt.Is(F32)) {
12857      if (cond.Is(al)) {
12858        EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12859                rm.Encode(5, 0));
12860        return;
12861      }
12862    }
12863    // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
12864    if (encoded_dt.IsValid()) {
12865      if (cond.Is(al)) {
12866        EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12867                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12868                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12869        return;
12870      }
12871    }
12872  }
12873  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
12874}
12875
12876void Assembler::vabd(
12877    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
12878  VIXL_ASSERT(AllowAssembler());
12879  CheckIT(cond);
12880  Dt_U_size_1 encoded_dt(dt);
12881  if (IsUsingT32()) {
12882    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
12883    if (dt.Is(F32)) {
12884      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12885        EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12886                   rm.Encode(5, 0));
12887        AdvanceIT();
12888        return;
12889      }
12890    }
12891    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
12892    if (encoded_dt.IsValid()) {
12893      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12894        EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12895                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12896                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12897        AdvanceIT();
12898        return;
12899      }
12900    }
12901  } else {
12902    // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
12903    if (dt.Is(F32)) {
12904      if (cond.Is(al)) {
12905        EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12906                rm.Encode(5, 0));
12907        return;
12908      }
12909    }
12910    // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
12911    if (encoded_dt.IsValid()) {
12912      if (cond.Is(al)) {
12913        EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12914                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12915                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12916        return;
12917      }
12918    }
12919  }
12920  Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
12921}
12922
12923void Assembler::vabdl(
12924    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
12925  VIXL_ASSERT(AllowAssembler());
12926  CheckIT(cond);
12927  Dt_U_size_1 encoded_dt(dt);
12928  if (IsUsingT32()) {
12929    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
12930    if (encoded_dt.IsValid()) {
12931      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12932        EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12933                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12934                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12935        AdvanceIT();
12936        return;
12937      }
12938    }
12939  } else {
12940    // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
12941    if (encoded_dt.IsValid()) {
12942      if (cond.Is(al)) {
12943        EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12944                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12945                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12946        return;
12947      }
12948    }
12949  }
12950  Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
12951}
12952
12953void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
12954  VIXL_ASSERT(AllowAssembler());
12955  CheckIT(cond);
12956  Dt_F_size_1 encoded_dt(dt);
12957  if (IsUsingT32()) {
12958    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
12959    if (encoded_dt.IsValid()) {
12960      if (cond.Is(al) || AllowStronglyDiscouraged()) {
12961        EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
12962                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
12963                   rd.Encode(22, 12) | rm.Encode(5, 0));
12964        AdvanceIT();
12965        return;
12966      }
12967    }
12968    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
12969    if (dt.Is(F64)) {
12970      EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
12971      AdvanceIT();
12972      return;
12973    }
12974  } else {
12975    // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
12976    if (encoded_dt.IsValid()) {
12977      if (cond.Is(al)) {
12978        EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
12979                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
12980                rd.Encode(22, 12) | rm.Encode(5, 0));
12981        return;
12982      }
12983    }
12984    // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
12985    if (dt.Is(F64) && cond.IsNotNever()) {
12986      EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
12987              rm.Encode(5, 0));
12988      return;
12989    }
12990  }
12991  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
12992}
12993
12994void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
12995  VIXL_ASSERT(AllowAssembler());
12996  CheckIT(cond);
12997  Dt_F_size_1 encoded_dt(dt);
12998  if (IsUsingT32()) {
12999    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
13000    if (encoded_dt.IsValid()) {
13001      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13002        EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13003                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13004                   rd.Encode(22, 12) | rm.Encode(5, 0));
13005        AdvanceIT();
13006        return;
13007      }
13008    }
13009  } else {
13010    // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
13011    if (encoded_dt.IsValid()) {
13012      if (cond.Is(al)) {
13013        EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13014                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13015                rd.Encode(22, 12) | rm.Encode(5, 0));
13016        return;
13017      }
13018    }
13019  }
13020  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13021}
13022
13023void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
13024  VIXL_ASSERT(AllowAssembler());
13025  CheckIT(cond);
13026  if (IsUsingT32()) {
13027    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
13028    if (dt.Is(F32)) {
13029      EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
13030      AdvanceIT();
13031      return;
13032    }
13033  } else {
13034    // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
13035    if (dt.Is(F32) && cond.IsNotNever()) {
13036      EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13037              rm.Encode(5, 0));
13038      return;
13039    }
13040  }
13041  Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13042}
13043
13044void Assembler::vacge(
13045    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13046  VIXL_ASSERT(AllowAssembler());
13047  CheckIT(cond);
13048  if (IsUsingT32()) {
13049    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13050    if (dt.Is(F32)) {
13051      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13052        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13053                   rm.Encode(5, 0));
13054        AdvanceIT();
13055        return;
13056      }
13057    }
13058  } else {
13059    // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13060    if (dt.Is(F32)) {
13061      if (cond.Is(al)) {
13062        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13063                rm.Encode(5, 0));
13064        return;
13065      }
13066    }
13067  }
13068  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
13069}
13070
13071void Assembler::vacge(
13072    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13073  VIXL_ASSERT(AllowAssembler());
13074  CheckIT(cond);
13075  if (IsUsingT32()) {
13076    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13077    if (dt.Is(F32)) {
13078      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13079        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13080                   rm.Encode(5, 0));
13081        AdvanceIT();
13082        return;
13083      }
13084    }
13085  } else {
13086    // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13087    if (dt.Is(F32)) {
13088      if (cond.Is(al)) {
13089        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13090                rm.Encode(5, 0));
13091        return;
13092      }
13093    }
13094  }
13095  Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
13096}
13097
13098void Assembler::vacgt(
13099    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13100  VIXL_ASSERT(AllowAssembler());
13101  CheckIT(cond);
13102  if (IsUsingT32()) {
13103    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13104    if (dt.Is(F32)) {
13105      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13106        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13107                   rm.Encode(5, 0));
13108        AdvanceIT();
13109        return;
13110      }
13111    }
13112  } else {
13113    // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13114    if (dt.Is(F32)) {
13115      if (cond.Is(al)) {
13116        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13117                rm.Encode(5, 0));
13118        return;
13119      }
13120    }
13121  }
13122  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
13123}
13124
13125void Assembler::vacgt(
13126    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13127  VIXL_ASSERT(AllowAssembler());
13128  CheckIT(cond);
13129  if (IsUsingT32()) {
13130    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13131    if (dt.Is(F32)) {
13132      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13133        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13134                   rm.Encode(5, 0));
13135        AdvanceIT();
13136        return;
13137      }
13138    }
13139  } else {
13140    // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13141    if (dt.Is(F32)) {
13142      if (cond.Is(al)) {
13143        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13144                rm.Encode(5, 0));
13145        return;
13146      }
13147    }
13148  }
13149  Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
13150}
13151
13152void Assembler::vacle(
13153    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13154  VIXL_ASSERT(AllowAssembler());
13155  CheckIT(cond);
13156  if (IsUsingT32()) {
13157    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13158    if (dt.Is(F32)) {
13159      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13160        EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13161                   rm.Encode(5, 0));
13162        AdvanceIT();
13163        return;
13164      }
13165    }
13166  } else {
13167    // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13168    if (dt.Is(F32)) {
13169      if (cond.Is(al)) {
13170        EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13171                rm.Encode(5, 0));
13172        return;
13173      }
13174    }
13175  }
13176  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
13177}
13178
13179void Assembler::vacle(
13180    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13181  VIXL_ASSERT(AllowAssembler());
13182  CheckIT(cond);
13183  if (IsUsingT32()) {
13184    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13185    if (dt.Is(F32)) {
13186      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13187        EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13188                   rm.Encode(5, 0));
13189        AdvanceIT();
13190        return;
13191      }
13192    }
13193  } else {
13194    // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13195    if (dt.Is(F32)) {
13196      if (cond.Is(al)) {
13197        EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13198                rm.Encode(5, 0));
13199        return;
13200      }
13201    }
13202  }
13203  Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
13204}
13205
13206void Assembler::vaclt(
13207    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13208  VIXL_ASSERT(AllowAssembler());
13209  CheckIT(cond);
13210  if (IsUsingT32()) {
13211    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13212    if (dt.Is(F32)) {
13213      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13214        EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13215                   rm.Encode(5, 0));
13216        AdvanceIT();
13217        return;
13218      }
13219    }
13220  } else {
13221    // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13222    if (dt.Is(F32)) {
13223      if (cond.Is(al)) {
13224        EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13225                rm.Encode(5, 0));
13226        return;
13227      }
13228    }
13229  }
13230  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
13231}
13232
13233void Assembler::vaclt(
13234    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13235  VIXL_ASSERT(AllowAssembler());
13236  CheckIT(cond);
13237  if (IsUsingT32()) {
13238    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13239    if (dt.Is(F32)) {
13240      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13241        EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13242                   rm.Encode(5, 0));
13243        AdvanceIT();
13244        return;
13245      }
13246    }
13247  } else {
13248    // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13249    if (dt.Is(F32)) {
13250      if (cond.Is(al)) {
13251        EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13252                rm.Encode(5, 0));
13253        return;
13254      }
13255    }
13256  }
13257  Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
13258}
13259
13260void Assembler::vadd(
13261    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13262  VIXL_ASSERT(AllowAssembler());
13263  CheckIT(cond);
13264  Dt_size_2 encoded_dt(dt);
13265  if (IsUsingT32()) {
13266    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13267    if (dt.Is(F32)) {
13268      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13269        EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13270                   rm.Encode(5, 0));
13271        AdvanceIT();
13272        return;
13273      }
13274    }
13275    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
13276    if (dt.Is(F64)) {
13277      EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13278                 rm.Encode(5, 0));
13279      AdvanceIT();
13280      return;
13281    }
13282    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13283    if (encoded_dt.IsValid()) {
13284      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13285        EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
13286                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13287        AdvanceIT();
13288        return;
13289      }
13290    }
13291  } else {
13292    // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13293    if (dt.Is(F32)) {
13294      if (cond.Is(al)) {
13295        EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13296                rm.Encode(5, 0));
13297        return;
13298      }
13299    }
13300    // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
13301    if (dt.Is(F64) && cond.IsNotNever()) {
13302      EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13303              rn.Encode(7, 16) | rm.Encode(5, 0));
13304      return;
13305    }
13306    // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13307    if (encoded_dt.IsValid()) {
13308      if (cond.Is(al)) {
13309        EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
13310                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13311        return;
13312      }
13313    }
13314  }
13315  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13316}
13317
13318void Assembler::vadd(
13319    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13320  VIXL_ASSERT(AllowAssembler());
13321  CheckIT(cond);
13322  Dt_size_2 encoded_dt(dt);
13323  if (IsUsingT32()) {
13324    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13325    if (dt.Is(F32)) {
13326      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13327        EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13328                   rm.Encode(5, 0));
13329        AdvanceIT();
13330        return;
13331      }
13332    }
13333    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
13334    if (encoded_dt.IsValid()) {
13335      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13336        EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
13337                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13338        AdvanceIT();
13339        return;
13340      }
13341    }
13342  } else {
13343    // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13344    if (dt.Is(F32)) {
13345      if (cond.Is(al)) {
13346        EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13347                rm.Encode(5, 0));
13348        return;
13349      }
13350    }
13351    // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
13352    if (encoded_dt.IsValid()) {
13353      if (cond.Is(al)) {
13354        EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
13355                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13356        return;
13357      }
13358    }
13359  }
13360  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13361}
13362
13363void Assembler::vadd(
13364    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
13365  VIXL_ASSERT(AllowAssembler());
13366  CheckIT(cond);
13367  if (IsUsingT32()) {
13368    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
13369    if (dt.Is(F32)) {
13370      EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13371                 rm.Encode(5, 0));
13372      AdvanceIT();
13373      return;
13374    }
13375  } else {
13376    // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
13377    if (dt.Is(F32) && cond.IsNotNever()) {
13378      EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13379              rn.Encode(7, 16) | rm.Encode(5, 0));
13380      return;
13381    }
13382  }
13383  Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13384}
13385
13386void Assembler::vaddhn(
13387    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
13388  VIXL_ASSERT(AllowAssembler());
13389  CheckIT(cond);
13390  Dt_size_3 encoded_dt(dt);
13391  if (IsUsingT32()) {
13392    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
13393    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
13394      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13395        EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
13396                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13397        AdvanceIT();
13398        return;
13399      }
13400    }
13401  } else {
13402    // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
13403    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
13404      if (cond.Is(al)) {
13405        EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
13406                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13407        return;
13408      }
13409    }
13410  }
13411  Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
13412}
13413
13414void Assembler::vaddl(
13415    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
13416  VIXL_ASSERT(AllowAssembler());
13417  CheckIT(cond);
13418  Dt_U_size_1 encoded_dt(dt);
13419  if (IsUsingT32()) {
13420    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13421    if (encoded_dt.IsValid()) {
13422      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13423        EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13424                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13425                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13426        AdvanceIT();
13427        return;
13428      }
13429    }
13430  } else {
13431    // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13432    if (encoded_dt.IsValid()) {
13433      if (cond.Is(al)) {
13434        EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13435                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13436                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13437        return;
13438      }
13439    }
13440  }
13441  Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
13442}
13443
13444void Assembler::vaddw(
13445    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
13446  VIXL_ASSERT(AllowAssembler());
13447  CheckIT(cond);
13448  Dt_U_size_1 encoded_dt(dt);
13449  if (IsUsingT32()) {
13450    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
13451    if (encoded_dt.IsValid()) {
13452      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13453        EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13454                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13455                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13456        AdvanceIT();
13457        return;
13458      }
13459    }
13460  } else {
13461    // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
13462    if (encoded_dt.IsValid()) {
13463      if (cond.Is(al)) {
13464        EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13465                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13466                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13467        return;
13468      }
13469    }
13470  }
13471  Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
13472}
13473
13474void Assembler::vand(Condition cond,
13475                     DataType dt,
13476                     DRegister rd,
13477                     DRegister rn,
13478                     const DOperand& operand) {
13479  VIXL_ASSERT(AllowAssembler());
13480  CheckIT(cond);
13481  if (operand.IsImmediate()) {
13482    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
13483    if (IsUsingT32()) {
13484      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
13485      if (encoded_dt.IsValid() && rd.Is(rn)) {
13486        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13487          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
13488                     rd.Encode(22, 12) |
13489                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13490                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13491                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13492          AdvanceIT();
13493          return;
13494        }
13495      }
13496    } else {
13497      // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
13498      if (encoded_dt.IsValid() && rd.Is(rn)) {
13499        if (cond.Is(al)) {
13500          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
13501                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13502                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13503                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13504          return;
13505        }
13506      }
13507    }
13508  }
13509  if (operand.IsRegister()) {
13510    DRegister rm = operand.GetRegister();
13511    USE(dt);
13512    if (IsUsingT32()) {
13513      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13514      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13515        EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13516                   rm.Encode(5, 0));
13517        AdvanceIT();
13518        return;
13519      }
13520    } else {
13521      // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13522      if (cond.Is(al)) {
13523        EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13524                rm.Encode(5, 0));
13525        return;
13526      }
13527    }
13528  }
13529  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
13530}
13531
13532void Assembler::vand(Condition cond,
13533                     DataType dt,
13534                     QRegister rd,
13535                     QRegister rn,
13536                     const QOperand& operand) {
13537  VIXL_ASSERT(AllowAssembler());
13538  CheckIT(cond);
13539  if (operand.IsImmediate()) {
13540    ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
13541    if (IsUsingT32()) {
13542      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
13543      if (encoded_dt.IsValid() && rd.Is(rn)) {
13544        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13545          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
13546                     rd.Encode(22, 12) |
13547                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13548                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13549                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13550          AdvanceIT();
13551          return;
13552        }
13553      }
13554    } else {
13555      // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
13556      if (encoded_dt.IsValid() && rd.Is(rn)) {
13557        if (cond.Is(al)) {
13558          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
13559                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13560                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13561                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13562          return;
13563        }
13564      }
13565    }
13566  }
13567  if (operand.IsRegister()) {
13568    QRegister rm = operand.GetRegister();
13569    USE(dt);
13570    if (IsUsingT32()) {
13571      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13572      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13573        EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13574                   rm.Encode(5, 0));
13575        AdvanceIT();
13576        return;
13577      }
13578    } else {
13579      // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13580      if (cond.Is(al)) {
13581        EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13582                rm.Encode(5, 0));
13583        return;
13584      }
13585    }
13586  }
13587  Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
13588}
13589
13590void Assembler::vbic(Condition cond,
13591                     DataType dt,
13592                     DRegister rd,
13593                     DRegister rn,
13594                     const DOperand& operand) {
13595  VIXL_ASSERT(AllowAssembler());
13596  CheckIT(cond);
13597  if (operand.IsImmediate()) {
13598    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
13599    if (IsUsingT32()) {
13600      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
13601      if (encoded_dt.IsValid() && rd.Is(rn)) {
13602        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13603          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
13604                     rd.Encode(22, 12) |
13605                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13606                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13607                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13608          AdvanceIT();
13609          return;
13610        }
13611      }
13612    } else {
13613      // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
13614      if (encoded_dt.IsValid() && rd.Is(rn)) {
13615        if (cond.Is(al)) {
13616          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
13617                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13618                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13619                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13620          return;
13621        }
13622      }
13623    }
13624  }
13625  if (operand.IsRegister()) {
13626    DRegister rm = operand.GetRegister();
13627    USE(dt);
13628    if (IsUsingT32()) {
13629      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13630      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13631        EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13632                   rm.Encode(5, 0));
13633        AdvanceIT();
13634        return;
13635      }
13636    } else {
13637      // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13638      if (cond.Is(al)) {
13639        EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13640                rm.Encode(5, 0));
13641        return;
13642      }
13643    }
13644  }
13645  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
13646}
13647
13648void Assembler::vbic(Condition cond,
13649                     DataType dt,
13650                     QRegister rd,
13651                     QRegister rn,
13652                     const QOperand& operand) {
13653  VIXL_ASSERT(AllowAssembler());
13654  CheckIT(cond);
13655  if (operand.IsImmediate()) {
13656    ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
13657    if (IsUsingT32()) {
13658      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
13659      if (encoded_dt.IsValid() && rd.Is(rn)) {
13660        if (cond.Is(al) || AllowStronglyDiscouraged()) {
13661          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
13662                     rd.Encode(22, 12) |
13663                     (encoded_dt.GetEncodedImmediate() & 0xf) |
13664                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13665                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13666          AdvanceIT();
13667          return;
13668        }
13669      }
13670    } else {
13671      // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
13672      if (encoded_dt.IsValid() && rd.Is(rn)) {
13673        if (cond.Is(al)) {
13674          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
13675                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13676                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13677                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13678          return;
13679        }
13680      }
13681    }
13682  }
13683  if (operand.IsRegister()) {
13684    QRegister rm = operand.GetRegister();
13685    USE(dt);
13686    if (IsUsingT32()) {
13687      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13688      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13689        EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13690                   rm.Encode(5, 0));
13691        AdvanceIT();
13692        return;
13693      }
13694    } else {
13695      // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13696      if (cond.Is(al)) {
13697        EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13698                rm.Encode(5, 0));
13699        return;
13700      }
13701    }
13702  }
13703  Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
13704}
13705
13706void Assembler::vbif(
13707    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13708  VIXL_ASSERT(AllowAssembler());
13709  CheckIT(cond);
13710  USE(dt);
13711  if (IsUsingT32()) {
13712    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13713    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13714      EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13715                 rm.Encode(5, 0));
13716      AdvanceIT();
13717      return;
13718    }
13719  } else {
13720    // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13721    if (cond.Is(al)) {
13722      EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13723              rm.Encode(5, 0));
13724      return;
13725    }
13726  }
13727  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
13728}
13729
13730void Assembler::vbif(
13731    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13732  VIXL_ASSERT(AllowAssembler());
13733  CheckIT(cond);
13734  USE(dt);
13735  if (IsUsingT32()) {
13736    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13737    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13738      EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13739                 rm.Encode(5, 0));
13740      AdvanceIT();
13741      return;
13742    }
13743  } else {
13744    // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13745    if (cond.Is(al)) {
13746      EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13747              rm.Encode(5, 0));
13748      return;
13749    }
13750  }
13751  Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
13752}
13753
13754void Assembler::vbit(
13755    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13756  VIXL_ASSERT(AllowAssembler());
13757  CheckIT(cond);
13758  USE(dt);
13759  if (IsUsingT32()) {
13760    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13761    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13762      EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13763                 rm.Encode(5, 0));
13764      AdvanceIT();
13765      return;
13766    }
13767  } else {
13768    // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13769    if (cond.Is(al)) {
13770      EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13771              rm.Encode(5, 0));
13772      return;
13773    }
13774  }
13775  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
13776}
13777
13778void Assembler::vbit(
13779    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13780  VIXL_ASSERT(AllowAssembler());
13781  CheckIT(cond);
13782  USE(dt);
13783  if (IsUsingT32()) {
13784    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13785    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13786      EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13787                 rm.Encode(5, 0));
13788      AdvanceIT();
13789      return;
13790    }
13791  } else {
13792    // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13793    if (cond.Is(al)) {
13794      EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13795              rm.Encode(5, 0));
13796      return;
13797    }
13798  }
13799  Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
13800}
13801
13802void Assembler::vbsl(
13803    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13804  VIXL_ASSERT(AllowAssembler());
13805  CheckIT(cond);
13806  USE(dt);
13807  if (IsUsingT32()) {
13808    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13809    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13810      EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13811                 rm.Encode(5, 0));
13812      AdvanceIT();
13813      return;
13814    }
13815  } else {
13816    // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13817    if (cond.Is(al)) {
13818      EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13819              rm.Encode(5, 0));
13820      return;
13821    }
13822  }
13823  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
13824}
13825
13826void Assembler::vbsl(
13827    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13828  VIXL_ASSERT(AllowAssembler());
13829  CheckIT(cond);
13830  USE(dt);
13831  if (IsUsingT32()) {
13832    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13833    if (cond.Is(al) || AllowStronglyDiscouraged()) {
13834      EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13835                 rm.Encode(5, 0));
13836      AdvanceIT();
13837      return;
13838    }
13839  } else {
13840    // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13841    if (cond.Is(al)) {
13842      EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13843              rm.Encode(5, 0));
13844      return;
13845    }
13846  }
13847  Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
13848}
13849
13850void Assembler::vceq(Condition cond,
13851                     DataType dt,
13852                     DRegister rd,
13853                     DRegister rm,
13854                     const DOperand& operand) {
13855  VIXL_ASSERT(AllowAssembler());
13856  CheckIT(cond);
13857  if (operand.IsImmediate()) {
13858    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
13859      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
13860      Dt_F_size_2 encoded_dt(dt);
13861      if (IsUsingT32()) {
13862        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
13863        if (encoded_dt.IsValid() && (imm == 0)) {
13864          if (cond.Is(al) || AllowStronglyDiscouraged()) {
13865            EmitT32_32(0xffb10100U |
13866                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13867                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13868                       rd.Encode(22, 12) | rm.Encode(5, 0));
13869            AdvanceIT();
13870            return;
13871          }
13872        }
13873      } else {
13874        // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
13875        if (encoded_dt.IsValid() && (imm == 0)) {
13876          if (cond.Is(al)) {
13877            EmitA32(0xf3b10100U |
13878                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13879                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13880                    rd.Encode(22, 12) | rm.Encode(5, 0));
13881            return;
13882          }
13883        }
13884      }
13885    }
13886  }
13887  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
13888}
13889
13890void Assembler::vceq(Condition cond,
13891                     DataType dt,
13892                     QRegister rd,
13893                     QRegister rm,
13894                     const QOperand& operand) {
13895  VIXL_ASSERT(AllowAssembler());
13896  CheckIT(cond);
13897  if (operand.IsImmediate()) {
13898    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
13899      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
13900      Dt_F_size_2 encoded_dt(dt);
13901      if (IsUsingT32()) {
13902        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
13903        if (encoded_dt.IsValid() && (imm == 0)) {
13904          if (cond.Is(al) || AllowStronglyDiscouraged()) {
13905            EmitT32_32(0xffb10140U |
13906                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13907                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13908                       rd.Encode(22, 12) | rm.Encode(5, 0));
13909            AdvanceIT();
13910            return;
13911          }
13912        }
13913      } else {
13914        // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
13915        if (encoded_dt.IsValid() && (imm == 0)) {
13916          if (cond.Is(al)) {
13917            EmitA32(0xf3b10140U |
13918                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13919                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13920                    rd.Encode(22, 12) | rm.Encode(5, 0));
13921            return;
13922          }
13923        }
13924      }
13925    }
13926  }
13927  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
13928}
13929
13930void Assembler::vceq(
13931    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
13932  VIXL_ASSERT(AllowAssembler());
13933  CheckIT(cond);
13934  Dt_size_4 encoded_dt(dt);
13935  Dt_sz_1 encoded_dt_2(dt);
13936  if (IsUsingT32()) {
13937    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13938    if (encoded_dt.IsValid()) {
13939      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13940        EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
13941                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13942        AdvanceIT();
13943        return;
13944      }
13945    }
13946    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
13947    if (encoded_dt_2.IsValid()) {
13948      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13949        EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
13950                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13951        AdvanceIT();
13952        return;
13953      }
13954    }
13955  } else {
13956    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13957    if (encoded_dt.IsValid()) {
13958      if (cond.Is(al)) {
13959        EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
13960                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13961        return;
13962      }
13963    }
13964    // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
13965    if (encoded_dt_2.IsValid()) {
13966      if (cond.Is(al)) {
13967        EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
13968                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13969        return;
13970      }
13971    }
13972  }
13973  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
13974}
13975
13976void Assembler::vceq(
13977    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
13978  VIXL_ASSERT(AllowAssembler());
13979  CheckIT(cond);
13980  Dt_size_4 encoded_dt(dt);
13981  Dt_sz_1 encoded_dt_2(dt);
13982  if (IsUsingT32()) {
13983    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
13984    if (encoded_dt.IsValid()) {
13985      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13986        EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
13987                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13988        AdvanceIT();
13989        return;
13990      }
13991    }
13992    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
13993    if (encoded_dt_2.IsValid()) {
13994      if (cond.Is(al) || AllowStronglyDiscouraged()) {
13995        EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
13996                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13997        AdvanceIT();
13998        return;
13999      }
14000    }
14001  } else {
14002    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14003    if (encoded_dt.IsValid()) {
14004      if (cond.Is(al)) {
14005        EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
14006                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14007        return;
14008      }
14009    }
14010    // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
14011    if (encoded_dt_2.IsValid()) {
14012      if (cond.Is(al)) {
14013        EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
14014                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14015        return;
14016      }
14017    }
14018  }
14019  Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
14020}
14021
14022void Assembler::vcge(Condition cond,
14023                     DataType dt,
14024                     DRegister rd,
14025                     DRegister rm,
14026                     const DOperand& operand) {
14027  VIXL_ASSERT(AllowAssembler());
14028  CheckIT(cond);
14029  if (operand.IsImmediate()) {
14030    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14031      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14032      Dt_F_size_1 encoded_dt(dt);
14033      if (IsUsingT32()) {
14034        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14035        if (encoded_dt.IsValid() && (imm == 0)) {
14036          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14037            EmitT32_32(0xffb10080U |
14038                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14039                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14040                       rd.Encode(22, 12) | rm.Encode(5, 0));
14041            AdvanceIT();
14042            return;
14043          }
14044        }
14045      } else {
14046        // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14047        if (encoded_dt.IsValid() && (imm == 0)) {
14048          if (cond.Is(al)) {
14049            EmitA32(0xf3b10080U |
14050                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14051                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14052                    rd.Encode(22, 12) | rm.Encode(5, 0));
14053            return;
14054          }
14055        }
14056      }
14057    }
14058  }
14059  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
14060}
14061
14062void Assembler::vcge(Condition cond,
14063                     DataType dt,
14064                     QRegister rd,
14065                     QRegister rm,
14066                     const QOperand& operand) {
14067  VIXL_ASSERT(AllowAssembler());
14068  CheckIT(cond);
14069  if (operand.IsImmediate()) {
14070    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14071      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14072      Dt_F_size_1 encoded_dt(dt);
14073      if (IsUsingT32()) {
14074        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14075        if (encoded_dt.IsValid() && (imm == 0)) {
14076          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14077            EmitT32_32(0xffb100c0U |
14078                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14079                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14080                       rd.Encode(22, 12) | rm.Encode(5, 0));
14081            AdvanceIT();
14082            return;
14083          }
14084        }
14085      } else {
14086        // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14087        if (encoded_dt.IsValid() && (imm == 0)) {
14088          if (cond.Is(al)) {
14089            EmitA32(0xf3b100c0U |
14090                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14091                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14092                    rd.Encode(22, 12) | rm.Encode(5, 0));
14093            return;
14094          }
14095        }
14096      }
14097    }
14098  }
14099  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
14100}
14101
14102void Assembler::vcge(
14103    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14104  VIXL_ASSERT(AllowAssembler());
14105  CheckIT(cond);
14106  Dt_U_size_1 encoded_dt(dt);
14107  if (IsUsingT32()) {
14108    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14109    if (encoded_dt.IsValid()) {
14110      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14111        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14112                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14113                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14114        AdvanceIT();
14115        return;
14116      }
14117    }
14118    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14119    if (dt.Is(F32)) {
14120      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14121        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14122                   rm.Encode(5, 0));
14123        AdvanceIT();
14124        return;
14125      }
14126    }
14127  } else {
14128    // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14129    if (encoded_dt.IsValid()) {
14130      if (cond.Is(al)) {
14131        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14132                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14133                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14134        return;
14135      }
14136    }
14137    // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14138    if (dt.Is(F32)) {
14139      if (cond.Is(al)) {
14140        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14141                rm.Encode(5, 0));
14142        return;
14143      }
14144    }
14145  }
14146  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
14147}
14148
14149void Assembler::vcge(
14150    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14151  VIXL_ASSERT(AllowAssembler());
14152  CheckIT(cond);
14153  Dt_U_size_1 encoded_dt(dt);
14154  if (IsUsingT32()) {
14155    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14156    if (encoded_dt.IsValid()) {
14157      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14158        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14159                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14160                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14161        AdvanceIT();
14162        return;
14163      }
14164    }
14165    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14166    if (dt.Is(F32)) {
14167      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14168        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14169                   rm.Encode(5, 0));
14170        AdvanceIT();
14171        return;
14172      }
14173    }
14174  } else {
14175    // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14176    if (encoded_dt.IsValid()) {
14177      if (cond.Is(al)) {
14178        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14179                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14180                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14181        return;
14182      }
14183    }
14184    // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14185    if (dt.Is(F32)) {
14186      if (cond.Is(al)) {
14187        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14188                rm.Encode(5, 0));
14189        return;
14190      }
14191    }
14192  }
14193  Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
14194}
14195
14196void Assembler::vcgt(Condition cond,
14197                     DataType dt,
14198                     DRegister rd,
14199                     DRegister rm,
14200                     const DOperand& operand) {
14201  VIXL_ASSERT(AllowAssembler());
14202  CheckIT(cond);
14203  if (operand.IsImmediate()) {
14204    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14205      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14206      Dt_F_size_1 encoded_dt(dt);
14207      if (IsUsingT32()) {
14208        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14209        if (encoded_dt.IsValid() && (imm == 0)) {
14210          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14211            EmitT32_32(0xffb10000U |
14212                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14213                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14214                       rd.Encode(22, 12) | rm.Encode(5, 0));
14215            AdvanceIT();
14216            return;
14217          }
14218        }
14219      } else {
14220        // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14221        if (encoded_dt.IsValid() && (imm == 0)) {
14222          if (cond.Is(al)) {
14223            EmitA32(0xf3b10000U |
14224                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14225                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14226                    rd.Encode(22, 12) | rm.Encode(5, 0));
14227            return;
14228          }
14229        }
14230      }
14231    }
14232  }
14233  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
14234}
14235
14236void Assembler::vcgt(Condition cond,
14237                     DataType dt,
14238                     QRegister rd,
14239                     QRegister rm,
14240                     const QOperand& operand) {
14241  VIXL_ASSERT(AllowAssembler());
14242  CheckIT(cond);
14243  if (operand.IsImmediate()) {
14244    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14245      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14246      Dt_F_size_1 encoded_dt(dt);
14247      if (IsUsingT32()) {
14248        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14249        if (encoded_dt.IsValid() && (imm == 0)) {
14250          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14251            EmitT32_32(0xffb10040U |
14252                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14253                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14254                       rd.Encode(22, 12) | rm.Encode(5, 0));
14255            AdvanceIT();
14256            return;
14257          }
14258        }
14259      } else {
14260        // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14261        if (encoded_dt.IsValid() && (imm == 0)) {
14262          if (cond.Is(al)) {
14263            EmitA32(0xf3b10040U |
14264                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14265                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14266                    rd.Encode(22, 12) | rm.Encode(5, 0));
14267            return;
14268          }
14269        }
14270      }
14271    }
14272  }
14273  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
14274}
14275
14276void Assembler::vcgt(
14277    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14278  VIXL_ASSERT(AllowAssembler());
14279  CheckIT(cond);
14280  Dt_U_size_1 encoded_dt(dt);
14281  if (IsUsingT32()) {
14282    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14283    if (encoded_dt.IsValid()) {
14284      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14285        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14286                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14287                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14288        AdvanceIT();
14289        return;
14290      }
14291    }
14292    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14293    if (dt.Is(F32)) {
14294      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14295        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14296                   rm.Encode(5, 0));
14297        AdvanceIT();
14298        return;
14299      }
14300    }
14301  } else {
14302    // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14303    if (encoded_dt.IsValid()) {
14304      if (cond.Is(al)) {
14305        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14306                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14307                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14308        return;
14309      }
14310    }
14311    // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14312    if (dt.Is(F32)) {
14313      if (cond.Is(al)) {
14314        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14315                rm.Encode(5, 0));
14316        return;
14317      }
14318    }
14319  }
14320  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
14321}
14322
14323void Assembler::vcgt(
14324    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14325  VIXL_ASSERT(AllowAssembler());
14326  CheckIT(cond);
14327  Dt_U_size_1 encoded_dt(dt);
14328  if (IsUsingT32()) {
14329    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14330    if (encoded_dt.IsValid()) {
14331      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14332        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14333                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14334                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14335        AdvanceIT();
14336        return;
14337      }
14338    }
14339    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14340    if (dt.Is(F32)) {
14341      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14342        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14343                   rm.Encode(5, 0));
14344        AdvanceIT();
14345        return;
14346      }
14347    }
14348  } else {
14349    // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14350    if (encoded_dt.IsValid()) {
14351      if (cond.Is(al)) {
14352        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14353                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14354                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14355        return;
14356      }
14357    }
14358    // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14359    if (dt.Is(F32)) {
14360      if (cond.Is(al)) {
14361        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14362                rm.Encode(5, 0));
14363        return;
14364      }
14365    }
14366  }
14367  Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
14368}
14369
14370void Assembler::vcle(Condition cond,
14371                     DataType dt,
14372                     DRegister rd,
14373                     DRegister rm,
14374                     const DOperand& operand) {
14375  VIXL_ASSERT(AllowAssembler());
14376  CheckIT(cond);
14377  if (operand.IsImmediate()) {
14378    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14379      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14380      Dt_F_size_1 encoded_dt(dt);
14381      if (IsUsingT32()) {
14382        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14383        if (encoded_dt.IsValid() && (imm == 0)) {
14384          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14385            EmitT32_32(0xffb10180U |
14386                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14387                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14388                       rd.Encode(22, 12) | rm.Encode(5, 0));
14389            AdvanceIT();
14390            return;
14391          }
14392        }
14393      } else {
14394        // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14395        if (encoded_dt.IsValid() && (imm == 0)) {
14396          if (cond.Is(al)) {
14397            EmitA32(0xf3b10180U |
14398                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14399                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14400                    rd.Encode(22, 12) | rm.Encode(5, 0));
14401            return;
14402          }
14403        }
14404      }
14405    }
14406  }
14407  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
14408}
14409
14410void Assembler::vcle(Condition cond,
14411                     DataType dt,
14412                     QRegister rd,
14413                     QRegister rm,
14414                     const QOperand& operand) {
14415  VIXL_ASSERT(AllowAssembler());
14416  CheckIT(cond);
14417  if (operand.IsImmediate()) {
14418    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14419      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14420      Dt_F_size_1 encoded_dt(dt);
14421      if (IsUsingT32()) {
14422        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14423        if (encoded_dt.IsValid() && (imm == 0)) {
14424          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14425            EmitT32_32(0xffb101c0U |
14426                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14427                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14428                       rd.Encode(22, 12) | rm.Encode(5, 0));
14429            AdvanceIT();
14430            return;
14431          }
14432        }
14433      } else {
14434        // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14435        if (encoded_dt.IsValid() && (imm == 0)) {
14436          if (cond.Is(al)) {
14437            EmitA32(0xf3b101c0U |
14438                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14439                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14440                    rd.Encode(22, 12) | rm.Encode(5, 0));
14441            return;
14442          }
14443        }
14444      }
14445    }
14446  }
14447  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
14448}
14449
14450void Assembler::vcle(
14451    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14452  VIXL_ASSERT(AllowAssembler());
14453  CheckIT(cond);
14454  Dt_U_size_1 encoded_dt(dt);
14455  if (IsUsingT32()) {
14456    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14457    if (encoded_dt.IsValid()) {
14458      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14459        EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14460                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14461                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14462        AdvanceIT();
14463        return;
14464      }
14465    }
14466    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14467    if (dt.Is(F32)) {
14468      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14469        EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14470                   rm.Encode(7, 16));
14471        AdvanceIT();
14472        return;
14473      }
14474    }
14475  } else {
14476    // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14477    if (encoded_dt.IsValid()) {
14478      if (cond.Is(al)) {
14479        EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14480                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14481                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14482        return;
14483      }
14484    }
14485    // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14486    if (dt.Is(F32)) {
14487      if (cond.Is(al)) {
14488        EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14489                rm.Encode(7, 16));
14490        return;
14491      }
14492    }
14493  }
14494  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
14495}
14496
14497void Assembler::vcle(
14498    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14499  VIXL_ASSERT(AllowAssembler());
14500  CheckIT(cond);
14501  Dt_U_size_1 encoded_dt(dt);
14502  if (IsUsingT32()) {
14503    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14504    if (encoded_dt.IsValid()) {
14505      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14506        EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14507                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14508                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14509        AdvanceIT();
14510        return;
14511      }
14512    }
14513    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14514    if (dt.Is(F32)) {
14515      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14516        EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14517                   rm.Encode(7, 16));
14518        AdvanceIT();
14519        return;
14520      }
14521    }
14522  } else {
14523    // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14524    if (encoded_dt.IsValid()) {
14525      if (cond.Is(al)) {
14526        EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14527                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14528                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14529        return;
14530      }
14531    }
14532    // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14533    if (dt.Is(F32)) {
14534      if (cond.Is(al)) {
14535        EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14536                rm.Encode(7, 16));
14537        return;
14538      }
14539    }
14540  }
14541  Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
14542}
14543
14544void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14545  VIXL_ASSERT(AllowAssembler());
14546  CheckIT(cond);
14547  Dt_size_5 encoded_dt(dt);
14548  if (IsUsingT32()) {
14549    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14550    if (encoded_dt.IsValid()) {
14551      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14552        EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
14553                   rd.Encode(22, 12) | rm.Encode(5, 0));
14554        AdvanceIT();
14555        return;
14556      }
14557    }
14558  } else {
14559    // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14560    if (encoded_dt.IsValid()) {
14561      if (cond.Is(al)) {
14562        EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
14563                rd.Encode(22, 12) | rm.Encode(5, 0));
14564        return;
14565      }
14566    }
14567  }
14568  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
14569}
14570
14571void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
14572  VIXL_ASSERT(AllowAssembler());
14573  CheckIT(cond);
14574  Dt_size_5 encoded_dt(dt);
14575  if (IsUsingT32()) {
14576    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14577    if (encoded_dt.IsValid()) {
14578      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14579        EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
14580                   rd.Encode(22, 12) | rm.Encode(5, 0));
14581        AdvanceIT();
14582        return;
14583      }
14584    }
14585  } else {
14586    // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14587    if (encoded_dt.IsValid()) {
14588      if (cond.Is(al)) {
14589        EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
14590                rd.Encode(22, 12) | rm.Encode(5, 0));
14591        return;
14592      }
14593    }
14594  }
14595  Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
14596}
14597
14598void Assembler::vclt(Condition cond,
14599                     DataType dt,
14600                     DRegister rd,
14601                     DRegister rm,
14602                     const DOperand& operand) {
14603  VIXL_ASSERT(AllowAssembler());
14604  CheckIT(cond);
14605  if (operand.IsImmediate()) {
14606    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14607      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14608      Dt_F_size_1 encoded_dt(dt);
14609      if (IsUsingT32()) {
14610        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14611        if (encoded_dt.IsValid() && (imm == 0)) {
14612          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14613            EmitT32_32(0xffb10200U |
14614                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14615                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14616                       rd.Encode(22, 12) | rm.Encode(5, 0));
14617            AdvanceIT();
14618            return;
14619          }
14620        }
14621      } else {
14622        // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14623        if (encoded_dt.IsValid() && (imm == 0)) {
14624          if (cond.Is(al)) {
14625            EmitA32(0xf3b10200U |
14626                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14627                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14628                    rd.Encode(22, 12) | rm.Encode(5, 0));
14629            return;
14630          }
14631        }
14632      }
14633    }
14634  }
14635  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
14636}
14637
14638void Assembler::vclt(Condition cond,
14639                     DataType dt,
14640                     QRegister rd,
14641                     QRegister rm,
14642                     const QOperand& operand) {
14643  VIXL_ASSERT(AllowAssembler());
14644  CheckIT(cond);
14645  if (operand.IsImmediate()) {
14646    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14647      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14648      Dt_F_size_1 encoded_dt(dt);
14649      if (IsUsingT32()) {
14650        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14651        if (encoded_dt.IsValid() && (imm == 0)) {
14652          if (cond.Is(al) || AllowStronglyDiscouraged()) {
14653            EmitT32_32(0xffb10240U |
14654                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14655                       ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14656                       rd.Encode(22, 12) | rm.Encode(5, 0));
14657            AdvanceIT();
14658            return;
14659          }
14660        }
14661      } else {
14662        // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14663        if (encoded_dt.IsValid() && (imm == 0)) {
14664          if (cond.Is(al)) {
14665            EmitA32(0xf3b10240U |
14666                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14667                    ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14668                    rd.Encode(22, 12) | rm.Encode(5, 0));
14669            return;
14670          }
14671        }
14672      }
14673    }
14674  }
14675  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
14676}
14677
14678void Assembler::vclt(
14679    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
14680  VIXL_ASSERT(AllowAssembler());
14681  CheckIT(cond);
14682  Dt_U_size_1 encoded_dt(dt);
14683  if (IsUsingT32()) {
14684    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14685    if (encoded_dt.IsValid()) {
14686      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14687        EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14688                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14689                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14690        AdvanceIT();
14691        return;
14692      }
14693    }
14694    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14695    if (dt.Is(F32)) {
14696      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14697        EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14698                   rm.Encode(7, 16));
14699        AdvanceIT();
14700        return;
14701      }
14702    }
14703  } else {
14704    // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14705    if (encoded_dt.IsValid()) {
14706      if (cond.Is(al)) {
14707        EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14708                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14709                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14710        return;
14711      }
14712    }
14713    // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14714    if (dt.Is(F32)) {
14715      if (cond.Is(al)) {
14716        EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14717                rm.Encode(7, 16));
14718        return;
14719      }
14720    }
14721  }
14722  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
14723}
14724
14725void Assembler::vclt(
14726    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
14727  VIXL_ASSERT(AllowAssembler());
14728  CheckIT(cond);
14729  Dt_U_size_1 encoded_dt(dt);
14730  if (IsUsingT32()) {
14731    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14732    if (encoded_dt.IsValid()) {
14733      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14734        EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14735                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14736                   rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14737        AdvanceIT();
14738        return;
14739      }
14740    }
14741    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14742    if (dt.Is(F32)) {
14743      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14744        EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14745                   rm.Encode(7, 16));
14746        AdvanceIT();
14747        return;
14748      }
14749    }
14750  } else {
14751    // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14752    if (encoded_dt.IsValid()) {
14753      if (cond.Is(al)) {
14754        EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14755                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14756                rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
14757        return;
14758      }
14759    }
14760    // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14761    if (dt.Is(F32)) {
14762      if (cond.Is(al)) {
14763        EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14764                rm.Encode(7, 16));
14765        return;
14766      }
14767    }
14768  }
14769  Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
14770}
14771
14772void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14773  VIXL_ASSERT(AllowAssembler());
14774  CheckIT(cond);
14775  Dt_size_4 encoded_dt(dt);
14776  if (IsUsingT32()) {
14777    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14778    if (encoded_dt.IsValid()) {
14779      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14780        EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
14781                   rd.Encode(22, 12) | rm.Encode(5, 0));
14782        AdvanceIT();
14783        return;
14784      }
14785    }
14786  } else {
14787    // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14788    if (encoded_dt.IsValid()) {
14789      if (cond.Is(al)) {
14790        EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
14791                rd.Encode(22, 12) | rm.Encode(5, 0));
14792        return;
14793      }
14794    }
14795  }
14796  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
14797}
14798
14799void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
14800  VIXL_ASSERT(AllowAssembler());
14801  CheckIT(cond);
14802  Dt_size_4 encoded_dt(dt);
14803  if (IsUsingT32()) {
14804    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14805    if (encoded_dt.IsValid()) {
14806      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14807        EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
14808                   rd.Encode(22, 12) | rm.Encode(5, 0));
14809        AdvanceIT();
14810        return;
14811      }
14812    }
14813  } else {
14814    // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14815    if (encoded_dt.IsValid()) {
14816      if (cond.Is(al)) {
14817        EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
14818                rd.Encode(22, 12) | rm.Encode(5, 0));
14819        return;
14820      }
14821    }
14822  }
14823  Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
14824}
14825
14826void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm) {
14827  VIXL_ASSERT(AllowAssembler());
14828  CheckIT(cond);
14829  if (IsUsingT32()) {
14830    // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
14831    if (dt.Is(F32)) {
14832      EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
14833      AdvanceIT();
14834      return;
14835    }
14836  } else {
14837    // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
14838    if (dt.Is(F32) && cond.IsNotNever()) {
14839      EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14840              rm.Encode(5, 0));
14841      return;
14842    }
14843  }
14844  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
14845}
14846
14847void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14848  VIXL_ASSERT(AllowAssembler());
14849  CheckIT(cond);
14850  if (IsUsingT32()) {
14851    // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
14852    if (dt.Is(F64)) {
14853      EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
14854      AdvanceIT();
14855      return;
14856    }
14857  } else {
14858    // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
14859    if (dt.Is(F64) && cond.IsNotNever()) {
14860      EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14861              rm.Encode(5, 0));
14862      return;
14863    }
14864  }
14865  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
14866}
14867
14868void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, double imm) {
14869  VIXL_ASSERT(AllowAssembler());
14870  CheckIT(cond);
14871  if (IsUsingT32()) {
14872    // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
14873    if (dt.Is(F32) && (imm == 0.0)) {
14874      EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
14875      AdvanceIT();
14876      return;
14877    }
14878  } else {
14879    // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
14880    if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
14881      EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14882      return;
14883    }
14884  }
14885  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
14886}
14887
14888void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, double imm) {
14889  VIXL_ASSERT(AllowAssembler());
14890  CheckIT(cond);
14891  if (IsUsingT32()) {
14892    // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
14893    if (dt.Is(F64) && (imm == 0.0)) {
14894      EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
14895      AdvanceIT();
14896      return;
14897    }
14898  } else {
14899    // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
14900    if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
14901      EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14902      return;
14903    }
14904  }
14905  Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
14906}
14907
14908void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm) {
14909  VIXL_ASSERT(AllowAssembler());
14910  CheckIT(cond);
14911  if (IsUsingT32()) {
14912    // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
14913    if (dt.Is(F32)) {
14914      EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14915      AdvanceIT();
14916      return;
14917    }
14918  } else {
14919    // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
14920    if (dt.Is(F32) && cond.IsNotNever()) {
14921      EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14922              rm.Encode(5, 0));
14923      return;
14924    }
14925  }
14926  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
14927}
14928
14929void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14930  VIXL_ASSERT(AllowAssembler());
14931  CheckIT(cond);
14932  if (IsUsingT32()) {
14933    // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
14934    if (dt.Is(F64)) {
14935      EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14936      AdvanceIT();
14937      return;
14938    }
14939  } else {
14940    // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
14941    if (dt.Is(F64) && cond.IsNotNever()) {
14942      EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14943              rm.Encode(5, 0));
14944      return;
14945    }
14946  }
14947  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
14948}
14949
14950void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, double imm) {
14951  VIXL_ASSERT(AllowAssembler());
14952  CheckIT(cond);
14953  if (IsUsingT32()) {
14954    // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
14955    if (dt.Is(F32) && (imm == 0.0)) {
14956      EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
14957      AdvanceIT();
14958      return;
14959    }
14960  } else {
14961    // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
14962    if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
14963      EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14964      return;
14965    }
14966  }
14967  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
14968}
14969
14970void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, double imm) {
14971  VIXL_ASSERT(AllowAssembler());
14972  CheckIT(cond);
14973  if (IsUsingT32()) {
14974    // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
14975    if (dt.Is(F64) && (imm == 0.0)) {
14976      EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
14977      AdvanceIT();
14978      return;
14979    }
14980  } else {
14981    // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
14982    if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
14983      EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14984      return;
14985    }
14986  }
14987  Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
14988}
14989
14990void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
14991  VIXL_ASSERT(AllowAssembler());
14992  CheckIT(cond);
14993  if (IsUsingT32()) {
14994    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
14995    if (dt.Is(Untyped8)) {
14996      if (cond.Is(al) || AllowStronglyDiscouraged()) {
14997        EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
14998        AdvanceIT();
14999        return;
15000      }
15001    }
15002  } else {
15003    // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
15004    if (dt.Is(Untyped8)) {
15005      if (cond.Is(al)) {
15006        EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
15007        return;
15008      }
15009    }
15010  }
15011  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
15012}
15013
15014void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
15015  VIXL_ASSERT(AllowAssembler());
15016  CheckIT(cond);
15017  if (IsUsingT32()) {
15018    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
15019    if (dt.Is(Untyped8)) {
15020      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15021        EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
15022        AdvanceIT();
15023        return;
15024      }
15025    }
15026  } else {
15027    // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
15028    if (dt.Is(Untyped8)) {
15029      if (cond.Is(al)) {
15030        EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
15031        return;
15032      }
15033    }
15034  }
15035  Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
15036}
15037
15038void Assembler::vcvt(
15039    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
15040  VIXL_ASSERT(AllowAssembler());
15041  CheckIT(cond);
15042  Dt_op_2 encoded_dt(dt2);
15043  if (IsUsingT32()) {
15044    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
15045    if (dt1.Is(F64) && dt2.Is(F32)) {
15046      EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15047      AdvanceIT();
15048      return;
15049    }
15050    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
15051    if (dt1.Is(F64) && encoded_dt.IsValid()) {
15052      EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
15053                 rd.Encode(22, 12) | rm.Encode(5, 0));
15054      AdvanceIT();
15055      return;
15056    }
15057  } else {
15058    // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
15059    if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
15060      EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15061              rm.Encode(5, 0));
15062      return;
15063    }
15064    // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
15065    if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
15066      EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
15067              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
15068              rm.Encode(5, 0));
15069      return;
15070    }
15071  }
15072  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15073}
15074
15075void Assembler::vcvt(
15076    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15077  VIXL_ASSERT(AllowAssembler());
15078  CheckIT(cond);
15079  if (IsUsingT32()) {
15080    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
15081    if (dt1.Is(F32) && dt2.Is(F64)) {
15082      EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15083      AdvanceIT();
15084      return;
15085    }
15086    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
15087    if (dt1.Is(U32) && dt2.Is(F64)) {
15088      EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15089      AdvanceIT();
15090      return;
15091    }
15092    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
15093    if (dt1.Is(S32) && dt2.Is(F64)) {
15094      EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15095      AdvanceIT();
15096      return;
15097    }
15098  } else {
15099    // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
15100    if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
15101      EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15102              rm.Encode(5, 0));
15103      return;
15104    }
15105    // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
15106    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
15107      EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15108              rm.Encode(5, 0));
15109      return;
15110    }
15111    // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
15112    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
15113      EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15114              rm.Encode(5, 0));
15115      return;
15116    }
15117  }
15118  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15119}
15120
15121void Assembler::vcvt(Condition cond,
15122                     DataType dt1,
15123                     DataType dt2,
15124                     DRegister rd,
15125                     DRegister rm,
15126                     int32_t fbits) {
15127  VIXL_ASSERT(AllowAssembler());
15128  CheckIT(cond);
15129  Dt_op_U_1 encoded_dt(dt1, dt2);
15130  Dt_U_sx_1 encoded_dt_2(dt2);
15131  Dt_U_sx_1 encoded_dt_3(dt1);
15132  if (IsUsingT32()) {
15133    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
15134    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15135      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15136        uint32_t fbits_ = 64 - fbits;
15137        EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
15138                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15139                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15140        AdvanceIT();
15141        return;
15142      }
15143    }
15144    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
15145    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
15146        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15147         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15148      unsigned offset = 32;
15149      if (dt2.Is(S16) || dt2.Is(U16)) {
15150        offset = 16;
15151      }
15152      uint32_t fbits_ = offset - fbits;
15153      EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15154                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15155                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15156                 ((fbits_ & 0x1e) >> 1));
15157      AdvanceIT();
15158      return;
15159    }
15160    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
15161    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
15162        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15163         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15164      unsigned offset = 32;
15165      if (dt1.Is(S16) || dt1.Is(U16)) {
15166        offset = 16;
15167      }
15168      uint32_t fbits_ = offset - fbits;
15169      EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
15170                 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
15171                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15172                 ((fbits_ & 0x1e) >> 1));
15173      AdvanceIT();
15174      return;
15175    }
15176  } else {
15177    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
15178    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15179      if (cond.Is(al)) {
15180        uint32_t fbits_ = 64 - fbits;
15181        EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
15182                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15183                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15184        return;
15185      }
15186    }
15187    // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
15188    if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
15189        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15190         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15191        cond.IsNotNever()) {
15192      unsigned offset = 32;
15193      if (dt2.Is(S16) || dt2.Is(U16)) {
15194        offset = 16;
15195      }
15196      uint32_t fbits_ = offset - fbits;
15197      EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
15198              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15199              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15200              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15201              ((fbits_ & 0x1e) >> 1));
15202      return;
15203    }
15204    // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
15205    if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
15206        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15207         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15208        cond.IsNotNever()) {
15209      unsigned offset = 32;
15210      if (dt1.Is(S16) || dt1.Is(U16)) {
15211        offset = 16;
15212      }
15213      uint32_t fbits_ = offset - fbits;
15214      EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
15215              ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
15216              ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
15217              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15218              ((fbits_ & 0x1e) >> 1));
15219      return;
15220    }
15221  }
15222  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15223}
15224
15225void Assembler::vcvt(Condition cond,
15226                     DataType dt1,
15227                     DataType dt2,
15228                     QRegister rd,
15229                     QRegister rm,
15230                     int32_t fbits) {
15231  VIXL_ASSERT(AllowAssembler());
15232  CheckIT(cond);
15233  Dt_op_U_1 encoded_dt(dt1, dt2);
15234  if (IsUsingT32()) {
15235    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
15236    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15237      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15238        uint32_t fbits_ = 64 - fbits;
15239        EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
15240                   ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15241                   rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15242        AdvanceIT();
15243        return;
15244      }
15245    }
15246  } else {
15247    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
15248    if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15249      if (cond.Is(al)) {
15250        uint32_t fbits_ = 64 - fbits;
15251        EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
15252                ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15253                rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15254        return;
15255      }
15256    }
15257  }
15258  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15259}
15260
15261void Assembler::vcvt(Condition cond,
15262                     DataType dt1,
15263                     DataType dt2,
15264                     SRegister rd,
15265                     SRegister rm,
15266                     int32_t fbits) {
15267  VIXL_ASSERT(AllowAssembler());
15268  CheckIT(cond);
15269  Dt_U_sx_1 encoded_dt(dt2);
15270  Dt_U_sx_1 encoded_dt_2(dt1);
15271  if (IsUsingT32()) {
15272    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
15273    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
15274        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15275         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15276      unsigned offset = 32;
15277      if (dt2.Is(S16) || dt2.Is(U16)) {
15278        offset = 16;
15279      }
15280      uint32_t fbits_ = offset - fbits;
15281      EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
15282                 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
15283                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15284                 ((fbits_ & 0x1e) >> 1));
15285      AdvanceIT();
15286      return;
15287    }
15288    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
15289    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
15290        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15291         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15292      unsigned offset = 32;
15293      if (dt1.Is(S16) || dt1.Is(U16)) {
15294        offset = 16;
15295      }
15296      uint32_t fbits_ = offset - fbits;
15297      EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15298                 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15299                 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15300                 ((fbits_ & 0x1e) >> 1));
15301      AdvanceIT();
15302      return;
15303    }
15304  } else {
15305    // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
15306    if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
15307        (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15308         ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15309        cond.IsNotNever()) {
15310      unsigned offset = 32;
15311      if (dt2.Is(S16) || dt2.Is(U16)) {
15312        offset = 16;
15313      }
15314      uint32_t fbits_ = offset - fbits;
15315      EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
15316              ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
15317              ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
15318              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15319              ((fbits_ & 0x1e) >> 1));
15320      return;
15321    }
15322    // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
15323    if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
15324        (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15325         ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15326        cond.IsNotNever()) {
15327      unsigned offset = 32;
15328      if (dt1.Is(S16) || dt1.Is(U16)) {
15329        offset = 16;
15330      }
15331      uint32_t fbits_ = offset - fbits;
15332      EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
15333              ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15334              ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15335              rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15336              ((fbits_ & 0x1e) >> 1));
15337      return;
15338    }
15339  }
15340  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15341}
15342
15343void Assembler::vcvt(
15344    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15345  VIXL_ASSERT(AllowAssembler());
15346  CheckIT(cond);
15347  Dt_op_1 encoded_dt(dt1, dt2);
15348  if (IsUsingT32()) {
15349    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
15350    if (encoded_dt.IsValid()) {
15351      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15352        EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
15353                   rd.Encode(22, 12) | rm.Encode(5, 0));
15354        AdvanceIT();
15355        return;
15356      }
15357    }
15358  } else {
15359    // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
15360    if (encoded_dt.IsValid()) {
15361      if (cond.Is(al)) {
15362        EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
15363                rd.Encode(22, 12) | rm.Encode(5, 0));
15364        return;
15365      }
15366    }
15367  }
15368  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15369}
15370
15371void Assembler::vcvt(
15372    Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15373  VIXL_ASSERT(AllowAssembler());
15374  CheckIT(cond);
15375  Dt_op_1 encoded_dt(dt1, dt2);
15376  if (IsUsingT32()) {
15377    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
15378    if (encoded_dt.IsValid()) {
15379      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15380        EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
15381                   rd.Encode(22, 12) | rm.Encode(5, 0));
15382        AdvanceIT();
15383        return;
15384      }
15385    }
15386  } else {
15387    // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
15388    if (encoded_dt.IsValid()) {
15389      if (cond.Is(al)) {
15390        EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
15391                rd.Encode(22, 12) | rm.Encode(5, 0));
15392        return;
15393      }
15394    }
15395  }
15396  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15397}
15398
15399void Assembler::vcvt(
15400    Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
15401  VIXL_ASSERT(AllowAssembler());
15402  CheckIT(cond);
15403  if (IsUsingT32()) {
15404    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
15405    if (dt1.Is(F16) && dt2.Is(F32)) {
15406      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15407        EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
15408        AdvanceIT();
15409        return;
15410      }
15411    }
15412  } else {
15413    // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
15414    if (dt1.Is(F16) && dt2.Is(F32)) {
15415      if (cond.Is(al)) {
15416        EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
15417        return;
15418      }
15419    }
15420  }
15421  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15422}
15423
15424void Assembler::vcvt(
15425    Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
15426  VIXL_ASSERT(AllowAssembler());
15427  CheckIT(cond);
15428  if (IsUsingT32()) {
15429    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
15430    if (dt1.Is(F32) && dt2.Is(F16)) {
15431      if (cond.Is(al) || AllowStronglyDiscouraged()) {
15432        EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
15433        AdvanceIT();
15434        return;
15435      }
15436    }
15437  } else {
15438    // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
15439    if (dt1.Is(F32) && dt2.Is(F16)) {
15440      if (cond.Is(al)) {
15441        EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
15442        return;
15443      }
15444    }
15445  }
15446  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15447}
15448
15449void Assembler::vcvt(
15450    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15451  VIXL_ASSERT(AllowAssembler());
15452  CheckIT(cond);
15453  Dt_op_2 encoded_dt(dt2);
15454  if (IsUsingT32()) {
15455    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
15456    if (dt1.Is(U32) && dt2.Is(F32)) {
15457      EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15458      AdvanceIT();
15459      return;
15460    }
15461    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
15462    if (dt1.Is(S32) && dt2.Is(F32)) {
15463      EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15464      AdvanceIT();
15465      return;
15466    }
15467    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
15468    if (dt1.Is(F32) && encoded_dt.IsValid()) {
15469      EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
15470                 rd.Encode(22, 12) | rm.Encode(5, 0));
15471      AdvanceIT();
15472      return;
15473    }
15474  } else {
15475    // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
15476    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
15477      EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15478              rm.Encode(5, 0));
15479      return;
15480    }
15481    // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
15482    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
15483      EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15484              rm.Encode(5, 0));
15485      return;
15486    }
15487    // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
15488    if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
15489      EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
15490              (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
15491              rm.Encode(5, 0));
15492      return;
15493    }
15494  }
15495  Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15496}
15497
15498void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15499  VIXL_ASSERT(AllowAssembler());
15500  CheckIT(al);
15501  Dt_op_3 encoded_dt(dt1);
15502  if (IsUsingT32()) {
15503    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15504    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15505      EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
15506                 rd.Encode(22, 12) | rm.Encode(5, 0));
15507      AdvanceIT();
15508      return;
15509    }
15510  } else {
15511    // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15512    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15513      EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
15514              rd.Encode(22, 12) | rm.Encode(5, 0));
15515      return;
15516    }
15517  }
15518  Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15519}
15520
15521void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15522  VIXL_ASSERT(AllowAssembler());
15523  CheckIT(al);
15524  Dt_op_3 encoded_dt(dt1);
15525  if (IsUsingT32()) {
15526    // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15527    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15528      EmitT32_32(0xffbb0040U | (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 <Qd>, <Qm> ; A1
15535    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15536      EmitA32(0xf3bb0040U | (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, SRegister rd, SRegister rm) {
15545  VIXL_ASSERT(AllowAssembler());
15546  CheckIT(al);
15547  Dt_op_2 encoded_dt(dt1);
15548  if (IsUsingT32()) {
15549    // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15550    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15551      EmitT32_32(0xfebc0a40U | (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 <Sd>, <Sm> ; A1
15558    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15559      EmitA32(0xfebc0a40U | (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, DRegister rm) {
15568  VIXL_ASSERT(AllowAssembler());
15569  CheckIT(al);
15570  Dt_op_2 encoded_dt(dt1);
15571  if (IsUsingT32()) {
15572    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15573    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15574      EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
15575                 rd.Encode(22, 12) | rm.Encode(5, 0));
15576      AdvanceIT();
15577      return;
15578    }
15579  } else {
15580    // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15581    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15582      EmitA32(0xfebc0b40U | (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::vcvtb(
15591    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15592  VIXL_ASSERT(AllowAssembler());
15593  CheckIT(cond);
15594  if (IsUsingT32()) {
15595    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
15596    if (dt1.Is(F32) && dt2.Is(F16)) {
15597      EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15598      AdvanceIT();
15599      return;
15600    }
15601    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
15602    if (dt1.Is(F16) && dt2.Is(F32)) {
15603      EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15604      AdvanceIT();
15605      return;
15606    }
15607  } else {
15608    // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
15609    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
15610      EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15611              rm.Encode(5, 0));
15612      return;
15613    }
15614    // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
15615    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
15616      EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15617              rm.Encode(5, 0));
15618      return;
15619    }
15620  }
15621  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15622}
15623
15624void Assembler::vcvtb(
15625    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
15626  VIXL_ASSERT(AllowAssembler());
15627  CheckIT(cond);
15628  if (IsUsingT32()) {
15629    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
15630    if (dt1.Is(F64) && dt2.Is(F16)) {
15631      EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15632      AdvanceIT();
15633      return;
15634    }
15635  } else {
15636    // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
15637    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
15638      EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15639              rm.Encode(5, 0));
15640      return;
15641    }
15642  }
15643  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15644}
15645
15646void Assembler::vcvtb(
15647    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15648  VIXL_ASSERT(AllowAssembler());
15649  CheckIT(cond);
15650  if (IsUsingT32()) {
15651    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
15652    if (dt1.Is(F16) && dt2.Is(F64)) {
15653      EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15654      AdvanceIT();
15655      return;
15656    }
15657  } else {
15658    // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
15659    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
15660      EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15661              rm.Encode(5, 0));
15662      return;
15663    }
15664  }
15665  Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15666}
15667
15668void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15669  VIXL_ASSERT(AllowAssembler());
15670  CheckIT(al);
15671  Dt_op_3 encoded_dt(dt1);
15672  if (IsUsingT32()) {
15673    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15674    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15675      EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
15676                 rd.Encode(22, 12) | rm.Encode(5, 0));
15677      AdvanceIT();
15678      return;
15679    }
15680  } else {
15681    // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15682    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15683      EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
15684              rd.Encode(22, 12) | rm.Encode(5, 0));
15685      return;
15686    }
15687  }
15688  Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15689}
15690
15691void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15692  VIXL_ASSERT(AllowAssembler());
15693  CheckIT(al);
15694  Dt_op_3 encoded_dt(dt1);
15695  if (IsUsingT32()) {
15696    // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15697    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15698      EmitT32_32(0xffbb0340U | (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 <Qd>, <Qm> ; A1
15705    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15706      EmitA32(0xf3bb0340U | (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, SRegister rd, SRegister rm) {
15715  VIXL_ASSERT(AllowAssembler());
15716  CheckIT(al);
15717  Dt_op_2 encoded_dt(dt1);
15718  if (IsUsingT32()) {
15719    // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15720    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15721      EmitT32_32(0xfebf0a40U | (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 <Sd>, <Sm> ; A1
15728    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15729      EmitA32(0xfebf0a40U | (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, DRegister rm) {
15738  VIXL_ASSERT(AllowAssembler());
15739  CheckIT(al);
15740  Dt_op_2 encoded_dt(dt1);
15741  if (IsUsingT32()) {
15742    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15743    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15744      EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
15745                 rd.Encode(22, 12) | rm.Encode(5, 0));
15746      AdvanceIT();
15747      return;
15748    }
15749  } else {
15750    // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15751    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15752      EmitA32(0xfebf0b40U | (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::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15761  VIXL_ASSERT(AllowAssembler());
15762  CheckIT(al);
15763  Dt_op_3 encoded_dt(dt1);
15764  if (IsUsingT32()) {
15765    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15766    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15767      EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
15768                 rd.Encode(22, 12) | rm.Encode(5, 0));
15769      AdvanceIT();
15770      return;
15771    }
15772  } else {
15773    // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15774    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15775      EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
15776              rd.Encode(22, 12) | rm.Encode(5, 0));
15777      return;
15778    }
15779  }
15780  Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15781}
15782
15783void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15784  VIXL_ASSERT(AllowAssembler());
15785  CheckIT(al);
15786  Dt_op_3 encoded_dt(dt1);
15787  if (IsUsingT32()) {
15788    // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15789    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15790      EmitT32_32(0xffbb0140U | (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 <Qd>, <Qm> ; A1
15797    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15798      EmitA32(0xf3bb0140U | (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, SRegister rd, SRegister rm) {
15807  VIXL_ASSERT(AllowAssembler());
15808  CheckIT(al);
15809  Dt_op_2 encoded_dt(dt1);
15810  if (IsUsingT32()) {
15811    // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15812    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15813      EmitT32_32(0xfebd0a40U | (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 <Sd>, <Sm> ; A1
15820    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15821      EmitA32(0xfebd0a40U | (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, DRegister rm) {
15830  VIXL_ASSERT(AllowAssembler());
15831  CheckIT(al);
15832  Dt_op_2 encoded_dt(dt1);
15833  if (IsUsingT32()) {
15834    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15835    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15836      EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
15837                 rd.Encode(22, 12) | rm.Encode(5, 0));
15838      AdvanceIT();
15839      return;
15840    }
15841  } else {
15842    // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15843    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15844      EmitA32(0xfebd0b40U | (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::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
15853  VIXL_ASSERT(AllowAssembler());
15854  CheckIT(al);
15855  Dt_op_3 encoded_dt(dt1);
15856  if (IsUsingT32()) {
15857    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15858    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15859      EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
15860                 rd.Encode(22, 12) | rm.Encode(5, 0));
15861      AdvanceIT();
15862      return;
15863    }
15864  } else {
15865    // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15866    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15867      EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
15868              rd.Encode(22, 12) | rm.Encode(5, 0));
15869      return;
15870    }
15871  }
15872  Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15873}
15874
15875void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
15876  VIXL_ASSERT(AllowAssembler());
15877  CheckIT(al);
15878  Dt_op_3 encoded_dt(dt1);
15879  if (IsUsingT32()) {
15880    // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15881    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15882      EmitT32_32(0xffbb0240U | (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 <Qd>, <Qm> ; A1
15889    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15890      EmitA32(0xf3bb0240U | (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, SRegister rd, SRegister rm) {
15899  VIXL_ASSERT(AllowAssembler());
15900  CheckIT(al);
15901  Dt_op_2 encoded_dt(dt1);
15902  if (IsUsingT32()) {
15903    // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15904    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15905      EmitT32_32(0xfebe0a40U | (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 <Sd>, <Sm> ; A1
15912    if (encoded_dt.IsValid() && dt2.Is(F32)) {
15913      EmitA32(0xfebe0a40U | (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, DRegister rm) {
15922  VIXL_ASSERT(AllowAssembler());
15923  CheckIT(al);
15924  Dt_op_2 encoded_dt(dt1);
15925  if (IsUsingT32()) {
15926    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15927    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15928      EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
15929                 rd.Encode(22, 12) | rm.Encode(5, 0));
15930      AdvanceIT();
15931      return;
15932    }
15933  } else {
15934    // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15935    if (encoded_dt.IsValid() && dt2.Is(F64)) {
15936      EmitA32(0xfebe0b40U | (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::vcvtr(
15945    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
15946  VIXL_ASSERT(AllowAssembler());
15947  CheckIT(cond);
15948  if (IsUsingT32()) {
15949    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
15950    if (dt1.Is(U32) && dt2.Is(F32)) {
15951      EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15952      AdvanceIT();
15953      return;
15954    }
15955    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
15956    if (dt1.Is(S32) && dt2.Is(F32)) {
15957      EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15958      AdvanceIT();
15959      return;
15960    }
15961  } else {
15962    // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
15963    if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
15964      EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15965              rm.Encode(5, 0));
15966      return;
15967    }
15968    // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
15969    if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
15970      EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15971              rm.Encode(5, 0));
15972      return;
15973    }
15974  }
15975  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
15976}
15977
15978void Assembler::vcvtr(
15979    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
15980  VIXL_ASSERT(AllowAssembler());
15981  CheckIT(cond);
15982  if (IsUsingT32()) {
15983    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
15984    if (dt1.Is(U32) && dt2.Is(F64)) {
15985      EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15986      AdvanceIT();
15987      return;
15988    }
15989    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
15990    if (dt1.Is(S32) && dt2.Is(F64)) {
15991      EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15992      AdvanceIT();
15993      return;
15994    }
15995  } else {
15996    // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
15997    if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
15998      EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15999              rm.Encode(5, 0));
16000      return;
16001    }
16002    // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16003    if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16004      EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16005              rm.Encode(5, 0));
16006      return;
16007    }
16008  }
16009  Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
16010}
16011
16012void Assembler::vcvtt(
16013    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
16014  VIXL_ASSERT(AllowAssembler());
16015  CheckIT(cond);
16016  if (IsUsingT32()) {
16017    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16018    if (dt1.Is(F32) && dt2.Is(F16)) {
16019      EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16020      AdvanceIT();
16021      return;
16022    }
16023    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16024    if (dt1.Is(F16) && dt2.Is(F32)) {
16025      EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16026      AdvanceIT();
16027      return;
16028    }
16029  } else {
16030    // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16031    if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16032      EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16033              rm.Encode(5, 0));
16034      return;
16035    }
16036    // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16037    if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16038      EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16039              rm.Encode(5, 0));
16040      return;
16041    }
16042  }
16043  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16044}
16045
16046void Assembler::vcvtt(
16047    Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
16048  VIXL_ASSERT(AllowAssembler());
16049  CheckIT(cond);
16050  if (IsUsingT32()) {
16051    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16052    if (dt1.Is(F64) && dt2.Is(F16)) {
16053      EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16054      AdvanceIT();
16055      return;
16056    }
16057  } else {
16058    // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16059    if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16060      EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16061              rm.Encode(5, 0));
16062      return;
16063    }
16064  }
16065  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16066}
16067
16068void Assembler::vcvtt(
16069    Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
16070  VIXL_ASSERT(AllowAssembler());
16071  CheckIT(cond);
16072  if (IsUsingT32()) {
16073    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16074    if (dt1.Is(F16) && dt2.Is(F64)) {
16075      EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16076      AdvanceIT();
16077      return;
16078    }
16079  } else {
16080    // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16081    if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16082      EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16083              rm.Encode(5, 0));
16084      return;
16085    }
16086  }
16087  Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16088}
16089
16090void Assembler::vdiv(
16091    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16092  VIXL_ASSERT(AllowAssembler());
16093  CheckIT(cond);
16094  if (IsUsingT32()) {
16095    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
16096    if (dt.Is(F32)) {
16097      EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16098                 rm.Encode(5, 0));
16099      AdvanceIT();
16100      return;
16101    }
16102  } else {
16103    // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
16104    if (dt.Is(F32) && cond.IsNotNever()) {
16105      EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16106              rn.Encode(7, 16) | rm.Encode(5, 0));
16107      return;
16108    }
16109  }
16110  Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
16111}
16112
16113void Assembler::vdiv(
16114    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16115  VIXL_ASSERT(AllowAssembler());
16116  CheckIT(cond);
16117  if (IsUsingT32()) {
16118    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
16119    if (dt.Is(F64)) {
16120      EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16121                 rm.Encode(5, 0));
16122      AdvanceIT();
16123      return;
16124    }
16125  } else {
16126    // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
16127    if (dt.Is(F64) && cond.IsNotNever()) {
16128      EmitA32(0x0e800b00U | (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::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
16137  VIXL_ASSERT(AllowAssembler());
16138  CheckIT(cond);
16139  Dt_B_E_1 encoded_dt(dt);
16140  if (IsUsingT32()) {
16141    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
16142    if (encoded_dt.IsValid()) {
16143      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16144        EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16145                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16146                   rd.Encode(7, 16) | (rt.GetCode() << 12));
16147        AdvanceIT();
16148        return;
16149      }
16150    }
16151  } else {
16152    // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
16153    if (encoded_dt.IsValid() && cond.IsNotNever()) {
16154      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16155        EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
16156                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16157                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16158                rd.Encode(7, 16) | (rt.GetCode() << 12));
16159        return;
16160      }
16161    }
16162  }
16163  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
16164}
16165
16166void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
16167  VIXL_ASSERT(AllowAssembler());
16168  CheckIT(cond);
16169  Dt_B_E_1 encoded_dt(dt);
16170  if (IsUsingT32()) {
16171    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
16172    if (encoded_dt.IsValid()) {
16173      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16174        EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16175                   ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16176                   rd.Encode(7, 16) | (rt.GetCode() << 12));
16177        AdvanceIT();
16178        return;
16179      }
16180    }
16181  } else {
16182    // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
16183    if (encoded_dt.IsValid() && cond.IsNotNever()) {
16184      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16185        EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
16186                ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16187                ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16188                rd.Encode(7, 16) | (rt.GetCode() << 12));
16189        return;
16190      }
16191    }
16192  }
16193  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
16194}
16195
16196void Assembler::vdup(Condition cond,
16197                     DataType dt,
16198                     DRegister rd,
16199                     DRegisterLane rm) {
16200  VIXL_ASSERT(AllowAssembler());
16201  CheckIT(cond);
16202  Dt_imm4_1 encoded_dt(dt, rm);
16203  if (IsUsingT32()) {
16204    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
16205    if (encoded_dt.IsValid()) {
16206      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16207        EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
16208                   rd.Encode(22, 12) | rm.Encode(5, 0));
16209        AdvanceIT();
16210        return;
16211      }
16212    }
16213  } else {
16214    // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
16215    if (encoded_dt.IsValid()) {
16216      if (cond.Is(al)) {
16217        EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
16218                rd.Encode(22, 12) | rm.Encode(5, 0));
16219        return;
16220      }
16221    }
16222  }
16223  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
16224}
16225
16226void Assembler::vdup(Condition cond,
16227                     DataType dt,
16228                     QRegister rd,
16229                     DRegisterLane rm) {
16230  VIXL_ASSERT(AllowAssembler());
16231  CheckIT(cond);
16232  Dt_imm4_1 encoded_dt(dt, rm);
16233  if (IsUsingT32()) {
16234    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
16235    if (encoded_dt.IsValid()) {
16236      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16237        EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
16238                   rd.Encode(22, 12) | rm.Encode(5, 0));
16239        AdvanceIT();
16240        return;
16241      }
16242    }
16243  } else {
16244    // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
16245    if (encoded_dt.IsValid()) {
16246      if (cond.Is(al)) {
16247        EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
16248                rd.Encode(22, 12) | rm.Encode(5, 0));
16249        return;
16250      }
16251    }
16252  }
16253  Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
16254}
16255
16256void Assembler::veor(
16257    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16258  VIXL_ASSERT(AllowAssembler());
16259  CheckIT(cond);
16260  USE(dt);
16261  if (IsUsingT32()) {
16262    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
16263    if (cond.Is(al) || AllowStronglyDiscouraged()) {
16264      EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16265                 rm.Encode(5, 0));
16266      AdvanceIT();
16267      return;
16268    }
16269  } else {
16270    // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
16271    if (cond.Is(al)) {
16272      EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16273              rm.Encode(5, 0));
16274      return;
16275    }
16276  }
16277  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
16278}
16279
16280void Assembler::veor(
16281    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16282  VIXL_ASSERT(AllowAssembler());
16283  CheckIT(cond);
16284  USE(dt);
16285  if (IsUsingT32()) {
16286    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
16287    if (cond.Is(al) || AllowStronglyDiscouraged()) {
16288      EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16289                 rm.Encode(5, 0));
16290      AdvanceIT();
16291      return;
16292    }
16293  } else {
16294    // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
16295    if (cond.Is(al)) {
16296      EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16297              rm.Encode(5, 0));
16298      return;
16299    }
16300  }
16301  Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
16302}
16303
16304void Assembler::vext(Condition cond,
16305                     DataType dt,
16306                     DRegister rd,
16307                     DRegister rn,
16308                     DRegister rm,
16309                     const DOperand& operand) {
16310  VIXL_ASSERT(AllowAssembler());
16311  CheckIT(cond);
16312  if (operand.IsImmediate()) {
16313    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
16314      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
16315      if (IsUsingT32()) {
16316        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
16317        if (dt.Is(Untyped8) && (imm <= 7)) {
16318          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16319            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16320                       rm.Encode(5, 0) | (imm << 8));
16321            AdvanceIT();
16322            return;
16323          }
16324        }
16325        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
16326        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
16327            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16328          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16329            uint32_t imm4 = imm / dt.GetSize();
16330            EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16331                       rm.Encode(5, 0) | (imm4 << 8));
16332            AdvanceIT();
16333            return;
16334          }
16335        }
16336      } else {
16337        // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
16338        if (dt.Is(Untyped8) && (imm <= 7)) {
16339          if (cond.Is(al)) {
16340            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16341                    rm.Encode(5, 0) | (imm << 8));
16342            return;
16343          }
16344        }
16345        // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
16346        if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
16347            (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16348          if (cond.Is(al)) {
16349            uint32_t imm4 = imm / dt.GetSize();
16350            EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16351                    rm.Encode(5, 0) | (imm4 << 8));
16352            return;
16353          }
16354        }
16355      }
16356    }
16357  }
16358  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
16359}
16360
16361void Assembler::vext(Condition cond,
16362                     DataType dt,
16363                     QRegister rd,
16364                     QRegister rn,
16365                     QRegister rm,
16366                     const QOperand& operand) {
16367  VIXL_ASSERT(AllowAssembler());
16368  CheckIT(cond);
16369  if (operand.IsImmediate()) {
16370    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
16371      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
16372      if (IsUsingT32()) {
16373        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
16374        if (dt.Is(Untyped8) && (imm <= 15)) {
16375          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16376            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16377                       rm.Encode(5, 0) | (imm << 8));
16378            AdvanceIT();
16379            return;
16380          }
16381        }
16382        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
16383        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
16384            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16385          if (cond.Is(al) || AllowStronglyDiscouraged()) {
16386            uint32_t imm4 = imm / dt.GetSize();
16387            EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16388                       rm.Encode(5, 0) | (imm4 << 8));
16389            AdvanceIT();
16390            return;
16391          }
16392        }
16393      } else {
16394        // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
16395        if (dt.Is(Untyped8) && (imm <= 15)) {
16396          if (cond.Is(al)) {
16397            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16398                    rm.Encode(5, 0) | (imm << 8));
16399            return;
16400          }
16401        }
16402        // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
16403        if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
16404            (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16405          if (cond.Is(al)) {
16406            uint32_t imm4 = imm / dt.GetSize();
16407            EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16408                    rm.Encode(5, 0) | (imm4 << 8));
16409            return;
16410          }
16411        }
16412      }
16413    }
16414  }
16415  Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
16416}
16417
16418void Assembler::vfma(
16419    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16420  VIXL_ASSERT(AllowAssembler());
16421  CheckIT(cond);
16422  if (IsUsingT32()) {
16423    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
16424    if (dt.Is(F32)) {
16425      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16426        EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16427                   rm.Encode(5, 0));
16428        AdvanceIT();
16429        return;
16430      }
16431    }
16432    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
16433    if (dt.Is(F64)) {
16434      EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16435                 rm.Encode(5, 0));
16436      AdvanceIT();
16437      return;
16438    }
16439  } else {
16440    // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
16441    if (dt.Is(F32)) {
16442      if (cond.Is(al)) {
16443        EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16444                rm.Encode(5, 0));
16445        return;
16446      }
16447    }
16448    // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
16449    if (dt.Is(F64) && cond.IsNotNever()) {
16450      EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16451              rn.Encode(7, 16) | rm.Encode(5, 0));
16452      return;
16453    }
16454  }
16455  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16456}
16457
16458void Assembler::vfma(
16459    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16460  VIXL_ASSERT(AllowAssembler());
16461  CheckIT(cond);
16462  if (IsUsingT32()) {
16463    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
16464    if (dt.Is(F32)) {
16465      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16466        EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16467                   rm.Encode(5, 0));
16468        AdvanceIT();
16469        return;
16470      }
16471    }
16472  } else {
16473    // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
16474    if (dt.Is(F32)) {
16475      if (cond.Is(al)) {
16476        EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16477                rm.Encode(5, 0));
16478        return;
16479      }
16480    }
16481  }
16482  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16483}
16484
16485void Assembler::vfma(
16486    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16487  VIXL_ASSERT(AllowAssembler());
16488  CheckIT(cond);
16489  if (IsUsingT32()) {
16490    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
16491    if (dt.Is(F32)) {
16492      EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16493                 rm.Encode(5, 0));
16494      AdvanceIT();
16495      return;
16496    }
16497  } else {
16498    // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
16499    if (dt.Is(F32) && cond.IsNotNever()) {
16500      EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16501              rn.Encode(7, 16) | rm.Encode(5, 0));
16502      return;
16503    }
16504  }
16505  Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16506}
16507
16508void Assembler::vfms(
16509    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16510  VIXL_ASSERT(AllowAssembler());
16511  CheckIT(cond);
16512  if (IsUsingT32()) {
16513    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
16514    if (dt.Is(F32)) {
16515      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16516        EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16517                   rm.Encode(5, 0));
16518        AdvanceIT();
16519        return;
16520      }
16521    }
16522    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
16523    if (dt.Is(F64)) {
16524      EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16525                 rm.Encode(5, 0));
16526      AdvanceIT();
16527      return;
16528    }
16529  } else {
16530    // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
16531    if (dt.Is(F32)) {
16532      if (cond.Is(al)) {
16533        EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16534                rm.Encode(5, 0));
16535        return;
16536      }
16537    }
16538    // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
16539    if (dt.Is(F64) && cond.IsNotNever()) {
16540      EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16541              rn.Encode(7, 16) | rm.Encode(5, 0));
16542      return;
16543    }
16544  }
16545  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16546}
16547
16548void Assembler::vfms(
16549    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16550  VIXL_ASSERT(AllowAssembler());
16551  CheckIT(cond);
16552  if (IsUsingT32()) {
16553    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
16554    if (dt.Is(F32)) {
16555      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16556        EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16557                   rm.Encode(5, 0));
16558        AdvanceIT();
16559        return;
16560      }
16561    }
16562  } else {
16563    // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
16564    if (dt.Is(F32)) {
16565      if (cond.Is(al)) {
16566        EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16567                rm.Encode(5, 0));
16568        return;
16569      }
16570    }
16571  }
16572  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16573}
16574
16575void Assembler::vfms(
16576    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16577  VIXL_ASSERT(AllowAssembler());
16578  CheckIT(cond);
16579  if (IsUsingT32()) {
16580    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
16581    if (dt.Is(F32)) {
16582      EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16583                 rm.Encode(5, 0));
16584      AdvanceIT();
16585      return;
16586    }
16587  } else {
16588    // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
16589    if (dt.Is(F32) && cond.IsNotNever()) {
16590      EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16591              rn.Encode(7, 16) | rm.Encode(5, 0));
16592      return;
16593    }
16594  }
16595  Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16596}
16597
16598void Assembler::vfnma(
16599    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16600  VIXL_ASSERT(AllowAssembler());
16601  CheckIT(cond);
16602  if (IsUsingT32()) {
16603    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
16604    if (dt.Is(F32)) {
16605      EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16606                 rm.Encode(5, 0));
16607      AdvanceIT();
16608      return;
16609    }
16610  } else {
16611    // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
16612    if (dt.Is(F32) && cond.IsNotNever()) {
16613      EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16614              rn.Encode(7, 16) | rm.Encode(5, 0));
16615      return;
16616    }
16617  }
16618  Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
16619}
16620
16621void Assembler::vfnma(
16622    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16623  VIXL_ASSERT(AllowAssembler());
16624  CheckIT(cond);
16625  if (IsUsingT32()) {
16626    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
16627    if (dt.Is(F64)) {
16628      EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16629                 rm.Encode(5, 0));
16630      AdvanceIT();
16631      return;
16632    }
16633  } else {
16634    // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
16635    if (dt.Is(F64) && cond.IsNotNever()) {
16636      EmitA32(0x0e900b40U | (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::vfnms(
16645    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
16646  VIXL_ASSERT(AllowAssembler());
16647  CheckIT(cond);
16648  if (IsUsingT32()) {
16649    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
16650    if (dt.Is(F32)) {
16651      EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16652                 rm.Encode(5, 0));
16653      AdvanceIT();
16654      return;
16655    }
16656  } else {
16657    // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
16658    if (dt.Is(F32) && cond.IsNotNever()) {
16659      EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16660              rn.Encode(7, 16) | rm.Encode(5, 0));
16661      return;
16662    }
16663  }
16664  Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
16665}
16666
16667void Assembler::vfnms(
16668    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16669  VIXL_ASSERT(AllowAssembler());
16670  CheckIT(cond);
16671  if (IsUsingT32()) {
16672    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
16673    if (dt.Is(F64)) {
16674      EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16675                 rm.Encode(5, 0));
16676      AdvanceIT();
16677      return;
16678    }
16679  } else {
16680    // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
16681    if (dt.Is(F64) && cond.IsNotNever()) {
16682      EmitA32(0x0e900b00U | (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::vhadd(
16691    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16692  VIXL_ASSERT(AllowAssembler());
16693  CheckIT(cond);
16694  Dt_U_size_1 encoded_dt(dt);
16695  if (IsUsingT32()) {
16696    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
16697    if (encoded_dt.IsValid()) {
16698      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16699        EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16700                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16701                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16702        AdvanceIT();
16703        return;
16704      }
16705    }
16706  } else {
16707    // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
16708    if (encoded_dt.IsValid()) {
16709      if (cond.Is(al)) {
16710        EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16711                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16712                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16713        return;
16714      }
16715    }
16716  }
16717  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
16718}
16719
16720void Assembler::vhadd(
16721    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16722  VIXL_ASSERT(AllowAssembler());
16723  CheckIT(cond);
16724  Dt_U_size_1 encoded_dt(dt);
16725  if (IsUsingT32()) {
16726    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
16727    if (encoded_dt.IsValid()) {
16728      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16729        EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16730                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16731                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16732        AdvanceIT();
16733        return;
16734      }
16735    }
16736  } else {
16737    // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
16738    if (encoded_dt.IsValid()) {
16739      if (cond.Is(al)) {
16740        EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16741                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16742                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16743        return;
16744      }
16745    }
16746  }
16747  Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
16748}
16749
16750void Assembler::vhsub(
16751    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
16752  VIXL_ASSERT(AllowAssembler());
16753  CheckIT(cond);
16754  Dt_U_size_1 encoded_dt(dt);
16755  if (IsUsingT32()) {
16756    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
16757    if (encoded_dt.IsValid()) {
16758      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16759        EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16760                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16761                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16762        AdvanceIT();
16763        return;
16764      }
16765    }
16766  } else {
16767    // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
16768    if (encoded_dt.IsValid()) {
16769      if (cond.Is(al)) {
16770        EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16771                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16772                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16773        return;
16774      }
16775    }
16776  }
16777  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
16778}
16779
16780void Assembler::vhsub(
16781    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
16782  VIXL_ASSERT(AllowAssembler());
16783  CheckIT(cond);
16784  Dt_U_size_1 encoded_dt(dt);
16785  if (IsUsingT32()) {
16786    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
16787    if (encoded_dt.IsValid()) {
16788      if (cond.Is(al) || AllowStronglyDiscouraged()) {
16789        EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16790                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16791                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16792        AdvanceIT();
16793        return;
16794      }
16795    }
16796  } else {
16797    // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
16798    if (encoded_dt.IsValid()) {
16799      if (cond.Is(al)) {
16800        EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16801                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16802                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16803        return;
16804      }
16805    }
16806  }
16807  Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
16808}
16809
16810void Assembler::vld1(Condition cond,
16811                     DataType dt,
16812                     const NeonRegisterList& nreglist,
16813                     const AlignedMemOperand& operand) {
16814  VIXL_ASSERT(AllowAssembler());
16815  CheckIT(cond);
16816  if (operand.IsImmediateZero()) {
16817    Register rn = operand.GetBaseRegister();
16818    Alignment align = operand.GetAlignment();
16819    Dt_size_6 encoded_dt(dt);
16820    Dt_size_7 encoded_dt_2(dt);
16821    Align_align_1 encoded_align_1(align, nreglist);
16822    Align_a_1 encoded_align_2(align, dt);
16823    Align_index_align_1 encoded_align_3(align, nreglist, dt);
16824    if (IsUsingT32()) {
16825      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16826      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16827          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16828          operand.IsOffset() && encoded_align_1.IsValid() &&
16829          (!rn.IsPC() || AllowUnpredictable())) {
16830        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16831          const DRegister& first = nreglist.GetFirstDRegister();
16832          uint32_t len_encoding;
16833          switch (nreglist.GetLength()) {
16834            default:
16835              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16836            case 1:
16837              len_encoding = 0x7;
16838              break;
16839            case 2:
16840              len_encoding = 0xa;
16841              break;
16842            case 3:
16843              len_encoding = 0x6;
16844              break;
16845            case 4:
16846              len_encoding = 0x2;
16847              break;
16848          }
16849          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
16850                     (encoded_align_1.GetEncodingValue() << 4) |
16851                     first.Encode(22, 12) | (len_encoding << 8) |
16852                     (rn.GetCode() << 16));
16853          AdvanceIT();
16854          return;
16855        }
16856      }
16857      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16858      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16859          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16860          operand.IsPostIndex() && encoded_align_1.IsValid() &&
16861          (!rn.IsPC() || AllowUnpredictable())) {
16862        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16863          const DRegister& first = nreglist.GetFirstDRegister();
16864          uint32_t len_encoding;
16865          switch (nreglist.GetLength()) {
16866            default:
16867              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16868            case 1:
16869              len_encoding = 0x7;
16870              break;
16871            case 2:
16872              len_encoding = 0xa;
16873              break;
16874            case 3:
16875              len_encoding = 0x6;
16876              break;
16877            case 4:
16878              len_encoding = 0x2;
16879              break;
16880          }
16881          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
16882                     (encoded_align_1.GetEncodingValue() << 4) |
16883                     first.Encode(22, 12) | (len_encoding << 8) |
16884                     (rn.GetCode() << 16));
16885          AdvanceIT();
16886          return;
16887        }
16888      }
16889      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16890      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
16891          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
16892          operand.IsOffset() && encoded_align_2.IsValid() &&
16893          (!rn.IsPC() || AllowUnpredictable())) {
16894        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16895          const DRegister& first = nreglist.GetFirstDRegister();
16896          uint32_t len_encoding = nreglist.GetLength() - 1;
16897          EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
16898                     (encoded_align_2.GetEncodingValue() << 4) |
16899                     first.Encode(22, 12) | (len_encoding << 5) |
16900                     (rn.GetCode() << 16));
16901          AdvanceIT();
16902          return;
16903        }
16904      }
16905      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16906      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
16907          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
16908          operand.IsPostIndex() && encoded_align_2.IsValid() &&
16909          (!rn.IsPC() || AllowUnpredictable())) {
16910        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16911          const DRegister& first = nreglist.GetFirstDRegister();
16912          uint32_t len_encoding = nreglist.GetLength() - 1;
16913          EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
16914                     (encoded_align_2.GetEncodingValue() << 4) |
16915                     first.Encode(22, 12) | (len_encoding << 5) |
16916                     (rn.GetCode() << 16));
16917          AdvanceIT();
16918          return;
16919        }
16920      }
16921      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16922      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
16923          (nreglist.GetLength() == 1) && operand.IsOffset() &&
16924          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
16925        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16926          const DRegister& first = nreglist.GetFirstDRegister();
16927          EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
16928                     (encoded_align_3.GetEncodingValue() << 4) |
16929                     first.Encode(22, 12) | (rn.GetCode() << 16));
16930          AdvanceIT();
16931          return;
16932        }
16933      }
16934      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16935      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
16936          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
16937          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
16938        if (cond.Is(al) || AllowStronglyDiscouraged()) {
16939          const DRegister& first = nreglist.GetFirstDRegister();
16940          EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
16941                     (encoded_align_3.GetEncodingValue() << 4) |
16942                     first.Encode(22, 12) | (rn.GetCode() << 16));
16943          AdvanceIT();
16944          return;
16945        }
16946      }
16947    } else {
16948      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
16949      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16950          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16951          operand.IsOffset() && encoded_align_1.IsValid() &&
16952          (!rn.IsPC() || AllowUnpredictable())) {
16953        if (cond.Is(al)) {
16954          const DRegister& first = nreglist.GetFirstDRegister();
16955          uint32_t len_encoding;
16956          switch (nreglist.GetLength()) {
16957            default:
16958              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16959            case 1:
16960              len_encoding = 0x7;
16961              break;
16962            case 2:
16963              len_encoding = 0xa;
16964              break;
16965            case 3:
16966              len_encoding = 0x6;
16967              break;
16968            case 4:
16969              len_encoding = 0x2;
16970              break;
16971          }
16972          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
16973                  (encoded_align_1.GetEncodingValue() << 4) |
16974                  first.Encode(22, 12) | (len_encoding << 8) |
16975                  (rn.GetCode() << 16));
16976          return;
16977        }
16978      }
16979      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
16980      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16981          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16982          operand.IsPostIndex() && encoded_align_1.IsValid() &&
16983          (!rn.IsPC() || AllowUnpredictable())) {
16984        if (cond.Is(al)) {
16985          const DRegister& first = nreglist.GetFirstDRegister();
16986          uint32_t len_encoding;
16987          switch (nreglist.GetLength()) {
16988            default:
16989              VIXL_UNREACHABLE_OR_FALLTHROUGH();
16990            case 1:
16991              len_encoding = 0x7;
16992              break;
16993            case 2:
16994              len_encoding = 0xa;
16995              break;
16996            case 3:
16997              len_encoding = 0x6;
16998              break;
16999            case 4:
17000              len_encoding = 0x2;
17001              break;
17002          }
17003          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17004                  (encoded_align_1.GetEncodingValue() << 4) |
17005                  first.Encode(22, 12) | (len_encoding << 8) |
17006                  (rn.GetCode() << 16));
17007          return;
17008        }
17009      }
17010      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17011      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17012          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17013          operand.IsOffset() && encoded_align_2.IsValid() &&
17014          (!rn.IsPC() || AllowUnpredictable())) {
17015        if (cond.Is(al)) {
17016          const DRegister& first = nreglist.GetFirstDRegister();
17017          uint32_t len_encoding = nreglist.GetLength() - 1;
17018          EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
17019                  (encoded_align_2.GetEncodingValue() << 4) |
17020                  first.Encode(22, 12) | (len_encoding << 5) |
17021                  (rn.GetCode() << 16));
17022          return;
17023        }
17024      }
17025      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17026      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17027          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17028          operand.IsPostIndex() && encoded_align_2.IsValid() &&
17029          (!rn.IsPC() || AllowUnpredictable())) {
17030        if (cond.Is(al)) {
17031          const DRegister& first = nreglist.GetFirstDRegister();
17032          uint32_t len_encoding = nreglist.GetLength() - 1;
17033          EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
17034                  (encoded_align_2.GetEncodingValue() << 4) |
17035                  first.Encode(22, 12) | (len_encoding << 5) |
17036                  (rn.GetCode() << 16));
17037          return;
17038        }
17039      }
17040      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17041      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17042          (nreglist.GetLength() == 1) && operand.IsOffset() &&
17043          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
17044        if (cond.Is(al)) {
17045          const DRegister& first = nreglist.GetFirstDRegister();
17046          EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
17047                  (encoded_align_3.GetEncodingValue() << 4) |
17048                  first.Encode(22, 12) | (rn.GetCode() << 16));
17049          return;
17050        }
17051      }
17052      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17053      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17054          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
17055          encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
17056        if (cond.Is(al)) {
17057          const DRegister& first = nreglist.GetFirstDRegister();
17058          EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
17059                  (encoded_align_3.GetEncodingValue() << 4) |
17060                  first.Encode(22, 12) | (rn.GetCode() << 16));
17061          return;
17062        }
17063      }
17064    }
17065  }
17066  if (operand.IsPlainRegister()) {
17067    Register rn = operand.GetBaseRegister();
17068    Alignment align = operand.GetAlignment();
17069    Register rm = operand.GetOffsetRegister();
17070    Dt_size_6 encoded_dt(dt);
17071    Dt_size_7 encoded_dt_2(dt);
17072    Align_align_1 encoded_align_1(align, nreglist);
17073    Align_a_1 encoded_align_2(align, dt);
17074    Align_index_align_1 encoded_align_3(align, nreglist, dt);
17075    if (IsUsingT32()) {
17076      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17077      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17078          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17079          !rm.IsPC() && !rm.IsSP()) {
17080        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17081          const DRegister& first = nreglist.GetFirstDRegister();
17082          uint32_t len_encoding;
17083          switch (nreglist.GetLength()) {
17084            default:
17085              VIXL_UNREACHABLE_OR_FALLTHROUGH();
17086            case 1:
17087              len_encoding = 0x7;
17088              break;
17089            case 2:
17090              len_encoding = 0xa;
17091              break;
17092            case 3:
17093              len_encoding = 0x6;
17094              break;
17095            case 4:
17096              len_encoding = 0x2;
17097              break;
17098          }
17099          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17100                     (encoded_align_1.GetEncodingValue() << 4) |
17101                     first.Encode(22, 12) | (len_encoding << 8) |
17102                     (rn.GetCode() << 16) | rm.GetCode());
17103          AdvanceIT();
17104          return;
17105        }
17106      }
17107      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17108      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17109          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17110          !rm.IsPC() && !rm.IsSP()) {
17111        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17112          const DRegister& first = nreglist.GetFirstDRegister();
17113          uint32_t len_encoding = nreglist.GetLength() - 1;
17114          EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
17115                     (encoded_align_2.GetEncodingValue() << 4) |
17116                     first.Encode(22, 12) | (len_encoding << 5) |
17117                     (rn.GetCode() << 16) | rm.GetCode());
17118          AdvanceIT();
17119          return;
17120        }
17121      }
17122      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17123      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17124          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
17125        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17126          const DRegister& first = nreglist.GetFirstDRegister();
17127          EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
17128                     (encoded_align_3.GetEncodingValue() << 4) |
17129                     first.Encode(22, 12) | (rn.GetCode() << 16) |
17130                     rm.GetCode());
17131          AdvanceIT();
17132          return;
17133        }
17134      }
17135    } else {
17136      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17137      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17138          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17139          !rm.IsPC() && !rm.IsSP()) {
17140        if (cond.Is(al)) {
17141          const DRegister& first = nreglist.GetFirstDRegister();
17142          uint32_t len_encoding;
17143          switch (nreglist.GetLength()) {
17144            default:
17145              VIXL_UNREACHABLE_OR_FALLTHROUGH();
17146            case 1:
17147              len_encoding = 0x7;
17148              break;
17149            case 2:
17150              len_encoding = 0xa;
17151              break;
17152            case 3:
17153              len_encoding = 0x6;
17154              break;
17155            case 4:
17156              len_encoding = 0x2;
17157              break;
17158          }
17159          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17160                  (encoded_align_1.GetEncodingValue() << 4) |
17161                  first.Encode(22, 12) | (len_encoding << 8) |
17162                  (rn.GetCode() << 16) | rm.GetCode());
17163          return;
17164        }
17165      }
17166      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17167      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17168          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17169          !rm.IsPC() && !rm.IsSP()) {
17170        if (cond.Is(al)) {
17171          const DRegister& first = nreglist.GetFirstDRegister();
17172          uint32_t len_encoding = nreglist.GetLength() - 1;
17173          EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
17174                  (encoded_align_2.GetEncodingValue() << 4) |
17175                  first.Encode(22, 12) | (len_encoding << 5) |
17176                  (rn.GetCode() << 16) | rm.GetCode());
17177          return;
17178        }
17179      }
17180      // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17181      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17182          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
17183        if (cond.Is(al)) {
17184          const DRegister& first = nreglist.GetFirstDRegister();
17185          EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
17186                  (encoded_align_3.GetEncodingValue() << 4) |
17187                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17188          return;
17189        }
17190      }
17191    }
17192  }
17193  Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
17194}
17195
17196void Assembler::vld2(Condition cond,
17197                     DataType dt,
17198                     const NeonRegisterList& nreglist,
17199                     const AlignedMemOperand& operand) {
17200  VIXL_ASSERT(AllowAssembler());
17201  CheckIT(cond);
17202  if (operand.IsImmediateZero()) {
17203    Register rn = operand.GetBaseRegister();
17204    Alignment align = operand.GetAlignment();
17205    Dt_size_7 encoded_dt(dt);
17206    Align_align_2 encoded_align_1(align, nreglist);
17207    Align_a_2 encoded_align_2(align, dt);
17208    Align_index_align_2 encoded_align_3(align, nreglist, dt);
17209    if (IsUsingT32()) {
17210      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17211      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17212          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17213           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17214           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17215          operand.IsOffset() && encoded_align_1.IsValid() &&
17216          (!rn.IsPC() || AllowUnpredictable())) {
17217        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17218          const DRegister& first = nreglist.GetFirstDRegister();
17219          uint32_t len_encoding;
17220          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17221            len_encoding = 0x8;
17222          }
17223          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17224            len_encoding = 0x9;
17225          }
17226          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17227            len_encoding = 0x3;
17228          }
17229          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17230                     (encoded_align_1.GetEncodingValue() << 4) |
17231                     first.Encode(22, 12) | (len_encoding << 8) |
17232                     (rn.GetCode() << 16));
17233          AdvanceIT();
17234          return;
17235        }
17236      }
17237      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17238      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17239          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17240           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17241           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17242          operand.IsPostIndex() && encoded_align_1.IsValid() &&
17243          (!rn.IsPC() || AllowUnpredictable())) {
17244        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17245          const DRegister& first = nreglist.GetFirstDRegister();
17246          uint32_t len_encoding;
17247          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17248            len_encoding = 0x8;
17249          }
17250          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17251            len_encoding = 0x9;
17252          }
17253          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17254            len_encoding = 0x3;
17255          }
17256          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17257                     (encoded_align_1.GetEncodingValue() << 4) |
17258                     first.Encode(22, 12) | (len_encoding << 8) |
17259                     (rn.GetCode() << 16));
17260          AdvanceIT();
17261          return;
17262        }
17263      }
17264      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17265      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17266          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17267           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17268          operand.IsOffset() && encoded_align_2.IsValid() &&
17269          (!rn.IsPC() || AllowUnpredictable())) {
17270        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17271          const DRegister& first = nreglist.GetFirstDRegister();
17272          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17273          EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
17274                     (encoded_align_2.GetEncodingValue() << 4) |
17275                     first.Encode(22, 12) | (len_encoding << 5) |
17276                     (rn.GetCode() << 16));
17277          AdvanceIT();
17278          return;
17279        }
17280      }
17281      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17282      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17283          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17284           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17285          operand.IsPostIndex() && encoded_align_2.IsValid() &&
17286          (!rn.IsPC() || AllowUnpredictable())) {
17287        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17288          const DRegister& first = nreglist.GetFirstDRegister();
17289          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17290          EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
17291                     (encoded_align_2.GetEncodingValue() << 4) |
17292                     first.Encode(22, 12) | (len_encoding << 5) |
17293                     (rn.GetCode() << 16));
17294          AdvanceIT();
17295          return;
17296        }
17297      }
17298      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17299      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17300          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17301           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17302          operand.IsOffset() && encoded_align_3.IsValid() &&
17303          (!rn.IsPC() || AllowUnpredictable())) {
17304        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17305          const DRegister& first = nreglist.GetFirstDRegister();
17306          EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
17307                     (encoded_align_3.GetEncodingValue() << 4) |
17308                     first.Encode(22, 12) | (rn.GetCode() << 16));
17309          AdvanceIT();
17310          return;
17311        }
17312      }
17313      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17314      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17315          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17316           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17317          operand.IsPostIndex() && encoded_align_3.IsValid() &&
17318          (!rn.IsPC() || AllowUnpredictable())) {
17319        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17320          const DRegister& first = nreglist.GetFirstDRegister();
17321          EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
17322                     (encoded_align_3.GetEncodingValue() << 4) |
17323                     first.Encode(22, 12) | (rn.GetCode() << 16));
17324          AdvanceIT();
17325          return;
17326        }
17327      }
17328    } else {
17329      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17330      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17331          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17332           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17333           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17334          operand.IsOffset() && encoded_align_1.IsValid() &&
17335          (!rn.IsPC() || AllowUnpredictable())) {
17336        if (cond.Is(al)) {
17337          const DRegister& first = nreglist.GetFirstDRegister();
17338          uint32_t len_encoding;
17339          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17340            len_encoding = 0x8;
17341          }
17342          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17343            len_encoding = 0x9;
17344          }
17345          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17346            len_encoding = 0x3;
17347          }
17348          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
17349                  (encoded_align_1.GetEncodingValue() << 4) |
17350                  first.Encode(22, 12) | (len_encoding << 8) |
17351                  (rn.GetCode() << 16));
17352          return;
17353        }
17354      }
17355      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17356      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17357          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17358           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17359           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17360          operand.IsPostIndex() && encoded_align_1.IsValid() &&
17361          (!rn.IsPC() || AllowUnpredictable())) {
17362        if (cond.Is(al)) {
17363          const DRegister& first = nreglist.GetFirstDRegister();
17364          uint32_t len_encoding;
17365          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17366            len_encoding = 0x8;
17367          }
17368          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17369            len_encoding = 0x9;
17370          }
17371          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17372            len_encoding = 0x3;
17373          }
17374          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17375                  (encoded_align_1.GetEncodingValue() << 4) |
17376                  first.Encode(22, 12) | (len_encoding << 8) |
17377                  (rn.GetCode() << 16));
17378          return;
17379        }
17380      }
17381      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17382      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17383          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17384           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17385          operand.IsOffset() && encoded_align_2.IsValid() &&
17386          (!rn.IsPC() || AllowUnpredictable())) {
17387        if (cond.Is(al)) {
17388          const DRegister& first = nreglist.GetFirstDRegister();
17389          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17390          EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
17391                  (encoded_align_2.GetEncodingValue() << 4) |
17392                  first.Encode(22, 12) | (len_encoding << 5) |
17393                  (rn.GetCode() << 16));
17394          return;
17395        }
17396      }
17397      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17398      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17399          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17400           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17401          operand.IsPostIndex() && encoded_align_2.IsValid() &&
17402          (!rn.IsPC() || AllowUnpredictable())) {
17403        if (cond.Is(al)) {
17404          const DRegister& first = nreglist.GetFirstDRegister();
17405          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17406          EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
17407                  (encoded_align_2.GetEncodingValue() << 4) |
17408                  first.Encode(22, 12) | (len_encoding << 5) |
17409                  (rn.GetCode() << 16));
17410          return;
17411        }
17412      }
17413      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17414      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17415          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17416           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17417          operand.IsOffset() && encoded_align_3.IsValid() &&
17418          (!rn.IsPC() || AllowUnpredictable())) {
17419        if (cond.Is(al)) {
17420          const DRegister& first = nreglist.GetFirstDRegister();
17421          EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
17422                  (encoded_align_3.GetEncodingValue() << 4) |
17423                  first.Encode(22, 12) | (rn.GetCode() << 16));
17424          return;
17425        }
17426      }
17427      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17428      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17429          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17430           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17431          operand.IsPostIndex() && encoded_align_3.IsValid() &&
17432          (!rn.IsPC() || AllowUnpredictable())) {
17433        if (cond.Is(al)) {
17434          const DRegister& first = nreglist.GetFirstDRegister();
17435          EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
17436                  (encoded_align_3.GetEncodingValue() << 4) |
17437                  first.Encode(22, 12) | (rn.GetCode() << 16));
17438          return;
17439        }
17440      }
17441    }
17442  }
17443  if (operand.IsPlainRegister()) {
17444    Register rn = operand.GetBaseRegister();
17445    Alignment align = operand.GetAlignment();
17446    Register rm = operand.GetOffsetRegister();
17447    Dt_size_7 encoded_dt(dt);
17448    Align_align_2 encoded_align_1(align, nreglist);
17449    Align_a_2 encoded_align_2(align, dt);
17450    Align_index_align_2 encoded_align_3(align, nreglist, dt);
17451    if (IsUsingT32()) {
17452      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17453      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17454          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17455           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17456           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17457          !rm.IsPC() && !rm.IsSP()) {
17458        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17459          const DRegister& first = nreglist.GetFirstDRegister();
17460          uint32_t len_encoding;
17461          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17462            len_encoding = 0x8;
17463          }
17464          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17465            len_encoding = 0x9;
17466          }
17467          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17468            len_encoding = 0x3;
17469          }
17470          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17471                     (encoded_align_1.GetEncodingValue() << 4) |
17472                     first.Encode(22, 12) | (len_encoding << 8) |
17473                     (rn.GetCode() << 16) | rm.GetCode());
17474          AdvanceIT();
17475          return;
17476        }
17477      }
17478      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17479      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17480          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17481           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17482          !rm.IsPC() && !rm.IsSP()) {
17483        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17484          const DRegister& first = nreglist.GetFirstDRegister();
17485          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17486          EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
17487                     (encoded_align_2.GetEncodingValue() << 4) |
17488                     first.Encode(22, 12) | (len_encoding << 5) |
17489                     (rn.GetCode() << 16) | rm.GetCode());
17490          AdvanceIT();
17491          return;
17492        }
17493      }
17494      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17495      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17496          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17497           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17498          !rm.IsPC() && !rm.IsSP()) {
17499        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17500          const DRegister& first = nreglist.GetFirstDRegister();
17501          EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
17502                     (encoded_align_3.GetEncodingValue() << 4) |
17503                     first.Encode(22, 12) | (rn.GetCode() << 16) |
17504                     rm.GetCode());
17505          AdvanceIT();
17506          return;
17507        }
17508      }
17509    } else {
17510      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17511      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17512          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17513           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17514           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17515          !rm.IsPC() && !rm.IsSP()) {
17516        if (cond.Is(al)) {
17517          const DRegister& first = nreglist.GetFirstDRegister();
17518          uint32_t len_encoding;
17519          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17520            len_encoding = 0x8;
17521          }
17522          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17523            len_encoding = 0x9;
17524          }
17525          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17526            len_encoding = 0x3;
17527          }
17528          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17529                  (encoded_align_1.GetEncodingValue() << 4) |
17530                  first.Encode(22, 12) | (len_encoding << 8) |
17531                  (rn.GetCode() << 16) | rm.GetCode());
17532          return;
17533        }
17534      }
17535      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17536      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17537          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17538           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17539          !rm.IsPC() && !rm.IsSP()) {
17540        if (cond.Is(al)) {
17541          const DRegister& first = nreglist.GetFirstDRegister();
17542          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17543          EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
17544                  (encoded_align_2.GetEncodingValue() << 4) |
17545                  first.Encode(22, 12) | (len_encoding << 5) |
17546                  (rn.GetCode() << 16) | rm.GetCode());
17547          return;
17548        }
17549      }
17550      // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17551      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17552          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17553           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17554          !rm.IsPC() && !rm.IsSP()) {
17555        if (cond.Is(al)) {
17556          const DRegister& first = nreglist.GetFirstDRegister();
17557          EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
17558                  (encoded_align_3.GetEncodingValue() << 4) |
17559                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17560          return;
17561        }
17562      }
17563    }
17564  }
17565  Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
17566}
17567
17568void Assembler::vld3(Condition cond,
17569                     DataType dt,
17570                     const NeonRegisterList& nreglist,
17571                     const AlignedMemOperand& operand) {
17572  VIXL_ASSERT(AllowAssembler());
17573  CheckIT(cond);
17574  if (operand.IsImmediateZero()) {
17575    Register rn = operand.GetBaseRegister();
17576    Alignment align = operand.GetAlignment();
17577    Dt_size_7 encoded_dt(dt);
17578    Align_align_3 encoded_align_1(align);
17579    if (IsUsingT32()) {
17580      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17581      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17582          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17583           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17584          operand.IsOffset() && encoded_align_1.IsValid() &&
17585          (!rn.IsPC() || AllowUnpredictable())) {
17586        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17587          const DRegister& first = nreglist.GetFirstDRegister();
17588          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17589          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17590                     (encoded_align_1.GetEncodingValue() << 4) |
17591                     first.Encode(22, 12) | (len_encoding << 8) |
17592                     (rn.GetCode() << 16));
17593          AdvanceIT();
17594          return;
17595        }
17596      }
17597      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17598      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17599          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17600           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17601          operand.IsPostIndex() && encoded_align_1.IsValid() &&
17602          (!rn.IsPC() || AllowUnpredictable())) {
17603        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17604          const DRegister& first = nreglist.GetFirstDRegister();
17605          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17606          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17607                     (encoded_align_1.GetEncodingValue() << 4) |
17608                     first.Encode(22, 12) | (len_encoding << 8) |
17609                     (rn.GetCode() << 16));
17610          AdvanceIT();
17611          return;
17612        }
17613      }
17614    } else {
17615      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17616      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17617          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17618           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17619          operand.IsOffset() && encoded_align_1.IsValid() &&
17620          (!rn.IsPC() || AllowUnpredictable())) {
17621        if (cond.Is(al)) {
17622          const DRegister& first = nreglist.GetFirstDRegister();
17623          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17624          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
17625                  (encoded_align_1.GetEncodingValue() << 4) |
17626                  first.Encode(22, 12) | (len_encoding << 8) |
17627                  (rn.GetCode() << 16));
17628          return;
17629        }
17630      }
17631      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17632      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17633          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17634           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17635          operand.IsPostIndex() && encoded_align_1.IsValid() &&
17636          (!rn.IsPC() || AllowUnpredictable())) {
17637        if (cond.Is(al)) {
17638          const DRegister& first = nreglist.GetFirstDRegister();
17639          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17640          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17641                  (encoded_align_1.GetEncodingValue() << 4) |
17642                  first.Encode(22, 12) | (len_encoding << 8) |
17643                  (rn.GetCode() << 16));
17644          return;
17645        }
17646      }
17647    }
17648  }
17649  if (operand.IsPlainRegister()) {
17650    Register rn = operand.GetBaseRegister();
17651    Alignment align = operand.GetAlignment();
17652    Register rm = operand.GetOffsetRegister();
17653    Dt_size_7 encoded_dt(dt);
17654    Align_align_3 encoded_align_1(align);
17655    if (IsUsingT32()) {
17656      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17657      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17658          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17659           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17660          !rm.IsPC() && !rm.IsSP()) {
17661        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17662          const DRegister& first = nreglist.GetFirstDRegister();
17663          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17664          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17665                     (encoded_align_1.GetEncodingValue() << 4) |
17666                     first.Encode(22, 12) | (len_encoding << 8) |
17667                     (rn.GetCode() << 16) | rm.GetCode());
17668          AdvanceIT();
17669          return;
17670        }
17671      }
17672    } else {
17673      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17674      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17675          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17676           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17677          !rm.IsPC() && !rm.IsSP()) {
17678        if (cond.Is(al)) {
17679          const DRegister& first = nreglist.GetFirstDRegister();
17680          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17681          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17682                  (encoded_align_1.GetEncodingValue() << 4) |
17683                  first.Encode(22, 12) | (len_encoding << 8) |
17684                  (rn.GetCode() << 16) | rm.GetCode());
17685          return;
17686        }
17687      }
17688    }
17689  }
17690  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
17691}
17692
17693void Assembler::vld3(Condition cond,
17694                     DataType dt,
17695                     const NeonRegisterList& nreglist,
17696                     const MemOperand& operand) {
17697  VIXL_ASSERT(AllowAssembler());
17698  CheckIT(cond);
17699  if (operand.IsImmediateZero()) {
17700    Register rn = operand.GetBaseRegister();
17701    Dt_size_7 encoded_dt(dt);
17702    Index_1 encoded_align_1(nreglist, dt);
17703    if (IsUsingT32()) {
17704      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
17705      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17706          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17707           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17708          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
17709        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17710          const DRegister& first = nreglist.GetFirstDRegister();
17711          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17712          EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
17713                     first.Encode(22, 12) | (len_encoding << 5) |
17714                     (rn.GetCode() << 16));
17715          AdvanceIT();
17716          return;
17717        }
17718      }
17719      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
17720      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17721          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17722           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17723          operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
17724        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17725          const DRegister& first = nreglist.GetFirstDRegister();
17726          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17727          EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
17728                     first.Encode(22, 12) | (len_encoding << 5) |
17729                     (rn.GetCode() << 16));
17730          AdvanceIT();
17731          return;
17732        }
17733      }
17734      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
17735      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17736          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17737           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17738          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
17739        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17740          const DRegister& first = nreglist.GetFirstDRegister();
17741          EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
17742                     (encoded_align_1.GetEncodingValue() << 4) |
17743                     first.Encode(22, 12) | (rn.GetCode() << 16));
17744          AdvanceIT();
17745          return;
17746        }
17747      }
17748      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
17749      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17750          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17751           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17752          operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
17753        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17754          const DRegister& first = nreglist.GetFirstDRegister();
17755          EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
17756                     (encoded_align_1.GetEncodingValue() << 4) |
17757                     first.Encode(22, 12) | (rn.GetCode() << 16));
17758          AdvanceIT();
17759          return;
17760        }
17761      }
17762    } else {
17763      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
17764      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17765          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17766           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17767          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
17768        if (cond.Is(al)) {
17769          const DRegister& first = nreglist.GetFirstDRegister();
17770          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17771          EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
17772                  first.Encode(22, 12) | (len_encoding << 5) |
17773                  (rn.GetCode() << 16));
17774          return;
17775        }
17776      }
17777      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
17778      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17779          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17780           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17781          operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
17782        if (cond.Is(al)) {
17783          const DRegister& first = nreglist.GetFirstDRegister();
17784          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17785          EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
17786                  first.Encode(22, 12) | (len_encoding << 5) |
17787                  (rn.GetCode() << 16));
17788          return;
17789        }
17790      }
17791      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
17792      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17793          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17794           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17795          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
17796        if (cond.Is(al)) {
17797          const DRegister& first = nreglist.GetFirstDRegister();
17798          EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
17799                  (encoded_align_1.GetEncodingValue() << 4) |
17800                  first.Encode(22, 12) | (rn.GetCode() << 16));
17801          return;
17802        }
17803      }
17804      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
17805      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17806          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17807           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17808          operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
17809        if (cond.Is(al)) {
17810          const DRegister& first = nreglist.GetFirstDRegister();
17811          EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
17812                  (encoded_align_1.GetEncodingValue() << 4) |
17813                  first.Encode(22, 12) | (rn.GetCode() << 16));
17814          return;
17815        }
17816      }
17817    }
17818  }
17819  if (operand.IsPlainRegister()) {
17820    Register rn = operand.GetBaseRegister();
17821    Sign sign = operand.GetSign();
17822    Register rm = operand.GetOffsetRegister();
17823    Dt_size_7 encoded_dt(dt);
17824    Index_1 encoded_align_1(nreglist, dt);
17825    if (IsUsingT32()) {
17826      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
17827      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17828          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17829           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17830          sign.IsPlus() && operand.IsPostIndex()) {
17831        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17832          const DRegister& first = nreglist.GetFirstDRegister();
17833          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17834          EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
17835                     first.Encode(22, 12) | (len_encoding << 5) |
17836                     (rn.GetCode() << 16) | rm.GetCode());
17837          AdvanceIT();
17838          return;
17839        }
17840      }
17841      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
17842      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17843          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17844           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17845          sign.IsPlus() && operand.IsPostIndex()) {
17846        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17847          const DRegister& first = nreglist.GetFirstDRegister();
17848          EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
17849                     (encoded_align_1.GetEncodingValue() << 4) |
17850                     first.Encode(22, 12) | (rn.GetCode() << 16) |
17851                     rm.GetCode());
17852          AdvanceIT();
17853          return;
17854        }
17855      }
17856    } else {
17857      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
17858      if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17859          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17860           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17861          sign.IsPlus() && operand.IsPostIndex()) {
17862        if (cond.Is(al)) {
17863          const DRegister& first = nreglist.GetFirstDRegister();
17864          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17865          EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
17866                  first.Encode(22, 12) | (len_encoding << 5) |
17867                  (rn.GetCode() << 16) | rm.GetCode());
17868          return;
17869        }
17870      }
17871      // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
17872      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17873          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17874           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17875          sign.IsPlus() && operand.IsPostIndex()) {
17876        if (cond.Is(al)) {
17877          const DRegister& first = nreglist.GetFirstDRegister();
17878          EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
17879                  (encoded_align_1.GetEncodingValue() << 4) |
17880                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17881          return;
17882        }
17883      }
17884    }
17885  }
17886  Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
17887}
17888
17889void Assembler::vld4(Condition cond,
17890                     DataType dt,
17891                     const NeonRegisterList& nreglist,
17892                     const AlignedMemOperand& operand) {
17893  VIXL_ASSERT(AllowAssembler());
17894  CheckIT(cond);
17895  if (operand.IsImmediateZero()) {
17896    Register rn = operand.GetBaseRegister();
17897    Alignment align = operand.GetAlignment();
17898    Dt_size_7 encoded_dt(dt);
17899    Dt_size_8 encoded_dt_2(dt, align);
17900    Align_align_4 encoded_align_1(align);
17901    Align_a_3 encoded_align_2(align, dt);
17902    Align_index_align_3 encoded_align_3(align, nreglist, dt);
17903    if (IsUsingT32()) {
17904      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17905      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17906          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17907           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17908          operand.IsOffset() && encoded_align_1.IsValid() &&
17909          (!rn.IsPC() || AllowUnpredictable())) {
17910        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17911          const DRegister& first = nreglist.GetFirstDRegister();
17912          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17913          EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17914                     (encoded_align_1.GetEncodingValue() << 4) |
17915                     first.Encode(22, 12) | (len_encoding << 8) |
17916                     (rn.GetCode() << 16));
17917          AdvanceIT();
17918          return;
17919        }
17920      }
17921      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17922      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17923          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17924           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17925          operand.IsPostIndex() && encoded_align_1.IsValid() &&
17926          (!rn.IsPC() || AllowUnpredictable())) {
17927        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17928          const DRegister& first = nreglist.GetFirstDRegister();
17929          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17930          EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17931                     (encoded_align_1.GetEncodingValue() << 4) |
17932                     first.Encode(22, 12) | (len_encoding << 8) |
17933                     (rn.GetCode() << 16));
17934          AdvanceIT();
17935          return;
17936        }
17937      }
17938      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17939      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17940          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17941           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17942          operand.IsOffset() && encoded_align_2.IsValid() &&
17943          (!rn.IsPC() || AllowUnpredictable())) {
17944        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17945          const DRegister& first = nreglist.GetFirstDRegister();
17946          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17947          EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
17948                     (encoded_align_2.GetEncodingValue() << 4) |
17949                     first.Encode(22, 12) | (len_encoding << 5) |
17950                     (rn.GetCode() << 16));
17951          AdvanceIT();
17952          return;
17953        }
17954      }
17955      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17956      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17957          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17958           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17959          operand.IsPostIndex() && encoded_align_2.IsValid() &&
17960          (!rn.IsPC() || AllowUnpredictable())) {
17961        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17962          const DRegister& first = nreglist.GetFirstDRegister();
17963          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17964          EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
17965                     (encoded_align_2.GetEncodingValue() << 4) |
17966                     first.Encode(22, 12) | (len_encoding << 5) |
17967                     (rn.GetCode() << 16));
17968          AdvanceIT();
17969          return;
17970        }
17971      }
17972      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17973      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17974          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17975           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17976          operand.IsOffset() && encoded_align_3.IsValid() &&
17977          (!rn.IsPC() || AllowUnpredictable())) {
17978        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17979          const DRegister& first = nreglist.GetFirstDRegister();
17980          EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
17981                     (encoded_align_3.GetEncodingValue() << 4) |
17982                     first.Encode(22, 12) | (rn.GetCode() << 16));
17983          AdvanceIT();
17984          return;
17985        }
17986      }
17987      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17988      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17989          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17990           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17991          operand.IsPostIndex() && encoded_align_3.IsValid() &&
17992          (!rn.IsPC() || AllowUnpredictable())) {
17993        if (cond.Is(al) || AllowStronglyDiscouraged()) {
17994          const DRegister& first = nreglist.GetFirstDRegister();
17995          EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
17996                     (encoded_align_3.GetEncodingValue() << 4) |
17997                     first.Encode(22, 12) | (rn.GetCode() << 16));
17998          AdvanceIT();
17999          return;
18000        }
18001      }
18002    } else {
18003      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18004      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18005          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18006           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18007          operand.IsOffset() && encoded_align_1.IsValid() &&
18008          (!rn.IsPC() || AllowUnpredictable())) {
18009        if (cond.Is(al)) {
18010          const DRegister& first = nreglist.GetFirstDRegister();
18011          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18012          EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18013                  (encoded_align_1.GetEncodingValue() << 4) |
18014                  first.Encode(22, 12) | (len_encoding << 8) |
18015                  (rn.GetCode() << 16));
18016          return;
18017        }
18018      }
18019      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18020      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18021          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18022           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18023          operand.IsPostIndex() && encoded_align_1.IsValid() &&
18024          (!rn.IsPC() || AllowUnpredictable())) {
18025        if (cond.Is(al)) {
18026          const DRegister& first = nreglist.GetFirstDRegister();
18027          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18028          EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18029                  (encoded_align_1.GetEncodingValue() << 4) |
18030                  first.Encode(22, 12) | (len_encoding << 8) |
18031                  (rn.GetCode() << 16));
18032          return;
18033        }
18034      }
18035      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18036      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18037          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18038           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18039          operand.IsOffset() && encoded_align_2.IsValid() &&
18040          (!rn.IsPC() || AllowUnpredictable())) {
18041        if (cond.Is(al)) {
18042          const DRegister& first = nreglist.GetFirstDRegister();
18043          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18044          EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18045                  (encoded_align_2.GetEncodingValue() << 4) |
18046                  first.Encode(22, 12) | (len_encoding << 5) |
18047                  (rn.GetCode() << 16));
18048          return;
18049        }
18050      }
18051      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18052      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18053          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18054           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18055          operand.IsPostIndex() && encoded_align_2.IsValid() &&
18056          (!rn.IsPC() || AllowUnpredictable())) {
18057        if (cond.Is(al)) {
18058          const DRegister& first = nreglist.GetFirstDRegister();
18059          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18060          EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18061                  (encoded_align_2.GetEncodingValue() << 4) |
18062                  first.Encode(22, 12) | (len_encoding << 5) |
18063                  (rn.GetCode() << 16));
18064          return;
18065        }
18066      }
18067      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18068      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18069          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18070           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18071          operand.IsOffset() && encoded_align_3.IsValid() &&
18072          (!rn.IsPC() || AllowUnpredictable())) {
18073        if (cond.Is(al)) {
18074          const DRegister& first = nreglist.GetFirstDRegister();
18075          EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
18076                  (encoded_align_3.GetEncodingValue() << 4) |
18077                  first.Encode(22, 12) | (rn.GetCode() << 16));
18078          return;
18079        }
18080      }
18081      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18082      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18083          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18084           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18085          operand.IsPostIndex() && encoded_align_3.IsValid() &&
18086          (!rn.IsPC() || AllowUnpredictable())) {
18087        if (cond.Is(al)) {
18088          const DRegister& first = nreglist.GetFirstDRegister();
18089          EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
18090                  (encoded_align_3.GetEncodingValue() << 4) |
18091                  first.Encode(22, 12) | (rn.GetCode() << 16));
18092          return;
18093        }
18094      }
18095    }
18096  }
18097  if (operand.IsPlainRegister()) {
18098    Register rn = operand.GetBaseRegister();
18099    Alignment align = operand.GetAlignment();
18100    Register rm = operand.GetOffsetRegister();
18101    Dt_size_7 encoded_dt(dt);
18102    Dt_size_8 encoded_dt_2(dt, align);
18103    Align_align_4 encoded_align_1(align);
18104    Align_a_3 encoded_align_2(align, dt);
18105    Align_index_align_3 encoded_align_3(align, nreglist, dt);
18106    if (IsUsingT32()) {
18107      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18108      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18109          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18110           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18111          !rm.IsPC() && !rm.IsSP()) {
18112        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18113          const DRegister& first = nreglist.GetFirstDRegister();
18114          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18115          EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18116                     (encoded_align_1.GetEncodingValue() << 4) |
18117                     first.Encode(22, 12) | (len_encoding << 8) |
18118                     (rn.GetCode() << 16) | rm.GetCode());
18119          AdvanceIT();
18120          return;
18121        }
18122      }
18123      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18124      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18125          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18126           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18127          !rm.IsPC() && !rm.IsSP()) {
18128        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18129          const DRegister& first = nreglist.GetFirstDRegister();
18130          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18131          EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
18132                     (encoded_align_2.GetEncodingValue() << 4) |
18133                     first.Encode(22, 12) | (len_encoding << 5) |
18134                     (rn.GetCode() << 16) | rm.GetCode());
18135          AdvanceIT();
18136          return;
18137        }
18138      }
18139      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18140      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18141          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18142           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18143          !rm.IsPC() && !rm.IsSP()) {
18144        if (cond.Is(al) || AllowStronglyDiscouraged()) {
18145          const DRegister& first = nreglist.GetFirstDRegister();
18146          EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
18147                     (encoded_align_3.GetEncodingValue() << 4) |
18148                     first.Encode(22, 12) | (rn.GetCode() << 16) |
18149                     rm.GetCode());
18150          AdvanceIT();
18151          return;
18152        }
18153      }
18154    } else {
18155      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18156      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18157          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18158           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18159          !rm.IsPC() && !rm.IsSP()) {
18160        if (cond.Is(al)) {
18161          const DRegister& first = nreglist.GetFirstDRegister();
18162          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18163          EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18164                  (encoded_align_1.GetEncodingValue() << 4) |
18165                  first.Encode(22, 12) | (len_encoding << 8) |
18166                  (rn.GetCode() << 16) | rm.GetCode());
18167          return;
18168        }
18169      }
18170      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18171      if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18172          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18173           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18174          !rm.IsPC() && !rm.IsSP()) {
18175        if (cond.Is(al)) {
18176          const DRegister& first = nreglist.GetFirstDRegister();
18177          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18178          EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
18179                  (encoded_align_2.GetEncodingValue() << 4) |
18180                  first.Encode(22, 12) | (len_encoding << 5) |
18181                  (rn.GetCode() << 16) | rm.GetCode());
18182          return;
18183        }
18184      }
18185      // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18186      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18187          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18188           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18189          !rm.IsPC() && !rm.IsSP()) {
18190        if (cond.Is(al)) {
18191          const DRegister& first = nreglist.GetFirstDRegister();
18192          EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
18193                  (encoded_align_3.GetEncodingValue() << 4) |
18194                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18195          return;
18196        }
18197      }
18198    }
18199  }
18200  Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
18201}
18202
18203void Assembler::vldm(Condition cond,
18204                     DataType dt,
18205                     Register rn,
18206                     WriteBack write_back,
18207                     DRegisterList dreglist) {
18208  VIXL_ASSERT(AllowAssembler());
18209  CheckIT(cond);
18210  USE(dt);
18211  if (IsUsingT32()) {
18212    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
18213    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
18214      const DRegister& dreg = dreglist.GetFirstDRegister();
18215      unsigned len = dreglist.GetLength() * 2;
18216      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
18217                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18218                 (len & 0xff));
18219      AdvanceIT();
18220      return;
18221    }
18222  } else {
18223    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
18224    if (cond.IsNotNever() &&
18225        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
18226      const DRegister& dreg = dreglist.GetFirstDRegister();
18227      unsigned len = dreglist.GetLength() * 2;
18228      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18229              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18230              (len & 0xff));
18231      return;
18232    }
18233  }
18234  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
18235}
18236
18237void Assembler::vldm(Condition cond,
18238                     DataType dt,
18239                     Register rn,
18240                     WriteBack write_back,
18241                     SRegisterList sreglist) {
18242  VIXL_ASSERT(AllowAssembler());
18243  CheckIT(cond);
18244  USE(dt);
18245  if (IsUsingT32()) {
18246    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
18247    const SRegister& sreg = sreglist.GetFirstSRegister();
18248    unsigned len = sreglist.GetLength();
18249    EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
18250               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18251               (len & 0xff));
18252    AdvanceIT();
18253    return;
18254  } else {
18255    // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
18256    if (cond.IsNotNever()) {
18257      const SRegister& sreg = sreglist.GetFirstSRegister();
18258      unsigned len = sreglist.GetLength();
18259      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18260              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18261              (len & 0xff));
18262      return;
18263    }
18264  }
18265  Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
18266}
18267
18268void Assembler::vldmdb(Condition cond,
18269                       DataType dt,
18270                       Register rn,
18271                       WriteBack write_back,
18272                       DRegisterList dreglist) {
18273  VIXL_ASSERT(AllowAssembler());
18274  CheckIT(cond);
18275  USE(dt);
18276  if (IsUsingT32()) {
18277    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
18278    if (write_back.DoesWriteBack() &&
18279        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
18280      const DRegister& dreg = dreglist.GetFirstDRegister();
18281      unsigned len = dreglist.GetLength() * 2;
18282      EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
18283                 (len & 0xff));
18284      AdvanceIT();
18285      return;
18286    }
18287  } else {
18288    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
18289    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
18290        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
18291      const DRegister& dreg = dreglist.GetFirstDRegister();
18292      unsigned len = dreglist.GetLength() * 2;
18293      EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18294              dreg.Encode(22, 12) | (len & 0xff));
18295      return;
18296    }
18297  }
18298  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
18299}
18300
18301void Assembler::vldmdb(Condition cond,
18302                       DataType dt,
18303                       Register rn,
18304                       WriteBack write_back,
18305                       SRegisterList sreglist) {
18306  VIXL_ASSERT(AllowAssembler());
18307  CheckIT(cond);
18308  USE(dt);
18309  if (IsUsingT32()) {
18310    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
18311    if (write_back.DoesWriteBack()) {
18312      const SRegister& sreg = sreglist.GetFirstSRegister();
18313      unsigned len = sreglist.GetLength();
18314      EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
18315                 (len & 0xff));
18316      AdvanceIT();
18317      return;
18318    }
18319  } else {
18320    // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
18321    if (write_back.DoesWriteBack() && cond.IsNotNever()) {
18322      const SRegister& sreg = sreglist.GetFirstSRegister();
18323      unsigned len = sreglist.GetLength();
18324      EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18325              sreg.Encode(22, 12) | (len & 0xff));
18326      return;
18327    }
18328  }
18329  Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
18330}
18331
18332void Assembler::vldmia(Condition cond,
18333                       DataType dt,
18334                       Register rn,
18335                       WriteBack write_back,
18336                       DRegisterList dreglist) {
18337  VIXL_ASSERT(AllowAssembler());
18338  CheckIT(cond);
18339  USE(dt);
18340  if (IsUsingT32()) {
18341    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
18342    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
18343      const DRegister& dreg = dreglist.GetFirstDRegister();
18344      unsigned len = dreglist.GetLength() * 2;
18345      EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
18346                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18347                 (len & 0xff));
18348      AdvanceIT();
18349      return;
18350    }
18351  } else {
18352    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
18353    if (cond.IsNotNever() &&
18354        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
18355      const DRegister& dreg = dreglist.GetFirstDRegister();
18356      unsigned len = dreglist.GetLength() * 2;
18357      EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18358              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18359              (len & 0xff));
18360      return;
18361    }
18362  }
18363  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
18364}
18365
18366void Assembler::vldmia(Condition cond,
18367                       DataType dt,
18368                       Register rn,
18369                       WriteBack write_back,
18370                       SRegisterList sreglist) {
18371  VIXL_ASSERT(AllowAssembler());
18372  CheckIT(cond);
18373  USE(dt);
18374  if (IsUsingT32()) {
18375    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
18376    const SRegister& sreg = sreglist.GetFirstSRegister();
18377    unsigned len = sreglist.GetLength();
18378    EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
18379               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18380               (len & 0xff));
18381    AdvanceIT();
18382    return;
18383  } else {
18384    // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
18385    if (cond.IsNotNever()) {
18386      const SRegister& sreg = sreglist.GetFirstSRegister();
18387      unsigned len = sreglist.GetLength();
18388      EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18389              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18390              (len & 0xff));
18391      return;
18392    }
18393  }
18394  Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
18395}
18396
18397void Assembler::vldr(Condition cond, DataType dt, DRegister rd, Label* label) {
18398  VIXL_ASSERT(AllowAssembler());
18399  CheckIT(cond);
18400  Label::Offset offset =
18401      label->IsBound()
18402          ? label->GetLocation() -
18403                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
18404          : 0;
18405  if (IsUsingT32()) {
18406    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
18407    if (dt.IsNoneOr(Untyped64) &&
18408        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18409          ((offset & 0x3) == 0)) ||
18410         !label->IsBound())) {
18411      static class EmitOp : public Label::LabelEmitOperator {
18412       public:
18413        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18414        virtual uint32_t Encode(uint32_t instr,
18415                                Label::Offset pc,
18416                                const Label* label) const VIXL_OVERRIDE {
18417          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18418          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18419                      ((offset & 0x3) == 0));
18420          int32_t target = offset >> 2;
18421          uint32_t U = (target >= 0) && !label->IsMinusZero();
18422          target = abs(target) | (U << 8);
18423          return instr | (target & 0xff) | ((target & 0x100) << 15);
18424        }
18425      } immop;
18426      EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12), label, immop));
18427      AdvanceIT();
18428      return;
18429    }
18430  } else {
18431    // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
18432    if (dt.IsNoneOr(Untyped64) &&
18433        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18434          ((offset & 0x3) == 0)) ||
18435         !label->IsBound()) &&
18436        cond.IsNotNever()) {
18437      static class EmitOp : public Label::LabelEmitOperator {
18438       public:
18439        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18440        virtual uint32_t Encode(uint32_t instr,
18441                                Label::Offset pc,
18442                                const Label* label) const VIXL_OVERRIDE {
18443          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18444          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18445                      ((offset & 0x3) == 0));
18446          int32_t target = offset >> 2;
18447          uint32_t U = (target >= 0) && !label->IsMinusZero();
18448          target = abs(target) | (U << 8);
18449          return instr | (target & 0xff) | ((target & 0x100) << 15);
18450        }
18451      } immop;
18452      EmitA32(
18453          Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
18454               label,
18455               immop));
18456      return;
18457    }
18458  }
18459  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, label);
18460}
18461
18462void Assembler::vldr(Condition cond,
18463                     DataType dt,
18464                     DRegister rd,
18465                     const MemOperand& operand) {
18466  VIXL_ASSERT(AllowAssembler());
18467  CheckIT(cond);
18468  if (operand.IsImmediate()) {
18469    Register rn = operand.GetBaseRegister();
18470    int32_t offset = operand.GetOffsetImmediate();
18471    if (IsUsingT32()) {
18472      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
18473      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18474          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
18475        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18476        uint32_t offset_ = abs(offset) >> 2;
18477        EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
18478        AdvanceIT();
18479        return;
18480      }
18481      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
18482      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18483          ((offset % 4) == 0) && operand.IsOffset() &&
18484          ((rn.GetCode() & 0xf) != 0xf)) {
18485        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18486        uint32_t offset_ = abs(offset) >> 2;
18487        EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
18488                   offset_ | (sign << 23));
18489        AdvanceIT();
18490        return;
18491      }
18492    } else {
18493      // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
18494      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18495          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
18496          cond.IsNotNever()) {
18497        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18498        uint32_t offset_ = abs(offset) >> 2;
18499        EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18500                offset_ | (sign << 23));
18501        return;
18502      }
18503      // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
18504      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18505          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
18506          ((rn.GetCode() & 0xf) != 0xf)) {
18507        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18508        uint32_t offset_ = abs(offset) >> 2;
18509        EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18510                (rn.GetCode() << 16) | offset_ | (sign << 23));
18511        return;
18512      }
18513    }
18514  }
18515  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
18516}
18517
18518void Assembler::vldr(Condition cond, DataType dt, SRegister rd, Label* label) {
18519  VIXL_ASSERT(AllowAssembler());
18520  CheckIT(cond);
18521  Label::Offset offset =
18522      label->IsBound()
18523          ? label->GetLocation() -
18524                AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
18525          : 0;
18526  if (IsUsingT32()) {
18527    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
18528    if (dt.IsNoneOr(Untyped32) &&
18529        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18530          ((offset & 0x3) == 0)) ||
18531         !label->IsBound())) {
18532      static class EmitOp : public Label::LabelEmitOperator {
18533       public:
18534        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18535        virtual uint32_t Encode(uint32_t instr,
18536                                Label::Offset pc,
18537                                const Label* label) const VIXL_OVERRIDE {
18538          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18539          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18540                      ((offset & 0x3) == 0));
18541          int32_t target = offset >> 2;
18542          uint32_t U = (target >= 0) && !label->IsMinusZero();
18543          target = abs(target) | (U << 8);
18544          return instr | (target & 0xff) | ((target & 0x100) << 15);
18545        }
18546      } immop;
18547      EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12), label, immop));
18548      AdvanceIT();
18549      return;
18550    }
18551  } else {
18552    // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
18553    if (dt.IsNoneOr(Untyped32) &&
18554        ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18555          ((offset & 0x3) == 0)) ||
18556         !label->IsBound()) &&
18557        cond.IsNotNever()) {
18558      static class EmitOp : public Label::LabelEmitOperator {
18559       public:
18560        EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
18561        virtual uint32_t Encode(uint32_t instr,
18562                                Label::Offset pc,
18563                                const Label* label) const VIXL_OVERRIDE {
18564          Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18565          VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18566                      ((offset & 0x3) == 0));
18567          int32_t target = offset >> 2;
18568          uint32_t U = (target >= 0) && !label->IsMinusZero();
18569          target = abs(target) | (U << 8);
18570          return instr | (target & 0xff) | ((target & 0x100) << 15);
18571        }
18572      } immop;
18573      EmitA32(
18574          Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
18575               label,
18576               immop));
18577      return;
18578    }
18579  }
18580  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, label);
18581}
18582
18583void Assembler::vldr(Condition cond,
18584                     DataType dt,
18585                     SRegister rd,
18586                     const MemOperand& operand) {
18587  VIXL_ASSERT(AllowAssembler());
18588  CheckIT(cond);
18589  if (operand.IsImmediate()) {
18590    Register rn = operand.GetBaseRegister();
18591    int32_t offset = operand.GetOffsetImmediate();
18592    if (IsUsingT32()) {
18593      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
18594      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18595          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
18596        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18597        uint32_t offset_ = abs(offset) >> 2;
18598        EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
18599        AdvanceIT();
18600        return;
18601      }
18602      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
18603      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18604          ((offset % 4) == 0) && operand.IsOffset() &&
18605          ((rn.GetCode() & 0xf) != 0xf)) {
18606        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18607        uint32_t offset_ = abs(offset) >> 2;
18608        EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
18609                   offset_ | (sign << 23));
18610        AdvanceIT();
18611        return;
18612      }
18613    } else {
18614      // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
18615      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18616          ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
18617          cond.IsNotNever()) {
18618        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18619        uint32_t offset_ = abs(offset) >> 2;
18620        EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18621                offset_ | (sign << 23));
18622        return;
18623      }
18624      // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
18625      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18626          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
18627          ((rn.GetCode() & 0xf) != 0xf)) {
18628        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18629        uint32_t offset_ = abs(offset) >> 2;
18630        EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18631                (rn.GetCode() << 16) | offset_ | (sign << 23));
18632        return;
18633      }
18634    }
18635  }
18636  Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
18637}
18638
18639void Assembler::vmax(
18640    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18641  VIXL_ASSERT(AllowAssembler());
18642  CheckIT(cond);
18643  Dt_U_size_1 encoded_dt(dt);
18644  if (IsUsingT32()) {
18645    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
18646    if (dt.Is(F32)) {
18647      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18648        EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18649                   rm.Encode(5, 0));
18650        AdvanceIT();
18651        return;
18652      }
18653    }
18654    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
18655    if (encoded_dt.IsValid()) {
18656      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18657        EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18658                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18659                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18660        AdvanceIT();
18661        return;
18662      }
18663    }
18664  } else {
18665    // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
18666    if (dt.Is(F32)) {
18667      if (cond.Is(al)) {
18668        EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18669                rm.Encode(5, 0));
18670        return;
18671      }
18672    }
18673    // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
18674    if (encoded_dt.IsValid()) {
18675      if (cond.Is(al)) {
18676        EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18677                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18678                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18679        return;
18680      }
18681    }
18682  }
18683  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
18684}
18685
18686void Assembler::vmax(
18687    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18688  VIXL_ASSERT(AllowAssembler());
18689  CheckIT(cond);
18690  Dt_U_size_1 encoded_dt(dt);
18691  if (IsUsingT32()) {
18692    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
18693    if (dt.Is(F32)) {
18694      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18695        EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18696                   rm.Encode(5, 0));
18697        AdvanceIT();
18698        return;
18699      }
18700    }
18701    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
18702    if (encoded_dt.IsValid()) {
18703      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18704        EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18705                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18706                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18707        AdvanceIT();
18708        return;
18709      }
18710    }
18711  } else {
18712    // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
18713    if (dt.Is(F32)) {
18714      if (cond.Is(al)) {
18715        EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18716                rm.Encode(5, 0));
18717        return;
18718      }
18719    }
18720    // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
18721    if (encoded_dt.IsValid()) {
18722      if (cond.Is(al)) {
18723        EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18724                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18725                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18726        return;
18727      }
18728    }
18729  }
18730  Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
18731}
18732
18733void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18734  VIXL_ASSERT(AllowAssembler());
18735  CheckIT(al);
18736  if (IsUsingT32()) {
18737    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
18738    if (OutsideITBlock() && dt.Is(F32)) {
18739      EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18740                 rm.Encode(5, 0));
18741      AdvanceIT();
18742      return;
18743    }
18744    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
18745    if (OutsideITBlock() && dt.Is(F64)) {
18746      EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18747                 rm.Encode(5, 0));
18748      AdvanceIT();
18749      return;
18750    }
18751  } else {
18752    // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
18753    if (dt.Is(F32)) {
18754      EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18755              rm.Encode(5, 0));
18756      return;
18757    }
18758    // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
18759    if (dt.Is(F64)) {
18760      EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18761              rm.Encode(5, 0));
18762      return;
18763    }
18764  }
18765  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18766}
18767
18768void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18769  VIXL_ASSERT(AllowAssembler());
18770  CheckIT(al);
18771  if (IsUsingT32()) {
18772    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
18773    if (OutsideITBlock() && dt.Is(F32)) {
18774      EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18775                 rm.Encode(5, 0));
18776      AdvanceIT();
18777      return;
18778    }
18779  } else {
18780    // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
18781    if (dt.Is(F32)) {
18782      EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18783              rm.Encode(5, 0));
18784      return;
18785    }
18786  }
18787  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18788}
18789
18790void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
18791  VIXL_ASSERT(AllowAssembler());
18792  CheckIT(al);
18793  if (IsUsingT32()) {
18794    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
18795    if (OutsideITBlock() && dt.Is(F32)) {
18796      EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18797                 rm.Encode(5, 0));
18798      AdvanceIT();
18799      return;
18800    }
18801  } else {
18802    // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
18803    if (dt.Is(F32)) {
18804      EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18805              rm.Encode(5, 0));
18806      return;
18807    }
18808  }
18809  Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18810}
18811
18812void Assembler::vmin(
18813    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18814  VIXL_ASSERT(AllowAssembler());
18815  CheckIT(cond);
18816  Dt_U_size_1 encoded_dt(dt);
18817  if (IsUsingT32()) {
18818    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
18819    if (dt.Is(F32)) {
18820      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18821        EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18822                   rm.Encode(5, 0));
18823        AdvanceIT();
18824        return;
18825      }
18826    }
18827    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
18828    if (encoded_dt.IsValid()) {
18829      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18830        EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18831                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18832                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18833        AdvanceIT();
18834        return;
18835      }
18836    }
18837  } else {
18838    // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
18839    if (dt.Is(F32)) {
18840      if (cond.Is(al)) {
18841        EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18842                rm.Encode(5, 0));
18843        return;
18844      }
18845    }
18846    // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
18847    if (encoded_dt.IsValid()) {
18848      if (cond.Is(al)) {
18849        EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18850                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18851                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18852        return;
18853      }
18854    }
18855  }
18856  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
18857}
18858
18859void Assembler::vmin(
18860    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18861  VIXL_ASSERT(AllowAssembler());
18862  CheckIT(cond);
18863  Dt_U_size_1 encoded_dt(dt);
18864  if (IsUsingT32()) {
18865    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
18866    if (dt.Is(F32)) {
18867      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18868        EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18869                   rm.Encode(5, 0));
18870        AdvanceIT();
18871        return;
18872      }
18873    }
18874    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
18875    if (encoded_dt.IsValid()) {
18876      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18877        EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18878                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18879                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18880        AdvanceIT();
18881        return;
18882      }
18883    }
18884  } else {
18885    // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
18886    if (dt.Is(F32)) {
18887      if (cond.Is(al)) {
18888        EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18889                rm.Encode(5, 0));
18890        return;
18891      }
18892    }
18893    // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
18894    if (encoded_dt.IsValid()) {
18895      if (cond.Is(al)) {
18896        EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18897                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18898                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18899        return;
18900      }
18901    }
18902  }
18903  Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
18904}
18905
18906void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
18907  VIXL_ASSERT(AllowAssembler());
18908  CheckIT(al);
18909  if (IsUsingT32()) {
18910    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
18911    if (OutsideITBlock() && dt.Is(F32)) {
18912      EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18913                 rm.Encode(5, 0));
18914      AdvanceIT();
18915      return;
18916    }
18917    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
18918    if (OutsideITBlock() && dt.Is(F64)) {
18919      EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18920                 rm.Encode(5, 0));
18921      AdvanceIT();
18922      return;
18923    }
18924  } else {
18925    // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
18926    if (dt.Is(F32)) {
18927      EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18928              rm.Encode(5, 0));
18929      return;
18930    }
18931    // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
18932    if (dt.Is(F64)) {
18933      EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18934              rm.Encode(5, 0));
18935      return;
18936    }
18937  }
18938  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18939}
18940
18941void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
18942  VIXL_ASSERT(AllowAssembler());
18943  CheckIT(al);
18944  if (IsUsingT32()) {
18945    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
18946    if (OutsideITBlock() && dt.Is(F32)) {
18947      EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18948                 rm.Encode(5, 0));
18949      AdvanceIT();
18950      return;
18951    }
18952  } else {
18953    // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
18954    if (dt.Is(F32)) {
18955      EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18956              rm.Encode(5, 0));
18957      return;
18958    }
18959  }
18960  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18961}
18962
18963void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
18964  VIXL_ASSERT(AllowAssembler());
18965  CheckIT(al);
18966  if (IsUsingT32()) {
18967    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
18968    if (OutsideITBlock() && dt.Is(F32)) {
18969      EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18970                 rm.Encode(5, 0));
18971      AdvanceIT();
18972      return;
18973    }
18974  } else {
18975    // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
18976    if (dt.Is(F32)) {
18977      EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18978              rm.Encode(5, 0));
18979      return;
18980    }
18981  }
18982  Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18983}
18984
18985void Assembler::vmla(
18986    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
18987  VIXL_ASSERT(AllowAssembler());
18988  CheckIT(cond);
18989  Dt_size_9 encoded_dt(dt);
18990  if (IsUsingT32()) {
18991    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
18992    if (encoded_dt.IsValid() &&
18993        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
18994         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
18995          (rm.GetLane() <= 1)))) {
18996      if (cond.Is(al) || AllowStronglyDiscouraged()) {
18997        EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
18998                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
18999                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19000        AdvanceIT();
19001        return;
19002      }
19003    }
19004  } else {
19005    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
19006    if (encoded_dt.IsValid() &&
19007        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19008         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19009          (rm.GetLane() <= 1)))) {
19010      if (cond.Is(al)) {
19011        EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19012                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19013                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19014        return;
19015      }
19016    }
19017  }
19018  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19019}
19020
19021void Assembler::vmla(
19022    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
19023  VIXL_ASSERT(AllowAssembler());
19024  CheckIT(cond);
19025  Dt_size_9 encoded_dt(dt);
19026  if (IsUsingT32()) {
19027    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
19028    if (encoded_dt.IsValid() &&
19029        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19030         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19031          (rm.GetLane() <= 1)))) {
19032      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19033        EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19034                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19035                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19036        AdvanceIT();
19037        return;
19038      }
19039    }
19040  } else {
19041    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
19042    if (encoded_dt.IsValid() &&
19043        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19044         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19045          (rm.GetLane() <= 1)))) {
19046      if (cond.Is(al)) {
19047        EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19048                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19049                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19050        return;
19051      }
19052    }
19053  }
19054  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19055}
19056
19057void Assembler::vmla(
19058    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19059  VIXL_ASSERT(AllowAssembler());
19060  CheckIT(cond);
19061  Dt_size_10 encoded_dt(dt);
19062  if (IsUsingT32()) {
19063    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19064    if (dt.Is(F32)) {
19065      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19066        EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19067                   rm.Encode(5, 0));
19068        AdvanceIT();
19069        return;
19070      }
19071    }
19072    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19073    if (dt.Is(F64)) {
19074      EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19075                 rm.Encode(5, 0));
19076      AdvanceIT();
19077      return;
19078    }
19079    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
19080    if (encoded_dt.IsValid()) {
19081      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19082        EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
19083                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19084        AdvanceIT();
19085        return;
19086      }
19087    }
19088  } else {
19089    // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19090    if (dt.Is(F32)) {
19091      if (cond.Is(al)) {
19092        EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19093                rm.Encode(5, 0));
19094        return;
19095      }
19096    }
19097    // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19098    if (dt.Is(F64) && cond.IsNotNever()) {
19099      EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19100              rn.Encode(7, 16) | rm.Encode(5, 0));
19101      return;
19102    }
19103    // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
19104    if (encoded_dt.IsValid()) {
19105      if (cond.Is(al)) {
19106        EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
19107                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19108        return;
19109      }
19110    }
19111  }
19112  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19113}
19114
19115void Assembler::vmla(
19116    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19117  VIXL_ASSERT(AllowAssembler());
19118  CheckIT(cond);
19119  Dt_size_10 encoded_dt(dt);
19120  if (IsUsingT32()) {
19121    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19122    if (dt.Is(F32)) {
19123      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19124        EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19125                   rm.Encode(5, 0));
19126        AdvanceIT();
19127        return;
19128      }
19129    }
19130    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
19131    if (encoded_dt.IsValid()) {
19132      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19133        EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
19134                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19135        AdvanceIT();
19136        return;
19137      }
19138    }
19139  } else {
19140    // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19141    if (dt.Is(F32)) {
19142      if (cond.Is(al)) {
19143        EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19144                rm.Encode(5, 0));
19145        return;
19146      }
19147    }
19148    // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
19149    if (encoded_dt.IsValid()) {
19150      if (cond.Is(al)) {
19151        EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
19152                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19153        return;
19154      }
19155    }
19156  }
19157  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19158}
19159
19160void Assembler::vmla(
19161    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
19162  VIXL_ASSERT(AllowAssembler());
19163  CheckIT(cond);
19164  if (IsUsingT32()) {
19165    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19166    if (dt.Is(F32)) {
19167      EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19168                 rm.Encode(5, 0));
19169      AdvanceIT();
19170      return;
19171    }
19172  } else {
19173    // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19174    if (dt.Is(F32) && cond.IsNotNever()) {
19175      EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19176              rn.Encode(7, 16) | rm.Encode(5, 0));
19177      return;
19178    }
19179  }
19180  Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19181}
19182
19183void Assembler::vmlal(
19184    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
19185  VIXL_ASSERT(AllowAssembler());
19186  CheckIT(cond);
19187  Dt_size_11 encoded_dt(dt);
19188  if (IsUsingT32()) {
19189    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
19190    if (encoded_dt.IsValid() &&
19191        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19192         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19193          (rm.GetLane() <= 1)))) {
19194      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19195        EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
19196                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19197                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19198        AdvanceIT();
19199        return;
19200      }
19201    }
19202  } else {
19203    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
19204    if (encoded_dt.IsValid() &&
19205        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19206         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19207          (rm.GetLane() <= 1)))) {
19208      if (cond.Is(al)) {
19209        EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
19210                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19211                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19212        return;
19213      }
19214    }
19215  }
19216  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
19217}
19218
19219void Assembler::vmlal(
19220    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
19221  VIXL_ASSERT(AllowAssembler());
19222  CheckIT(cond);
19223  Dt_size_12 encoded_dt(dt);
19224  if (IsUsingT32()) {
19225    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
19226    if (encoded_dt.IsValid()) {
19227      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19228        EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
19229                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19230                   rn.Encode(7, 16) | rm.Encode(5, 0));
19231        AdvanceIT();
19232        return;
19233      }
19234    }
19235  } else {
19236    // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
19237    if (encoded_dt.IsValid()) {
19238      if (cond.Is(al)) {
19239        EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
19240                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19241                rn.Encode(7, 16) | rm.Encode(5, 0));
19242        return;
19243      }
19244    }
19245  }
19246  Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
19247}
19248
19249void Assembler::vmls(
19250    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
19251  VIXL_ASSERT(AllowAssembler());
19252  CheckIT(cond);
19253  Dt_size_9 encoded_dt(dt);
19254  if (IsUsingT32()) {
19255    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
19256    if (encoded_dt.IsValid() &&
19257        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19258         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19259          (rm.GetLane() <= 1)))) {
19260      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19261        EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19262                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19263                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19264        AdvanceIT();
19265        return;
19266      }
19267    }
19268  } else {
19269    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
19270    if (encoded_dt.IsValid() &&
19271        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19272         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19273          (rm.GetLane() <= 1)))) {
19274      if (cond.Is(al)) {
19275        EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19276                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19277                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19278        return;
19279      }
19280    }
19281  }
19282  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19283}
19284
19285void Assembler::vmls(
19286    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
19287  VIXL_ASSERT(AllowAssembler());
19288  CheckIT(cond);
19289  Dt_size_9 encoded_dt(dt);
19290  if (IsUsingT32()) {
19291    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
19292    if (encoded_dt.IsValid() &&
19293        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19294         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19295          (rm.GetLane() <= 1)))) {
19296      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19297        EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19298                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19299                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19300        AdvanceIT();
19301        return;
19302      }
19303    }
19304  } else {
19305    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
19306    if (encoded_dt.IsValid() &&
19307        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19308         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19309          (rm.GetLane() <= 1)))) {
19310      if (cond.Is(al)) {
19311        EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19312                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19313                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19314        return;
19315      }
19316    }
19317  }
19318  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19319}
19320
19321void Assembler::vmls(
19322    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
19323  VIXL_ASSERT(AllowAssembler());
19324  CheckIT(cond);
19325  Dt_size_10 encoded_dt(dt);
19326  if (IsUsingT32()) {
19327    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19328    if (dt.Is(F32)) {
19329      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19330        EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19331                   rm.Encode(5, 0));
19332        AdvanceIT();
19333        return;
19334      }
19335    }
19336    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19337    if (dt.Is(F64)) {
19338      EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19339                 rm.Encode(5, 0));
19340      AdvanceIT();
19341      return;
19342    }
19343    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
19344    if (encoded_dt.IsValid()) {
19345      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19346        EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
19347                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19348        AdvanceIT();
19349        return;
19350      }
19351    }
19352  } else {
19353    // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19354    if (dt.Is(F32)) {
19355      if (cond.Is(al)) {
19356        EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19357                rm.Encode(5, 0));
19358        return;
19359      }
19360    }
19361    // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19362    if (dt.Is(F64) && cond.IsNotNever()) {
19363      EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19364              rn.Encode(7, 16) | rm.Encode(5, 0));
19365      return;
19366    }
19367    // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
19368    if (encoded_dt.IsValid()) {
19369      if (cond.Is(al)) {
19370        EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
19371                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19372        return;
19373      }
19374    }
19375  }
19376  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19377}
19378
19379void Assembler::vmls(
19380    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
19381  VIXL_ASSERT(AllowAssembler());
19382  CheckIT(cond);
19383  Dt_size_10 encoded_dt(dt);
19384  if (IsUsingT32()) {
19385    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19386    if (dt.Is(F32)) {
19387      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19388        EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19389                   rm.Encode(5, 0));
19390        AdvanceIT();
19391        return;
19392      }
19393    }
19394    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
19395    if (encoded_dt.IsValid()) {
19396      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19397        EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
19398                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19399        AdvanceIT();
19400        return;
19401      }
19402    }
19403  } else {
19404    // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19405    if (dt.Is(F32)) {
19406      if (cond.Is(al)) {
19407        EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19408                rm.Encode(5, 0));
19409        return;
19410      }
19411    }
19412    // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
19413    if (encoded_dt.IsValid()) {
19414      if (cond.Is(al)) {
19415        EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
19416                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19417        return;
19418      }
19419    }
19420  }
19421  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19422}
19423
19424void Assembler::vmls(
19425    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
19426  VIXL_ASSERT(AllowAssembler());
19427  CheckIT(cond);
19428  if (IsUsingT32()) {
19429    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19430    if (dt.Is(F32)) {
19431      EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19432                 rm.Encode(5, 0));
19433      AdvanceIT();
19434      return;
19435    }
19436  } else {
19437    // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19438    if (dt.Is(F32) && cond.IsNotNever()) {
19439      EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19440              rn.Encode(7, 16) | rm.Encode(5, 0));
19441      return;
19442    }
19443  }
19444  Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19445}
19446
19447void Assembler::vmlsl(
19448    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
19449  VIXL_ASSERT(AllowAssembler());
19450  CheckIT(cond);
19451  Dt_size_11 encoded_dt(dt);
19452  if (IsUsingT32()) {
19453    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
19454    if (encoded_dt.IsValid() &&
19455        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19456         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19457          (rm.GetLane() <= 1)))) {
19458      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19459        EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
19460                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19461                   rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19462        AdvanceIT();
19463        return;
19464      }
19465    }
19466  } else {
19467    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
19468    if (encoded_dt.IsValid() &&
19469        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19470         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19471          (rm.GetLane() <= 1)))) {
19472      if (cond.Is(al)) {
19473        EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
19474                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19475                rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19476        return;
19477      }
19478    }
19479  }
19480  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
19481}
19482
19483void Assembler::vmlsl(
19484    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
19485  VIXL_ASSERT(AllowAssembler());
19486  CheckIT(cond);
19487  Dt_size_12 encoded_dt(dt);
19488  if (IsUsingT32()) {
19489    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
19490    if (encoded_dt.IsValid()) {
19491      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19492        EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
19493                   (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19494                   rn.Encode(7, 16) | rm.Encode(5, 0));
19495        AdvanceIT();
19496        return;
19497      }
19498    }
19499  } else {
19500    // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
19501    if (encoded_dt.IsValid()) {
19502      if (cond.Is(al)) {
19503        EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
19504                (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19505                rn.Encode(7, 16) | rm.Encode(5, 0));
19506        return;
19507      }
19508    }
19509  }
19510  Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
19511}
19512
19513void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
19514  VIXL_ASSERT(AllowAssembler());
19515  CheckIT(cond);
19516  if (IsUsingT32()) {
19517    // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
19518    EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
19519    AdvanceIT();
19520    return;
19521  } else {
19522    // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
19523    if (cond.IsNotNever()) {
19524      EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19525              rn.Encode(7, 16));
19526      return;
19527    }
19528  }
19529  Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
19530}
19531
19532void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
19533  VIXL_ASSERT(AllowAssembler());
19534  CheckIT(cond);
19535  if (IsUsingT32()) {
19536    // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
19537    EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
19538    AdvanceIT();
19539    return;
19540  } else {
19541    // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
19542    if (cond.IsNotNever()) {
19543      EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
19544              (rt.GetCode() << 12));
19545      return;
19546    }
19547  }
19548  Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
19549}
19550
19551void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
19552  VIXL_ASSERT(AllowAssembler());
19553  CheckIT(cond);
19554  if (IsUsingT32()) {
19555    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
19556    EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
19557               rm.Encode(5, 0));
19558    AdvanceIT();
19559    return;
19560  } else {
19561    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
19562    if (cond.IsNotNever()) {
19563      EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19564              (rt2.GetCode() << 16) | rm.Encode(5, 0));
19565      return;
19566    }
19567  }
19568  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
19569}
19570
19571void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
19572  VIXL_ASSERT(AllowAssembler());
19573  CheckIT(cond);
19574  if (IsUsingT32()) {
19575    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
19576    EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
19577               (rt2.GetCode() << 16));
19578    AdvanceIT();
19579    return;
19580  } else {
19581    // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
19582    if (cond.IsNotNever()) {
19583      EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
19584              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
19585      return;
19586    }
19587  }
19588  Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
19589}
19590
19591void Assembler::vmov(
19592    Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
19593  VIXL_ASSERT(AllowAssembler());
19594  CheckIT(cond);
19595  if (IsUsingT32()) {
19596    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
19597    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode())) {
19598      EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
19599                 rm.Encode(5, 0));
19600      AdvanceIT();
19601      return;
19602    }
19603  } else {
19604    // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
19605    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
19606        cond.IsNotNever()) {
19607      EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19608              (rt2.GetCode() << 16) | rm.Encode(5, 0));
19609      return;
19610    }
19611  }
19612  Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
19613}
19614
19615void Assembler::vmov(
19616    Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
19617  VIXL_ASSERT(AllowAssembler());
19618  CheckIT(cond);
19619  if (IsUsingT32()) {
19620    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
19621    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode())) {
19622      EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
19623                 (rt2.GetCode() << 16));
19624      AdvanceIT();
19625      return;
19626    }
19627  } else {
19628    // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
19629    if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
19630        cond.IsNotNever()) {
19631      EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
19632              (rt.GetCode() << 12) | (rt2.GetCode() << 16));
19633      return;
19634    }
19635  }
19636  Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
19637}
19638
19639void Assembler::vmov(Condition cond,
19640                     DataType dt,
19641                     DRegisterLane rd,
19642                     Register rt) {
19643  VIXL_ASSERT(AllowAssembler());
19644  CheckIT(cond);
19645  Dt_opc1_opc2_1 encoded_dt(dt, rd);
19646  if (IsUsingT32()) {
19647    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
19648    if (encoded_dt.IsValid()) {
19649      EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19650                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19651                 rd.Encode(7, 16) | (rt.GetCode() << 12));
19652      AdvanceIT();
19653      return;
19654    }
19655  } else {
19656    // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
19657    if (encoded_dt.IsValid() && cond.IsNotNever()) {
19658      EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
19659              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19660              ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
19661              (rt.GetCode() << 12));
19662      return;
19663    }
19664  }
19665  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
19666}
19667
19668void Assembler::vmov(Condition cond,
19669                     DataType dt,
19670                     DRegister rd,
19671                     const DOperand& operand) {
19672  VIXL_ASSERT(AllowAssembler());
19673  CheckIT(cond);
19674  if (operand.IsImmediate()) {
19675    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
19676    ImmediateVFP vfp(operand.GetNeonImmediate());
19677    if (IsUsingT32()) {
19678      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
19679      if (encoded_dt.IsValid()) {
19680        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19681          EmitT32_32(
19682              0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19683              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19684              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19685              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19686              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
19687          AdvanceIT();
19688          return;
19689        }
19690      }
19691      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
19692      if (dt.Is(F64) && vfp.IsValid()) {
19693        EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
19694                   (vfp.GetEncodingValue() & 0xf) |
19695                   ((vfp.GetEncodingValue() & 0xf0) << 12));
19696        AdvanceIT();
19697        return;
19698      }
19699    } else {
19700      // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
19701      if (encoded_dt.IsValid()) {
19702        if (cond.Is(al)) {
19703          EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19704                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19705                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19706                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19707                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
19708          return;
19709        }
19710      }
19711      // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
19712      if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
19713        EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19714                (vfp.GetEncodingValue() & 0xf) |
19715                ((vfp.GetEncodingValue() & 0xf0) << 12));
19716        return;
19717      }
19718    }
19719  }
19720  if (operand.IsRegister()) {
19721    DRegister rm = operand.GetRegister();
19722    if (IsUsingT32()) {
19723      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
19724      if (dt.Is(F64)) {
19725        EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
19726        AdvanceIT();
19727        return;
19728      }
19729      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
19730      if (!dt.Is(F64)) {
19731        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19732          EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19733                     rm.Encode(5, 0));
19734          AdvanceIT();
19735          return;
19736        }
19737      }
19738    } else {
19739      // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
19740      if (dt.Is(F64) && cond.IsNotNever()) {
19741        EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19742                rm.Encode(5, 0));
19743        return;
19744      }
19745      // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
19746      if (!dt.Is(F64)) {
19747        if (cond.Is(al)) {
19748          EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19749                  rm.Encode(5, 0));
19750          return;
19751        }
19752      }
19753    }
19754  }
19755  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19756}
19757
19758void Assembler::vmov(Condition cond,
19759                     DataType dt,
19760                     QRegister rd,
19761                     const QOperand& operand) {
19762  VIXL_ASSERT(AllowAssembler());
19763  CheckIT(cond);
19764  if (operand.IsImmediate()) {
19765    ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
19766    if (IsUsingT32()) {
19767      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
19768      if (encoded_dt.IsValid()) {
19769        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19770          EmitT32_32(
19771              0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19772              ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19773              rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19774              ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19775              ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
19776          AdvanceIT();
19777          return;
19778        }
19779      }
19780    } else {
19781      // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
19782      if (encoded_dt.IsValid()) {
19783        if (cond.Is(al)) {
19784          EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19785                  ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19786                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19787                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19788                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
19789          return;
19790        }
19791      }
19792    }
19793  }
19794  if (operand.IsRegister()) {
19795    QRegister rm = operand.GetRegister();
19796    if (IsUsingT32()) {
19797      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
19798      if (!dt.Is(F64)) {
19799        if (cond.Is(al) || AllowStronglyDiscouraged()) {
19800          EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19801                     rm.Encode(5, 0));
19802          AdvanceIT();
19803          return;
19804        }
19805      }
19806    } else {
19807      // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
19808      if (!dt.Is(F64)) {
19809        if (cond.Is(al)) {
19810          EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19811                  rm.Encode(5, 0));
19812          return;
19813        }
19814      }
19815    }
19816  }
19817  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19818}
19819
19820void Assembler::vmov(Condition cond,
19821                     DataType dt,
19822                     SRegister rd,
19823                     const SOperand& operand) {
19824  VIXL_ASSERT(AllowAssembler());
19825  CheckIT(cond);
19826  if (operand.IsImmediate()) {
19827    ImmediateVFP vfp(operand.GetNeonImmediate());
19828    if (IsUsingT32()) {
19829      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
19830      if (dt.Is(F32) && vfp.IsValid()) {
19831        EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
19832                   (vfp.GetEncodingValue() & 0xf) |
19833                   ((vfp.GetEncodingValue() & 0xf0) << 12));
19834        AdvanceIT();
19835        return;
19836      }
19837    } else {
19838      // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
19839      if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
19840        EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19841                (vfp.GetEncodingValue() & 0xf) |
19842                ((vfp.GetEncodingValue() & 0xf0) << 12));
19843        return;
19844      }
19845    }
19846  }
19847  if (operand.IsRegister()) {
19848    SRegister rm = operand.GetRegister();
19849    if (IsUsingT32()) {
19850      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
19851      if (dt.Is(F32)) {
19852        EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
19853        AdvanceIT();
19854        return;
19855      }
19856    } else {
19857      // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
19858      if (dt.Is(F32) && cond.IsNotNever()) {
19859        EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19860                rm.Encode(5, 0));
19861        return;
19862      }
19863    }
19864  }
19865  Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19866}
19867
19868void Assembler::vmov(Condition cond,
19869                     DataType dt,
19870                     Register rt,
19871                     DRegisterLane rn) {
19872  VIXL_ASSERT(AllowAssembler());
19873  CheckIT(cond);
19874  Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
19875  if (IsUsingT32()) {
19876    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
19877    if (encoded_dt.IsValid()) {
19878      EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19879                 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19880                 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
19881                 (rt.GetCode() << 12) | rn.Encode(7, 16));
19882      AdvanceIT();
19883      return;
19884    }
19885  } else {
19886    // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
19887    if (encoded_dt.IsValid() && cond.IsNotNever()) {
19888      EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
19889              ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19890              ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19891              ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
19892              (rt.GetCode() << 12) | rn.Encode(7, 16));
19893      return;
19894    }
19895  }
19896  Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
19897}
19898
19899void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
19900  VIXL_ASSERT(AllowAssembler());
19901  CheckIT(cond);
19902  Dt_U_imm3H_1 encoded_dt(dt);
19903  if (IsUsingT32()) {
19904    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
19905    if (encoded_dt.IsValid()) {
19906      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19907        EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
19908                   ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
19909                   rd.Encode(22, 12) | rm.Encode(5, 0));
19910        AdvanceIT();
19911        return;
19912      }
19913    }
19914  } else {
19915    // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
19916    if (encoded_dt.IsValid()) {
19917      if (cond.Is(al)) {
19918        EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
19919                ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
19920                rd.Encode(22, 12) | rm.Encode(5, 0));
19921        return;
19922      }
19923    }
19924  }
19925  Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
19926}
19927
19928void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
19929  VIXL_ASSERT(AllowAssembler());
19930  CheckIT(cond);
19931  Dt_size_3 encoded_dt(dt);
19932  if (IsUsingT32()) {
19933    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
19934    if (encoded_dt.IsValid()) {
19935      if (cond.Is(al) || AllowStronglyDiscouraged()) {
19936        EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
19937                   rd.Encode(22, 12) | rm.Encode(5, 0));
19938        AdvanceIT();
19939        return;
19940      }
19941    }
19942  } else {
19943    // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
19944    if (encoded_dt.IsValid()) {
19945      if (cond.Is(al)) {
19946        EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
19947                rd.Encode(22, 12) | rm.Encode(5, 0));
19948        return;
19949      }
19950    }
19951  }
19952  Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
19953}
19954
19955void Assembler::vmrs(Condition cond,
19956                     RegisterOrAPSR_nzcv rt,
19957                     SpecialFPRegister spec_reg) {
19958  VIXL_ASSERT(AllowAssembler());
19959  CheckIT(cond);
19960  if (IsUsingT32()) {
19961    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
19962    EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
19963    AdvanceIT();
19964    return;
19965  } else {
19966    // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
19967    if (cond.IsNotNever()) {
19968      EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19969              (spec_reg.GetReg() << 16));
19970      return;
19971    }
19972  }
19973  Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
19974}
19975
19976void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
19977  VIXL_ASSERT(AllowAssembler());
19978  CheckIT(cond);
19979  if (IsUsingT32()) {
19980    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
19981    EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
19982    AdvanceIT();
19983    return;
19984  } else {
19985    // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
19986    if (cond.IsNotNever()) {
19987      EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
19988              (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
19989      return;
19990    }
19991  }
19992  Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
19993}
19994
19995void Assembler::vmul(Condition cond,
19996                     DataType dt,
19997                     DRegister rd,
19998                     DRegister rn,
19999                     DRegister dm,
20000                     unsigned index) {
20001  VIXL_ASSERT(AllowAssembler());
20002  CheckIT(cond);
20003  Dt_F_size_3 encoded_dt(dt);
20004  if (IsUsingT32()) {
20005    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
20006    if (encoded_dt.IsValid() &&
20007        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20008         (!dt.Is(I16) && (index <= 1)))) {
20009      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20010        uint32_t shift = 4;
20011        if (dt.Is(I16)) {
20012          shift = 3;
20013        }
20014        uint32_t mvm = dm.GetCode() | index << shift;
20015        EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20016                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20017                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20018                   ((mvm & 0x10) << 1));
20019        AdvanceIT();
20020        return;
20021      }
20022    }
20023  } else {
20024    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
20025    if (encoded_dt.IsValid() &&
20026        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20027         (!dt.Is(I16) && (index <= 1)))) {
20028      if (cond.Is(al)) {
20029        uint32_t shift = 4;
20030        if (dt.Is(I16)) {
20031          shift = 3;
20032        }
20033        uint32_t mvm = dm.GetCode() | index << shift;
20034        EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20035                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20036                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20037                ((mvm & 0x10) << 1));
20038        return;
20039      }
20040    }
20041  }
20042  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
20043}
20044
20045void Assembler::vmul(Condition cond,
20046                     DataType dt,
20047                     QRegister rd,
20048                     QRegister rn,
20049                     DRegister dm,
20050                     unsigned index) {
20051  VIXL_ASSERT(AllowAssembler());
20052  CheckIT(cond);
20053  Dt_F_size_3 encoded_dt(dt);
20054  if (IsUsingT32()) {
20055    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
20056    if (encoded_dt.IsValid() &&
20057        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20058         (!dt.Is(I16) && (index <= 1)))) {
20059      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20060        uint32_t shift = 4;
20061        if (dt.Is(I16)) {
20062          shift = 3;
20063        }
20064        uint32_t mvm = dm.GetCode() | index << shift;
20065        EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20066                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20067                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20068                   ((mvm & 0x10) << 1));
20069        AdvanceIT();
20070        return;
20071      }
20072    }
20073  } else {
20074    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
20075    if (encoded_dt.IsValid() &&
20076        ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20077         (!dt.Is(I16) && (index <= 1)))) {
20078      if (cond.Is(al)) {
20079        uint32_t shift = 4;
20080        if (dt.Is(I16)) {
20081          shift = 3;
20082        }
20083        uint32_t mvm = dm.GetCode() | index << shift;
20084        EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20085                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20086                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20087                ((mvm & 0x10) << 1));
20088        return;
20089      }
20090    }
20091  }
20092  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
20093}
20094
20095void Assembler::vmul(
20096    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20097  VIXL_ASSERT(AllowAssembler());
20098  CheckIT(cond);
20099  Dt_op_size_1 encoded_dt(dt);
20100  if (IsUsingT32()) {
20101    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20102    if (dt.Is(F32)) {
20103      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20104        EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20105                   rm.Encode(5, 0));
20106        AdvanceIT();
20107        return;
20108      }
20109    }
20110    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
20111    if (dt.Is(F64)) {
20112      EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20113                 rm.Encode(5, 0));
20114      AdvanceIT();
20115      return;
20116    }
20117    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20118    if (encoded_dt.IsValid()) {
20119      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20120        EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20121                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20122                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20123        AdvanceIT();
20124        return;
20125      }
20126    }
20127  } else {
20128    // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20129    if (dt.Is(F32)) {
20130      if (cond.Is(al)) {
20131        EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20132                rm.Encode(5, 0));
20133        return;
20134      }
20135    }
20136    // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
20137    if (dt.Is(F64) && cond.IsNotNever()) {
20138      EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20139              rn.Encode(7, 16) | rm.Encode(5, 0));
20140      return;
20141    }
20142    // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20143    if (encoded_dt.IsValid()) {
20144      if (cond.Is(al)) {
20145        EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20146                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20147                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20148        return;
20149      }
20150    }
20151  }
20152  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20153}
20154
20155void Assembler::vmul(
20156    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
20157  VIXL_ASSERT(AllowAssembler());
20158  CheckIT(cond);
20159  Dt_op_size_1 encoded_dt(dt);
20160  if (IsUsingT32()) {
20161    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20162    if (dt.Is(F32)) {
20163      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20164        EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20165                   rm.Encode(5, 0));
20166        AdvanceIT();
20167        return;
20168      }
20169    }
20170    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20171    if (encoded_dt.IsValid()) {
20172      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20173        EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20174                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20175                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20176        AdvanceIT();
20177        return;
20178      }
20179    }
20180  } else {
20181    // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20182    if (dt.Is(F32)) {
20183      if (cond.Is(al)) {
20184        EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20185                rm.Encode(5, 0));
20186        return;
20187      }
20188    }
20189    // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20190    if (encoded_dt.IsValid()) {
20191      if (cond.Is(al)) {
20192        EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20193                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20194                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20195        return;
20196      }
20197    }
20198  }
20199  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20200}
20201
20202void Assembler::vmul(
20203    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20204  VIXL_ASSERT(AllowAssembler());
20205  CheckIT(cond);
20206  if (IsUsingT32()) {
20207    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
20208    if (dt.Is(F32)) {
20209      EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20210                 rm.Encode(5, 0));
20211      AdvanceIT();
20212      return;
20213    }
20214  } else {
20215    // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
20216    if (dt.Is(F32) && cond.IsNotNever()) {
20217      EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20218              rn.Encode(7, 16) | rm.Encode(5, 0));
20219      return;
20220    }
20221  }
20222  Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20223}
20224
20225void Assembler::vmull(Condition cond,
20226                      DataType dt,
20227                      QRegister rd,
20228                      DRegister rn,
20229                      DRegister dm,
20230                      unsigned index) {
20231  VIXL_ASSERT(AllowAssembler());
20232  CheckIT(cond);
20233  Dt_U_size_2 encoded_dt(dt);
20234  if (IsUsingT32()) {
20235    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
20236    if (encoded_dt.IsValid() &&
20237        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
20238         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
20239      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20240        uint32_t shift = 4;
20241        if (dt.Is(S16) || dt.Is(U16)) {
20242          shift = 3;
20243        }
20244        uint32_t mvm = dm.GetCode() | index << shift;
20245        EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20246                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20247                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20248                   ((mvm & 0x10) << 1));
20249        AdvanceIT();
20250        return;
20251      }
20252    }
20253  } else {
20254    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
20255    if (encoded_dt.IsValid() &&
20256        (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
20257         (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
20258      if (cond.Is(al)) {
20259        uint32_t shift = 4;
20260        if (dt.Is(S16) || dt.Is(U16)) {
20261          shift = 3;
20262        }
20263        uint32_t mvm = dm.GetCode() | index << shift;
20264        EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20265                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20266                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20267                ((mvm & 0x10) << 1));
20268        return;
20269      }
20270    }
20271  }
20272  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
20273}
20274
20275void Assembler::vmull(
20276    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
20277  VIXL_ASSERT(AllowAssembler());
20278  CheckIT(cond);
20279  Dt_op_U_size_1 encoded_dt(dt);
20280  if (IsUsingT32()) {
20281    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
20282    if (encoded_dt.IsValid()) {
20283      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20284        EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20285                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20286                   ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
20287                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20288        AdvanceIT();
20289        return;
20290      }
20291    }
20292  } else {
20293    // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
20294    if (encoded_dt.IsValid()) {
20295      if (cond.Is(al)) {
20296        EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20297                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20298                ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
20299                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20300        return;
20301      }
20302    }
20303  }
20304  Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
20305}
20306
20307void Assembler::vmvn(Condition cond,
20308                     DataType dt,
20309                     DRegister rd,
20310                     const DOperand& operand) {
20311  VIXL_ASSERT(AllowAssembler());
20312  CheckIT(cond);
20313  if (operand.IsImmediate()) {
20314    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
20315    if (IsUsingT32()) {
20316      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20317      if (encoded_dt.IsValid()) {
20318        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20319          EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
20320                     rd.Encode(22, 12) |
20321                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20322                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20323                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20324          AdvanceIT();
20325          return;
20326        }
20327      }
20328    } else {
20329      // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20330      if (encoded_dt.IsValid()) {
20331        if (cond.Is(al)) {
20332          EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
20333                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20334                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20335                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20336          return;
20337        }
20338      }
20339    }
20340  }
20341  if (operand.IsRegister()) {
20342    DRegister rm = operand.GetRegister();
20343    USE(dt);
20344    if (IsUsingT32()) {
20345      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
20346      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20347        EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
20348        AdvanceIT();
20349        return;
20350      }
20351    } else {
20352      // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
20353      if (cond.Is(al)) {
20354        EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
20355        return;
20356      }
20357    }
20358  }
20359  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
20360}
20361
20362void Assembler::vmvn(Condition cond,
20363                     DataType dt,
20364                     QRegister rd,
20365                     const QOperand& operand) {
20366  VIXL_ASSERT(AllowAssembler());
20367  CheckIT(cond);
20368  if (operand.IsImmediate()) {
20369    ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
20370    if (IsUsingT32()) {
20371      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
20372      if (encoded_dt.IsValid()) {
20373        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20374          EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
20375                     rd.Encode(22, 12) |
20376                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20377                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20378                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20379          AdvanceIT();
20380          return;
20381        }
20382      }
20383    } else {
20384      // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
20385      if (encoded_dt.IsValid()) {
20386        if (cond.Is(al)) {
20387          EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
20388                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20389                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20390                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20391          return;
20392        }
20393      }
20394    }
20395  }
20396  if (operand.IsRegister()) {
20397    QRegister rm = operand.GetRegister();
20398    USE(dt);
20399    if (IsUsingT32()) {
20400      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
20401      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20402        EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
20403        AdvanceIT();
20404        return;
20405      }
20406    } else {
20407      // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
20408      if (cond.Is(al)) {
20409        EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
20410        return;
20411      }
20412    }
20413  }
20414  Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
20415}
20416
20417void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
20418  VIXL_ASSERT(AllowAssembler());
20419  CheckIT(cond);
20420  Dt_F_size_1 encoded_dt(dt);
20421  if (IsUsingT32()) {
20422    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20423    if (encoded_dt.IsValid()) {
20424      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20425        EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20426                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20427                   rd.Encode(22, 12) | rm.Encode(5, 0));
20428        AdvanceIT();
20429        return;
20430      }
20431    }
20432    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
20433    if (dt.Is(F64)) {
20434      EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20435      AdvanceIT();
20436      return;
20437    }
20438  } else {
20439    // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
20440    if (encoded_dt.IsValid()) {
20441      if (cond.Is(al)) {
20442        EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20443                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20444                rd.Encode(22, 12) | rm.Encode(5, 0));
20445        return;
20446      }
20447    }
20448    // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
20449    if (dt.Is(F64) && cond.IsNotNever()) {
20450      EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20451              rm.Encode(5, 0));
20452      return;
20453    }
20454  }
20455  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20456}
20457
20458void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
20459  VIXL_ASSERT(AllowAssembler());
20460  CheckIT(cond);
20461  Dt_F_size_1 encoded_dt(dt);
20462  if (IsUsingT32()) {
20463    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
20464    if (encoded_dt.IsValid()) {
20465      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20466        EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20467                   ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20468                   rd.Encode(22, 12) | rm.Encode(5, 0));
20469        AdvanceIT();
20470        return;
20471      }
20472    }
20473  } else {
20474    // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
20475    if (encoded_dt.IsValid()) {
20476      if (cond.Is(al)) {
20477        EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20478                ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20479                rd.Encode(22, 12) | rm.Encode(5, 0));
20480        return;
20481      }
20482    }
20483  }
20484  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20485}
20486
20487void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
20488  VIXL_ASSERT(AllowAssembler());
20489  CheckIT(cond);
20490  if (IsUsingT32()) {
20491    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
20492    if (dt.Is(F32)) {
20493      EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20494      AdvanceIT();
20495      return;
20496    }
20497  } else {
20498    // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
20499    if (dt.Is(F32) && cond.IsNotNever()) {
20500      EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20501              rm.Encode(5, 0));
20502      return;
20503    }
20504  }
20505  Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20506}
20507
20508void Assembler::vnmla(
20509    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20510  VIXL_ASSERT(AllowAssembler());
20511  CheckIT(cond);
20512  if (IsUsingT32()) {
20513    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
20514    if (dt.Is(F32)) {
20515      EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20516                 rm.Encode(5, 0));
20517      AdvanceIT();
20518      return;
20519    }
20520  } else {
20521    // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
20522    if (dt.Is(F32) && cond.IsNotNever()) {
20523      EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20524              rn.Encode(7, 16) | rm.Encode(5, 0));
20525      return;
20526    }
20527  }
20528  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
20529}
20530
20531void Assembler::vnmla(
20532    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20533  VIXL_ASSERT(AllowAssembler());
20534  CheckIT(cond);
20535  if (IsUsingT32()) {
20536    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
20537    if (dt.Is(F64)) {
20538      EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20539                 rm.Encode(5, 0));
20540      AdvanceIT();
20541      return;
20542    }
20543  } else {
20544    // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
20545    if (dt.Is(F64) && cond.IsNotNever()) {
20546      EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20547              rn.Encode(7, 16) | rm.Encode(5, 0));
20548      return;
20549    }
20550  }
20551  Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
20552}
20553
20554void Assembler::vnmls(
20555    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20556  VIXL_ASSERT(AllowAssembler());
20557  CheckIT(cond);
20558  if (IsUsingT32()) {
20559    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
20560    if (dt.Is(F32)) {
20561      EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20562                 rm.Encode(5, 0));
20563      AdvanceIT();
20564      return;
20565    }
20566  } else {
20567    // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
20568    if (dt.Is(F32) && cond.IsNotNever()) {
20569      EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20570              rn.Encode(7, 16) | rm.Encode(5, 0));
20571      return;
20572    }
20573  }
20574  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
20575}
20576
20577void Assembler::vnmls(
20578    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20579  VIXL_ASSERT(AllowAssembler());
20580  CheckIT(cond);
20581  if (IsUsingT32()) {
20582    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
20583    if (dt.Is(F64)) {
20584      EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20585                 rm.Encode(5, 0));
20586      AdvanceIT();
20587      return;
20588    }
20589  } else {
20590    // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
20591    if (dt.Is(F64) && cond.IsNotNever()) {
20592      EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20593              rn.Encode(7, 16) | rm.Encode(5, 0));
20594      return;
20595    }
20596  }
20597  Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
20598}
20599
20600void Assembler::vnmul(
20601    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
20602  VIXL_ASSERT(AllowAssembler());
20603  CheckIT(cond);
20604  if (IsUsingT32()) {
20605    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
20606    if (dt.Is(F32)) {
20607      EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20608                 rm.Encode(5, 0));
20609      AdvanceIT();
20610      return;
20611    }
20612  } else {
20613    // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
20614    if (dt.Is(F32) && cond.IsNotNever()) {
20615      EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20616              rn.Encode(7, 16) | rm.Encode(5, 0));
20617      return;
20618    }
20619  }
20620  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
20621}
20622
20623void Assembler::vnmul(
20624    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20625  VIXL_ASSERT(AllowAssembler());
20626  CheckIT(cond);
20627  if (IsUsingT32()) {
20628    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
20629    if (dt.Is(F64)) {
20630      EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20631                 rm.Encode(5, 0));
20632      AdvanceIT();
20633      return;
20634    }
20635  } else {
20636    // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
20637    if (dt.Is(F64) && cond.IsNotNever()) {
20638      EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20639              rn.Encode(7, 16) | rm.Encode(5, 0));
20640      return;
20641    }
20642  }
20643  Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
20644}
20645
20646void Assembler::vorn(Condition cond,
20647                     DataType dt,
20648                     DRegister rd,
20649                     DRegister rn,
20650                     const DOperand& operand) {
20651  VIXL_ASSERT(AllowAssembler());
20652  CheckIT(cond);
20653  if (operand.IsImmediate()) {
20654    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
20655    if (IsUsingT32()) {
20656      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
20657      if (encoded_dt.IsValid() && rd.Is(rn)) {
20658        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20659          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
20660                     rd.Encode(22, 12) |
20661                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20662                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20663                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20664          AdvanceIT();
20665          return;
20666        }
20667      }
20668    } else {
20669      // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
20670      if (encoded_dt.IsValid() && rd.Is(rn)) {
20671        if (cond.Is(al)) {
20672          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
20673                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20674                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20675                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20676          return;
20677        }
20678      }
20679    }
20680  }
20681  if (operand.IsRegister()) {
20682    DRegister rm = operand.GetRegister();
20683    USE(dt);
20684    if (IsUsingT32()) {
20685      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
20686      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20687        EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20688                   rm.Encode(5, 0));
20689        AdvanceIT();
20690        return;
20691      }
20692    } else {
20693      // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
20694      if (cond.Is(al)) {
20695        EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20696                rm.Encode(5, 0));
20697        return;
20698      }
20699    }
20700  }
20701  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
20702}
20703
20704void Assembler::vorn(Condition cond,
20705                     DataType dt,
20706                     QRegister rd,
20707                     QRegister rn,
20708                     const QOperand& operand) {
20709  VIXL_ASSERT(AllowAssembler());
20710  CheckIT(cond);
20711  if (operand.IsImmediate()) {
20712    ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
20713    if (IsUsingT32()) {
20714      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
20715      if (encoded_dt.IsValid() && rd.Is(rn)) {
20716        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20717          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
20718                     rd.Encode(22, 12) |
20719                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20720                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20721                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20722          AdvanceIT();
20723          return;
20724        }
20725      }
20726    } else {
20727      // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
20728      if (encoded_dt.IsValid() && rd.Is(rn)) {
20729        if (cond.Is(al)) {
20730          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
20731                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20732                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20733                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20734          return;
20735        }
20736      }
20737    }
20738  }
20739  if (operand.IsRegister()) {
20740    QRegister rm = operand.GetRegister();
20741    USE(dt);
20742    if (IsUsingT32()) {
20743      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
20744      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20745        EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20746                   rm.Encode(5, 0));
20747        AdvanceIT();
20748        return;
20749      }
20750    } else {
20751      // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
20752      if (cond.Is(al)) {
20753        EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20754                rm.Encode(5, 0));
20755        return;
20756      }
20757    }
20758  }
20759  Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
20760}
20761
20762void Assembler::vorr(Condition cond,
20763                     DataType dt,
20764                     DRegister rd,
20765                     DRegister rn,
20766                     const DOperand& operand) {
20767  VIXL_ASSERT(AllowAssembler());
20768  CheckIT(cond);
20769  if (operand.IsRegister()) {
20770    DRegister rm = operand.GetRegister();
20771    USE(dt);
20772    if (IsUsingT32()) {
20773      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
20774      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20775        EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20776                   rm.Encode(5, 0));
20777        AdvanceIT();
20778        return;
20779      }
20780    } else {
20781      // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
20782      if (cond.Is(al)) {
20783        EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20784                rm.Encode(5, 0));
20785        return;
20786      }
20787    }
20788  }
20789  if (operand.IsImmediate()) {
20790    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
20791    if (IsUsingT32()) {
20792      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
20793      if (encoded_dt.IsValid() && rd.Is(rn)) {
20794        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20795          EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
20796                     rd.Encode(22, 12) |
20797                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20798                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20799                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20800          AdvanceIT();
20801          return;
20802        }
20803      }
20804    } else {
20805      // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
20806      if (encoded_dt.IsValid() && rd.Is(rn)) {
20807        if (cond.Is(al)) {
20808          EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
20809                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20810                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20811                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20812          return;
20813        }
20814      }
20815    }
20816  }
20817  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
20818}
20819
20820void Assembler::vorr(Condition cond,
20821                     DataType dt,
20822                     QRegister rd,
20823                     QRegister rn,
20824                     const QOperand& operand) {
20825  VIXL_ASSERT(AllowAssembler());
20826  CheckIT(cond);
20827  if (operand.IsRegister()) {
20828    QRegister rm = operand.GetRegister();
20829    USE(dt);
20830    if (IsUsingT32()) {
20831      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
20832      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20833        EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20834                   rm.Encode(5, 0));
20835        AdvanceIT();
20836        return;
20837      }
20838    } else {
20839      // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
20840      if (cond.Is(al)) {
20841        EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20842                rm.Encode(5, 0));
20843        return;
20844      }
20845    }
20846  }
20847  if (operand.IsImmediate()) {
20848    ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
20849    if (IsUsingT32()) {
20850      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
20851      if (encoded_dt.IsValid() && rd.Is(rn)) {
20852        if (cond.Is(al) || AllowStronglyDiscouraged()) {
20853          EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
20854                     rd.Encode(22, 12) |
20855                     (encoded_dt.GetEncodedImmediate() & 0xf) |
20856                     ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20857                     ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20858          AdvanceIT();
20859          return;
20860        }
20861      }
20862    } else {
20863      // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
20864      if (encoded_dt.IsValid() && rd.Is(rn)) {
20865        if (cond.Is(al)) {
20866          EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
20867                  rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20868                  ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20869                  ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20870          return;
20871        }
20872      }
20873    }
20874  }
20875  Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
20876}
20877
20878void Assembler::vpadal(Condition cond,
20879                       DataType dt,
20880                       DRegister rd,
20881                       DRegister rm) {
20882  VIXL_ASSERT(AllowAssembler());
20883  CheckIT(cond);
20884  Dt_op_size_2 encoded_dt(dt);
20885  if (IsUsingT32()) {
20886    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20887    if (encoded_dt.IsValid()) {
20888      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20889        EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20890                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20891                   rd.Encode(22, 12) | rm.Encode(5, 0));
20892        AdvanceIT();
20893        return;
20894      }
20895    }
20896  } else {
20897    // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
20898    if (encoded_dt.IsValid()) {
20899      if (cond.Is(al)) {
20900        EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20901                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20902                rd.Encode(22, 12) | rm.Encode(5, 0));
20903        return;
20904      }
20905    }
20906  }
20907  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
20908}
20909
20910void Assembler::vpadal(Condition cond,
20911                       DataType dt,
20912                       QRegister rd,
20913                       QRegister rm) {
20914  VIXL_ASSERT(AllowAssembler());
20915  CheckIT(cond);
20916  Dt_op_size_2 encoded_dt(dt);
20917  if (IsUsingT32()) {
20918    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
20919    if (encoded_dt.IsValid()) {
20920      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20921        EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20922                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20923                   rd.Encode(22, 12) | rm.Encode(5, 0));
20924        AdvanceIT();
20925        return;
20926      }
20927    }
20928  } else {
20929    // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
20930    if (encoded_dt.IsValid()) {
20931      if (cond.Is(al)) {
20932        EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20933                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20934                rd.Encode(22, 12) | rm.Encode(5, 0));
20935        return;
20936      }
20937    }
20938  }
20939  Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
20940}
20941
20942void Assembler::vpadd(
20943    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
20944  VIXL_ASSERT(AllowAssembler());
20945  CheckIT(cond);
20946  Dt_size_4 encoded_dt(dt);
20947  if (IsUsingT32()) {
20948    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20949    if (dt.Is(F32)) {
20950      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20951        EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20952                   rm.Encode(5, 0));
20953        AdvanceIT();
20954        return;
20955      }
20956    }
20957    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20958    if (encoded_dt.IsValid()) {
20959      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20960        EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
20961                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20962        AdvanceIT();
20963        return;
20964      }
20965    }
20966  } else {
20967    // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20968    if (dt.Is(F32)) {
20969      if (cond.Is(al)) {
20970        EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20971                rm.Encode(5, 0));
20972        return;
20973      }
20974    }
20975    // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20976    if (encoded_dt.IsValid()) {
20977      if (cond.Is(al)) {
20978        EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
20979                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20980        return;
20981      }
20982    }
20983  }
20984  Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
20985}
20986
20987void Assembler::vpaddl(Condition cond,
20988                       DataType dt,
20989                       DRegister rd,
20990                       DRegister rm) {
20991  VIXL_ASSERT(AllowAssembler());
20992  CheckIT(cond);
20993  Dt_op_size_2 encoded_dt(dt);
20994  if (IsUsingT32()) {
20995    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20996    if (encoded_dt.IsValid()) {
20997      if (cond.Is(al) || AllowStronglyDiscouraged()) {
20998        EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20999                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21000                   rd.Encode(22, 12) | rm.Encode(5, 0));
21001        AdvanceIT();
21002        return;
21003      }
21004    }
21005  } else {
21006    // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21007    if (encoded_dt.IsValid()) {
21008      if (cond.Is(al)) {
21009        EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21010                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21011                rd.Encode(22, 12) | rm.Encode(5, 0));
21012        return;
21013      }
21014    }
21015  }
21016  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
21017}
21018
21019void Assembler::vpaddl(Condition cond,
21020                       DataType dt,
21021                       QRegister rd,
21022                       QRegister rm) {
21023  VIXL_ASSERT(AllowAssembler());
21024  CheckIT(cond);
21025  Dt_op_size_2 encoded_dt(dt);
21026  if (IsUsingT32()) {
21027    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21028    if (encoded_dt.IsValid()) {
21029      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21030        EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21031                   ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21032                   rd.Encode(22, 12) | rm.Encode(5, 0));
21033        AdvanceIT();
21034        return;
21035      }
21036    }
21037  } else {
21038    // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21039    if (encoded_dt.IsValid()) {
21040      if (cond.Is(al)) {
21041        EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21042                ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21043                rd.Encode(22, 12) | rm.Encode(5, 0));
21044        return;
21045      }
21046    }
21047  }
21048  Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
21049}
21050
21051void Assembler::vpmax(
21052    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21053  VIXL_ASSERT(AllowAssembler());
21054  CheckIT(cond);
21055  Dt_U_size_1 encoded_dt(dt);
21056  if (IsUsingT32()) {
21057    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21058    if (dt.Is(F32)) {
21059      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21060        EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21061                   rm.Encode(5, 0));
21062        AdvanceIT();
21063        return;
21064      }
21065    }
21066    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21067    if (encoded_dt.IsValid()) {
21068      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21069        EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21070                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21071                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21072        AdvanceIT();
21073        return;
21074      }
21075    }
21076  } else {
21077    // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21078    if (dt.Is(F32)) {
21079      if (cond.Is(al)) {
21080        EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21081                rm.Encode(5, 0));
21082        return;
21083      }
21084    }
21085    // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21086    if (encoded_dt.IsValid()) {
21087      if (cond.Is(al)) {
21088        EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21089                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21090                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21091        return;
21092      }
21093    }
21094  }
21095  Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
21096}
21097
21098void Assembler::vpmin(
21099    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21100  VIXL_ASSERT(AllowAssembler());
21101  CheckIT(cond);
21102  Dt_U_size_1 encoded_dt(dt);
21103  if (IsUsingT32()) {
21104    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21105    if (dt.Is(F32)) {
21106      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21107        EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21108                   rm.Encode(5, 0));
21109        AdvanceIT();
21110        return;
21111      }
21112    }
21113    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21114    if (encoded_dt.IsValid()) {
21115      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21116        EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21117                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21118                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21119        AdvanceIT();
21120        return;
21121      }
21122    }
21123  } else {
21124    // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21125    if (dt.Is(F32)) {
21126      if (cond.Is(al)) {
21127        EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21128                rm.Encode(5, 0));
21129        return;
21130      }
21131    }
21132    // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21133    if (encoded_dt.IsValid()) {
21134      if (cond.Is(al)) {
21135        EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21136                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21137                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21138        return;
21139      }
21140    }
21141  }
21142  Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
21143}
21144
21145void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
21146  VIXL_ASSERT(AllowAssembler());
21147  CheckIT(cond);
21148  USE(dt);
21149  if (IsUsingT32()) {
21150    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
21151    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
21152      const DRegister& dreg = dreglist.GetFirstDRegister();
21153      unsigned len = dreglist.GetLength() * 2;
21154      EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
21155      AdvanceIT();
21156      return;
21157    }
21158  } else {
21159    // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
21160    if (cond.IsNotNever() &&
21161        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
21162      const DRegister& dreg = dreglist.GetFirstDRegister();
21163      unsigned len = dreglist.GetLength() * 2;
21164      EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
21165              (len & 0xff));
21166      return;
21167    }
21168  }
21169  Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
21170}
21171
21172void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
21173  VIXL_ASSERT(AllowAssembler());
21174  CheckIT(cond);
21175  USE(dt);
21176  if (IsUsingT32()) {
21177    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
21178    const SRegister& sreg = sreglist.GetFirstSRegister();
21179    unsigned len = sreglist.GetLength();
21180    EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
21181    AdvanceIT();
21182    return;
21183  } else {
21184    // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
21185    if (cond.IsNotNever()) {
21186      const SRegister& sreg = sreglist.GetFirstSRegister();
21187      unsigned len = sreglist.GetLength();
21188      EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
21189              (len & 0xff));
21190      return;
21191    }
21192  }
21193  Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
21194}
21195
21196void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
21197  VIXL_ASSERT(AllowAssembler());
21198  CheckIT(cond);
21199  USE(dt);
21200  if (IsUsingT32()) {
21201    // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
21202    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
21203      const DRegister& dreg = dreglist.GetFirstDRegister();
21204      unsigned len = dreglist.GetLength() * 2;
21205      EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
21206      AdvanceIT();
21207      return;
21208    }
21209  } else {
21210    // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
21211    if (cond.IsNotNever() &&
21212        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
21213      const DRegister& dreg = dreglist.GetFirstDRegister();
21214      unsigned len = dreglist.GetLength() * 2;
21215      EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
21216              (len & 0xff));
21217      return;
21218    }
21219  }
21220  Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
21221}
21222
21223void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
21224  VIXL_ASSERT(AllowAssembler());
21225  CheckIT(cond);
21226  USE(dt);
21227  if (IsUsingT32()) {
21228    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
21229    const SRegister& sreg = sreglist.GetFirstSRegister();
21230    unsigned len = sreglist.GetLength();
21231    EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
21232    AdvanceIT();
21233    return;
21234  } else {
21235    // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
21236    if (cond.IsNotNever()) {
21237      const SRegister& sreg = sreglist.GetFirstSRegister();
21238      unsigned len = sreglist.GetLength();
21239      EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
21240              (len & 0xff));
21241      return;
21242    }
21243  }
21244  Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
21245}
21246
21247void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
21248  VIXL_ASSERT(AllowAssembler());
21249  CheckIT(cond);
21250  Dt_size_5 encoded_dt(dt);
21251  if (IsUsingT32()) {
21252    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21253    if (encoded_dt.IsValid()) {
21254      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21255        EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
21256                   rd.Encode(22, 12) | rm.Encode(5, 0));
21257        AdvanceIT();
21258        return;
21259      }
21260    }
21261  } else {
21262    // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21263    if (encoded_dt.IsValid()) {
21264      if (cond.Is(al)) {
21265        EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
21266                rd.Encode(22, 12) | rm.Encode(5, 0));
21267        return;
21268      }
21269    }
21270  }
21271  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
21272}
21273
21274void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
21275  VIXL_ASSERT(AllowAssembler());
21276  CheckIT(cond);
21277  Dt_size_5 encoded_dt(dt);
21278  if (IsUsingT32()) {
21279    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21280    if (encoded_dt.IsValid()) {
21281      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21282        EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
21283                   rd.Encode(22, 12) | rm.Encode(5, 0));
21284        AdvanceIT();
21285        return;
21286      }
21287    }
21288  } else {
21289    // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21290    if (encoded_dt.IsValid()) {
21291      if (cond.Is(al)) {
21292        EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
21293                rd.Encode(22, 12) | rm.Encode(5, 0));
21294        return;
21295      }
21296    }
21297  }
21298  Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
21299}
21300
21301void Assembler::vqadd(
21302    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21303  VIXL_ASSERT(AllowAssembler());
21304  CheckIT(cond);
21305  Dt_U_size_3 encoded_dt(dt);
21306  if (IsUsingT32()) {
21307    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21308    if (encoded_dt.IsValid()) {
21309      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21310        EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21311                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21312                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21313        AdvanceIT();
21314        return;
21315      }
21316    }
21317  } else {
21318    // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21319    if (encoded_dt.IsValid()) {
21320      if (cond.Is(al)) {
21321        EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21322                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21323                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21324        return;
21325      }
21326    }
21327  }
21328  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
21329}
21330
21331void Assembler::vqadd(
21332    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21333  VIXL_ASSERT(AllowAssembler());
21334  CheckIT(cond);
21335  Dt_U_size_3 encoded_dt(dt);
21336  if (IsUsingT32()) {
21337    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21338    if (encoded_dt.IsValid()) {
21339      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21340        EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21341                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21342                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21343        AdvanceIT();
21344        return;
21345      }
21346    }
21347  } else {
21348    // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21349    if (encoded_dt.IsValid()) {
21350      if (cond.Is(al)) {
21351        EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21352                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21353                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21354        return;
21355      }
21356    }
21357  }
21358  Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
21359}
21360
21361void Assembler::vqdmlal(
21362    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21363  VIXL_ASSERT(AllowAssembler());
21364  CheckIT(cond);
21365  Dt_size_13 encoded_dt(dt);
21366  if (IsUsingT32()) {
21367    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21368    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21369      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21370        EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
21371                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21372        AdvanceIT();
21373        return;
21374      }
21375    }
21376  } else {
21377    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21378    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21379      if (cond.Is(al)) {
21380        EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
21381                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21382        return;
21383      }
21384    }
21385  }
21386  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
21387}
21388
21389void Assembler::vqdmlal(Condition cond,
21390                        DataType dt,
21391                        QRegister rd,
21392                        DRegister rn,
21393                        DRegister dm,
21394                        unsigned index) {
21395  VIXL_ASSERT(AllowAssembler());
21396  CheckIT(cond);
21397  Dt_size_13 encoded_dt(dt);
21398  if (IsUsingT32()) {
21399    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
21400    if (encoded_dt.IsValid() &&
21401        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21402         (!dt.Is(S16) && (index <= 1))) &&
21403        (dt.Is(S16) || dt.Is(S32))) {
21404      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21405        uint32_t shift = 4;
21406        if (dt.Is(S16)) {
21407          shift = 3;
21408        }
21409        uint32_t mvm = dm.GetCode() | index << shift;
21410        EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
21411                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21412                   ((mvm & 0x10) << 1));
21413        AdvanceIT();
21414        return;
21415      }
21416    }
21417  } else {
21418    // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
21419    if (encoded_dt.IsValid() &&
21420        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21421         (!dt.Is(S16) && (index <= 1))) &&
21422        (dt.Is(S16) || dt.Is(S32))) {
21423      if (cond.Is(al)) {
21424        uint32_t shift = 4;
21425        if (dt.Is(S16)) {
21426          shift = 3;
21427        }
21428        uint32_t mvm = dm.GetCode() | index << shift;
21429        EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
21430                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21431                ((mvm & 0x10) << 1));
21432        return;
21433      }
21434    }
21435  }
21436  Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
21437}
21438
21439void Assembler::vqdmlsl(
21440    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21441  VIXL_ASSERT(AllowAssembler());
21442  CheckIT(cond);
21443  Dt_size_13 encoded_dt(dt);
21444  if (IsUsingT32()) {
21445    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21446    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21447      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21448        EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
21449                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21450        AdvanceIT();
21451        return;
21452      }
21453    }
21454  } else {
21455    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21456    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21457      if (cond.Is(al)) {
21458        EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
21459                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21460        return;
21461      }
21462    }
21463  }
21464  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
21465}
21466
21467void Assembler::vqdmlsl(Condition cond,
21468                        DataType dt,
21469                        QRegister rd,
21470                        DRegister rn,
21471                        DRegister dm,
21472                        unsigned index) {
21473  VIXL_ASSERT(AllowAssembler());
21474  CheckIT(cond);
21475  Dt_size_13 encoded_dt(dt);
21476  if (IsUsingT32()) {
21477    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
21478    if (encoded_dt.IsValid() &&
21479        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21480         (!dt.Is(S16) && (index <= 1))) &&
21481        (dt.Is(S16) || dt.Is(S32))) {
21482      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21483        uint32_t shift = 4;
21484        if (dt.Is(S16)) {
21485          shift = 3;
21486        }
21487        uint32_t mvm = dm.GetCode() | index << shift;
21488        EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
21489                   rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21490                   ((mvm & 0x10) << 1));
21491        AdvanceIT();
21492        return;
21493      }
21494    }
21495  } else {
21496    // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
21497    if (encoded_dt.IsValid() &&
21498        ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21499         (!dt.Is(S16) && (index <= 1))) &&
21500        (dt.Is(S16) || dt.Is(S32))) {
21501      if (cond.Is(al)) {
21502        uint32_t shift = 4;
21503        if (dt.Is(S16)) {
21504          shift = 3;
21505        }
21506        uint32_t mvm = dm.GetCode() | index << shift;
21507        EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
21508                rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21509                ((mvm & 0x10) << 1));
21510        return;
21511      }
21512    }
21513  }
21514  Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
21515}
21516
21517void Assembler::vqdmulh(
21518    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21519  VIXL_ASSERT(AllowAssembler());
21520  CheckIT(cond);
21521  Dt_size_13 encoded_dt(dt);
21522  if (IsUsingT32()) {
21523    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21524    if (encoded_dt.IsValid()) {
21525      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21526        EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
21527                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21528        AdvanceIT();
21529        return;
21530      }
21531    }
21532  } else {
21533    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21534    if (encoded_dt.IsValid()) {
21535      if (cond.Is(al)) {
21536        EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
21537                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21538        return;
21539      }
21540    }
21541  }
21542  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21543}
21544
21545void Assembler::vqdmulh(
21546    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21547  VIXL_ASSERT(AllowAssembler());
21548  CheckIT(cond);
21549  Dt_size_13 encoded_dt(dt);
21550  if (IsUsingT32()) {
21551    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21552    if (encoded_dt.IsValid()) {
21553      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21554        EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
21555                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21556        AdvanceIT();
21557        return;
21558      }
21559    }
21560  } else {
21561    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21562    if (encoded_dt.IsValid()) {
21563      if (cond.Is(al)) {
21564        EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
21565                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21566        return;
21567      }
21568    }
21569  }
21570  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21571}
21572
21573void Assembler::vqdmulh(
21574    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
21575  VIXL_ASSERT(AllowAssembler());
21576  CheckIT(cond);
21577  Dt_size_13 encoded_dt(dt);
21578  if (IsUsingT32()) {
21579    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
21580    if (encoded_dt.IsValid() &&
21581        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21582         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21583          (rm.GetLane() <= 1))) &&
21584        (dt.Is(S16) || dt.Is(S32))) {
21585      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21586        EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
21587                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21588        AdvanceIT();
21589        return;
21590      }
21591    }
21592  } else {
21593    // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
21594    if (encoded_dt.IsValid() &&
21595        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21596         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21597          (rm.GetLane() <= 1))) &&
21598        (dt.Is(S16) || dt.Is(S32))) {
21599      if (cond.Is(al)) {
21600        EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
21601                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21602        return;
21603      }
21604    }
21605  }
21606  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21607}
21608
21609void Assembler::vqdmulh(
21610    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
21611  VIXL_ASSERT(AllowAssembler());
21612  CheckIT(cond);
21613  Dt_size_13 encoded_dt(dt);
21614  if (IsUsingT32()) {
21615    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
21616    if (encoded_dt.IsValid() &&
21617        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21618         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21619          (rm.GetLane() <= 1))) &&
21620        (dt.Is(S16) || dt.Is(S32))) {
21621      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21622        EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
21623                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21624        AdvanceIT();
21625        return;
21626      }
21627    }
21628  } else {
21629    // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
21630    if (encoded_dt.IsValid() &&
21631        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21632         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21633          (rm.GetLane() <= 1))) &&
21634        (dt.Is(S16) || dt.Is(S32))) {
21635      if (cond.Is(al)) {
21636        EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
21637                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21638        return;
21639      }
21640    }
21641  }
21642  Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21643}
21644
21645void Assembler::vqdmull(
21646    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
21647  VIXL_ASSERT(AllowAssembler());
21648  CheckIT(cond);
21649  Dt_size_13 encoded_dt(dt);
21650  if (IsUsingT32()) {
21651    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21652    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21653      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21654        EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
21655                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21656        AdvanceIT();
21657        return;
21658      }
21659    }
21660  } else {
21661    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21662    if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21663      if (cond.Is(al)) {
21664        EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
21665                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21666        return;
21667      }
21668    }
21669  }
21670  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
21671}
21672
21673void Assembler::vqdmull(
21674    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
21675  VIXL_ASSERT(AllowAssembler());
21676  CheckIT(cond);
21677  Dt_size_13 encoded_dt(dt);
21678  if (IsUsingT32()) {
21679    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
21680    if (encoded_dt.IsValid() &&
21681        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21682         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21683          (rm.GetLane() <= 1))) &&
21684        (dt.Is(S16) || dt.Is(S32))) {
21685      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21686        EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
21687                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21688        AdvanceIT();
21689        return;
21690      }
21691    }
21692  } else {
21693    // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
21694    if (encoded_dt.IsValid() &&
21695        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21696         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21697          (rm.GetLane() <= 1))) &&
21698        (dt.Is(S16) || dt.Is(S32))) {
21699      if (cond.Is(al)) {
21700        EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
21701                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21702        return;
21703      }
21704    }
21705  }
21706  Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
21707}
21708
21709void Assembler::vqmovn(Condition cond,
21710                       DataType dt,
21711                       DRegister rd,
21712                       QRegister rm) {
21713  VIXL_ASSERT(AllowAssembler());
21714  CheckIT(cond);
21715  Dt_op_size_3 encoded_dt(dt);
21716  if (IsUsingT32()) {
21717    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21718    if (encoded_dt.IsValid()) {
21719      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21720        EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21721                   ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
21722                   rd.Encode(22, 12) | rm.Encode(5, 0));
21723        AdvanceIT();
21724        return;
21725      }
21726    }
21727  } else {
21728    // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21729    if (encoded_dt.IsValid()) {
21730      if (cond.Is(al)) {
21731        EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21732                ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
21733                rd.Encode(22, 12) | rm.Encode(5, 0));
21734        return;
21735      }
21736    }
21737  }
21738  Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
21739}
21740
21741void Assembler::vqmovun(Condition cond,
21742                        DataType dt,
21743                        DRegister rd,
21744                        QRegister rm) {
21745  VIXL_ASSERT(AllowAssembler());
21746  CheckIT(cond);
21747  Dt_size_14 encoded_dt(dt);
21748  if (IsUsingT32()) {
21749    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21750    if (encoded_dt.IsValid()) {
21751      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21752        EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
21753                   rd.Encode(22, 12) | rm.Encode(5, 0));
21754        AdvanceIT();
21755        return;
21756      }
21757    }
21758  } else {
21759    // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21760    if (encoded_dt.IsValid()) {
21761      if (cond.Is(al)) {
21762        EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
21763                rd.Encode(22, 12) | rm.Encode(5, 0));
21764        return;
21765      }
21766    }
21767  }
21768  Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
21769}
21770
21771void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
21772  VIXL_ASSERT(AllowAssembler());
21773  CheckIT(cond);
21774  Dt_size_5 encoded_dt(dt);
21775  if (IsUsingT32()) {
21776    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21777    if (encoded_dt.IsValid()) {
21778      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21779        EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
21780                   rd.Encode(22, 12) | rm.Encode(5, 0));
21781        AdvanceIT();
21782        return;
21783      }
21784    }
21785  } else {
21786    // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21787    if (encoded_dt.IsValid()) {
21788      if (cond.Is(al)) {
21789        EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
21790                rd.Encode(22, 12) | rm.Encode(5, 0));
21791        return;
21792      }
21793    }
21794  }
21795  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
21796}
21797
21798void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
21799  VIXL_ASSERT(AllowAssembler());
21800  CheckIT(cond);
21801  Dt_size_5 encoded_dt(dt);
21802  if (IsUsingT32()) {
21803    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21804    if (encoded_dt.IsValid()) {
21805      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21806        EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
21807                   rd.Encode(22, 12) | rm.Encode(5, 0));
21808        AdvanceIT();
21809        return;
21810      }
21811    }
21812  } else {
21813    // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21814    if (encoded_dt.IsValid()) {
21815      if (cond.Is(al)) {
21816        EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
21817                rd.Encode(22, 12) | rm.Encode(5, 0));
21818        return;
21819      }
21820    }
21821  }
21822  Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
21823}
21824
21825void Assembler::vqrdmulh(
21826    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
21827  VIXL_ASSERT(AllowAssembler());
21828  CheckIT(cond);
21829  Dt_size_13 encoded_dt(dt);
21830  if (IsUsingT32()) {
21831    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21832    if (encoded_dt.IsValid()) {
21833      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21834        EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
21835                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21836        AdvanceIT();
21837        return;
21838      }
21839    }
21840  } else {
21841    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21842    if (encoded_dt.IsValid()) {
21843      if (cond.Is(al)) {
21844        EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
21845                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21846        return;
21847      }
21848    }
21849  }
21850  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21851}
21852
21853void Assembler::vqrdmulh(
21854    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
21855  VIXL_ASSERT(AllowAssembler());
21856  CheckIT(cond);
21857  Dt_size_13 encoded_dt(dt);
21858  if (IsUsingT32()) {
21859    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21860    if (encoded_dt.IsValid()) {
21861      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21862        EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
21863                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21864        AdvanceIT();
21865        return;
21866      }
21867    }
21868  } else {
21869    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21870    if (encoded_dt.IsValid()) {
21871      if (cond.Is(al)) {
21872        EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
21873                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21874        return;
21875      }
21876    }
21877  }
21878  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21879}
21880
21881void Assembler::vqrdmulh(
21882    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
21883  VIXL_ASSERT(AllowAssembler());
21884  CheckIT(cond);
21885  Dt_size_13 encoded_dt(dt);
21886  if (IsUsingT32()) {
21887    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
21888    if (encoded_dt.IsValid() &&
21889        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21890         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21891          (rm.GetLane() <= 1))) &&
21892        (dt.Is(S16) || dt.Is(S32))) {
21893      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21894        EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
21895                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21896        AdvanceIT();
21897        return;
21898      }
21899    }
21900  } else {
21901    // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
21902    if (encoded_dt.IsValid() &&
21903        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21904         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21905          (rm.GetLane() <= 1))) &&
21906        (dt.Is(S16) || dt.Is(S32))) {
21907      if (cond.Is(al)) {
21908        EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
21909                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21910        return;
21911      }
21912    }
21913  }
21914  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21915}
21916
21917void Assembler::vqrdmulh(
21918    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
21919  VIXL_ASSERT(AllowAssembler());
21920  CheckIT(cond);
21921  Dt_size_13 encoded_dt(dt);
21922  if (IsUsingT32()) {
21923    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
21924    if (encoded_dt.IsValid() &&
21925        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21926         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21927          (rm.GetLane() <= 1))) &&
21928        (dt.Is(S16) || dt.Is(S32))) {
21929      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21930        EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
21931                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21932        AdvanceIT();
21933        return;
21934      }
21935    }
21936  } else {
21937    // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
21938    if (encoded_dt.IsValid() &&
21939        (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21940         ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21941          (rm.GetLane() <= 1))) &&
21942        (dt.Is(S16) || dt.Is(S32))) {
21943      if (cond.Is(al)) {
21944        EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
21945                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21946        return;
21947      }
21948    }
21949  }
21950  Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21951}
21952
21953void Assembler::vqrshl(
21954    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
21955  VIXL_ASSERT(AllowAssembler());
21956  CheckIT(cond);
21957  Dt_U_size_3 encoded_dt(dt);
21958  if (IsUsingT32()) {
21959    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
21960    if (encoded_dt.IsValid()) {
21961      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21962        EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21963                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21964                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
21965        AdvanceIT();
21966        return;
21967      }
21968    }
21969  } else {
21970    // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
21971    if (encoded_dt.IsValid()) {
21972      if (cond.Is(al)) {
21973        EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21974                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21975                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
21976        return;
21977      }
21978    }
21979  }
21980  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
21981}
21982
21983void Assembler::vqrshl(
21984    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
21985  VIXL_ASSERT(AllowAssembler());
21986  CheckIT(cond);
21987  Dt_U_size_3 encoded_dt(dt);
21988  if (IsUsingT32()) {
21989    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
21990    if (encoded_dt.IsValid()) {
21991      if (cond.Is(al) || AllowStronglyDiscouraged()) {
21992        EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21993                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21994                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
21995        AdvanceIT();
21996        return;
21997      }
21998    }
21999  } else {
22000    // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
22001    if (encoded_dt.IsValid()) {
22002      if (cond.Is(al)) {
22003        EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22004                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22005                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22006        return;
22007      }
22008    }
22009  }
22010  Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
22011}
22012
22013void Assembler::vqrshrn(Condition cond,
22014                        DataType dt,
22015                        DRegister rd,
22016                        QRegister rm,
22017                        const QOperand& operand) {
22018  VIXL_ASSERT(AllowAssembler());
22019  CheckIT(cond);
22020  if (operand.IsImmediate()) {
22021    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22022      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22023      Dt_op_size_3 encoded_dt(dt);
22024      Dt_imm6_1 encoded_dt_2(dt);
22025      if (IsUsingT32()) {
22026        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22027        if (encoded_dt.IsValid() && (imm == 0)) {
22028          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22029            EmitT32_32(0xffb20280U |
22030                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22031                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22032                       rd.Encode(22, 12) | rm.Encode(5, 0));
22033            AdvanceIT();
22034            return;
22035          }
22036        }
22037        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22038        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22039          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22040            uint32_t imm6 = dt.GetSize() / 2 - imm;
22041            EmitT32_32(0xef800950U |
22042                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
22043                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22044                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22045            AdvanceIT();
22046            return;
22047          }
22048        }
22049      } else {
22050        // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22051        if (encoded_dt.IsValid() && (imm == 0)) {
22052          if (cond.Is(al)) {
22053            EmitA32(0xf3b20280U |
22054                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22055                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22056                    rd.Encode(22, 12) | rm.Encode(5, 0));
22057            return;
22058          }
22059        }
22060        // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22061        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22062          if (cond.Is(al)) {
22063            uint32_t imm6 = dt.GetSize() / 2 - imm;
22064            EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
22065                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22066                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22067            return;
22068          }
22069        }
22070      }
22071    }
22072  }
22073  Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
22074}
22075
22076void Assembler::vqrshrun(Condition cond,
22077                         DataType dt,
22078                         DRegister rd,
22079                         QRegister rm,
22080                         const QOperand& operand) {
22081  VIXL_ASSERT(AllowAssembler());
22082  CheckIT(cond);
22083  if (operand.IsImmediate()) {
22084    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22085      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22086      Dt_imm6_2 encoded_dt(dt);
22087      Dt_size_14 encoded_dt_2(dt);
22088      if (IsUsingT32()) {
22089        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22090        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22091          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22092            uint32_t imm6 = dt.GetSize() / 2 - imm;
22093            EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
22094                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22095                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22096            AdvanceIT();
22097            return;
22098          }
22099        }
22100        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22101        if (encoded_dt_2.IsValid() && (imm == 0)) {
22102          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22103            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22104                       rd.Encode(22, 12) | rm.Encode(5, 0));
22105            AdvanceIT();
22106            return;
22107          }
22108        }
22109      } else {
22110        // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22111        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22112          if (cond.Is(al)) {
22113            uint32_t imm6 = dt.GetSize() / 2 - imm;
22114            EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
22115                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22116                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22117            return;
22118          }
22119        }
22120        // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22121        if (encoded_dt_2.IsValid() && (imm == 0)) {
22122          if (cond.Is(al)) {
22123            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22124                    rd.Encode(22, 12) | rm.Encode(5, 0));
22125            return;
22126          }
22127        }
22128      }
22129    }
22130  }
22131  Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
22132}
22133
22134void Assembler::vqshl(Condition cond,
22135                      DataType dt,
22136                      DRegister rd,
22137                      DRegister rm,
22138                      const DOperand& operand) {
22139  VIXL_ASSERT(AllowAssembler());
22140  CheckIT(cond);
22141  if (operand.IsRegister()) {
22142    DRegister rn = operand.GetRegister();
22143    Dt_U_size_3 encoded_dt(dt);
22144    if (IsUsingT32()) {
22145      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
22146      if (encoded_dt.IsValid()) {
22147        if (cond.Is(al) || AllowStronglyDiscouraged()) {
22148          EmitT32_32(0xef000410U |
22149                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22150                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22151                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22152          AdvanceIT();
22153          return;
22154        }
22155      }
22156    } else {
22157      // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
22158      if (encoded_dt.IsValid()) {
22159        if (cond.Is(al)) {
22160          EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22161                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22162                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22163          return;
22164        }
22165      }
22166    }
22167  }
22168  if (operand.IsImmediate()) {
22169    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22170      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22171      Dt_L_imm6_1 encoded_dt(dt);
22172      if (IsUsingT32()) {
22173        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
22174        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22175          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22176            uint32_t imm6 = imm;
22177            EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
22178                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22179                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22180                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22181            AdvanceIT();
22182            return;
22183          }
22184        }
22185      } else {
22186        // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
22187        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22188          if (cond.Is(al)) {
22189            uint32_t imm6 = imm;
22190            EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
22191                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22192                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22193                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22194            return;
22195          }
22196        }
22197      }
22198    }
22199  }
22200  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
22201}
22202
22203void Assembler::vqshl(Condition cond,
22204                      DataType dt,
22205                      QRegister rd,
22206                      QRegister rm,
22207                      const QOperand& operand) {
22208  VIXL_ASSERT(AllowAssembler());
22209  CheckIT(cond);
22210  if (operand.IsRegister()) {
22211    QRegister rn = operand.GetRegister();
22212    Dt_U_size_3 encoded_dt(dt);
22213    if (IsUsingT32()) {
22214      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
22215      if (encoded_dt.IsValid()) {
22216        if (cond.Is(al) || AllowStronglyDiscouraged()) {
22217          EmitT32_32(0xef000450U |
22218                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22219                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22220                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22221          AdvanceIT();
22222          return;
22223        }
22224      }
22225    } else {
22226      // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
22227      if (encoded_dt.IsValid()) {
22228        if (cond.Is(al)) {
22229          EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22230                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22231                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22232          return;
22233        }
22234      }
22235    }
22236  }
22237  if (operand.IsImmediate()) {
22238    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22239      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22240      Dt_L_imm6_1 encoded_dt(dt);
22241      if (IsUsingT32()) {
22242        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
22243        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22244          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22245            uint32_t imm6 = imm;
22246            EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
22247                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22248                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22249                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22250            AdvanceIT();
22251            return;
22252          }
22253        }
22254      } else {
22255        // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
22256        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22257          if (cond.Is(al)) {
22258            uint32_t imm6 = imm;
22259            EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
22260                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22261                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22262                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22263            return;
22264          }
22265        }
22266      }
22267    }
22268  }
22269  Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
22270}
22271
22272void Assembler::vqshlu(Condition cond,
22273                       DataType dt,
22274                       DRegister rd,
22275                       DRegister rm,
22276                       const DOperand& operand) {
22277  VIXL_ASSERT(AllowAssembler());
22278  CheckIT(cond);
22279  if (operand.IsImmediate()) {
22280    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22281      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22282      Dt_L_imm6_2 encoded_dt(dt);
22283      if (IsUsingT32()) {
22284        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
22285        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22286          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22287            uint32_t imm6 = imm;
22288            EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
22289                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22290                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22291                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22292            AdvanceIT();
22293            return;
22294          }
22295        }
22296      } else {
22297        // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
22298        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22299          if (cond.Is(al)) {
22300            uint32_t imm6 = imm;
22301            EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
22302                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22303                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22304                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22305            return;
22306          }
22307        }
22308      }
22309    }
22310  }
22311  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
22312}
22313
22314void Assembler::vqshlu(Condition cond,
22315                       DataType dt,
22316                       QRegister rd,
22317                       QRegister rm,
22318                       const QOperand& operand) {
22319  VIXL_ASSERT(AllowAssembler());
22320  CheckIT(cond);
22321  if (operand.IsImmediate()) {
22322    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22323      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22324      Dt_L_imm6_2 encoded_dt(dt);
22325      if (IsUsingT32()) {
22326        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
22327        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22328          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22329            uint32_t imm6 = imm;
22330            EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
22331                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22332                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22333                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22334            AdvanceIT();
22335            return;
22336          }
22337        }
22338      } else {
22339        // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
22340        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22341          if (cond.Is(al)) {
22342            uint32_t imm6 = imm;
22343            EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
22344                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22345                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22346                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22347            return;
22348          }
22349        }
22350      }
22351    }
22352  }
22353  Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
22354}
22355
22356void Assembler::vqshrn(Condition cond,
22357                       DataType dt,
22358                       DRegister rd,
22359                       QRegister rm,
22360                       const QOperand& operand) {
22361  VIXL_ASSERT(AllowAssembler());
22362  CheckIT(cond);
22363  if (operand.IsImmediate()) {
22364    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22365      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22366      Dt_op_size_3 encoded_dt(dt);
22367      Dt_imm6_1 encoded_dt_2(dt);
22368      if (IsUsingT32()) {
22369        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22370        if (encoded_dt.IsValid() && (imm == 0)) {
22371          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22372            EmitT32_32(0xffb20280U |
22373                       ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22374                       ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22375                       rd.Encode(22, 12) | rm.Encode(5, 0));
22376            AdvanceIT();
22377            return;
22378          }
22379        }
22380        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22381        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22382          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22383            uint32_t imm6 = dt.GetSize() / 2 - imm;
22384            EmitT32_32(0xef800910U |
22385                       (encoded_dt_2.GetTypeEncodingValue() << 28) |
22386                       ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22387                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22388            AdvanceIT();
22389            return;
22390          }
22391        }
22392      } else {
22393        // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22394        if (encoded_dt.IsValid() && (imm == 0)) {
22395          if (cond.Is(al)) {
22396            EmitA32(0xf3b20280U |
22397                    ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22398                    ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22399                    rd.Encode(22, 12) | rm.Encode(5, 0));
22400            return;
22401          }
22402        }
22403        // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22404        if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22405          if (cond.Is(al)) {
22406            uint32_t imm6 = dt.GetSize() / 2 - imm;
22407            EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
22408                    ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22409                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22410            return;
22411          }
22412        }
22413      }
22414    }
22415  }
22416  Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
22417}
22418
22419void Assembler::vqshrun(Condition cond,
22420                        DataType dt,
22421                        DRegister rd,
22422                        QRegister rm,
22423                        const QOperand& operand) {
22424  VIXL_ASSERT(AllowAssembler());
22425  CheckIT(cond);
22426  if (operand.IsImmediate()) {
22427    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22428      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22429      Dt_imm6_2 encoded_dt(dt);
22430      Dt_size_14 encoded_dt_2(dt);
22431      if (IsUsingT32()) {
22432        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22433        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22434          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22435            uint32_t imm6 = dt.GetSize() / 2 - imm;
22436            EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
22437                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22438                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22439            AdvanceIT();
22440            return;
22441          }
22442        }
22443        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22444        if (encoded_dt_2.IsValid() && (imm == 0)) {
22445          if (cond.Is(al) || AllowStronglyDiscouraged()) {
22446            EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22447                       rd.Encode(22, 12) | rm.Encode(5, 0));
22448            AdvanceIT();
22449            return;
22450          }
22451        }
22452      } else {
22453        // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22454        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22455          if (cond.Is(al)) {
22456            uint32_t imm6 = dt.GetSize() / 2 - imm;
22457            EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
22458                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22459                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22460            return;
22461          }
22462        }
22463        // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22464        if (encoded_dt_2.IsValid() && (imm == 0)) {
22465          if (cond.Is(al)) {
22466            EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22467                    rd.Encode(22, 12) | rm.Encode(5, 0));
22468            return;
22469          }
22470        }
22471      }
22472    }
22473  }
22474  Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
22475}
22476
22477void Assembler::vqsub(
22478    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22479  VIXL_ASSERT(AllowAssembler());
22480  CheckIT(cond);
22481  Dt_U_size_3 encoded_dt(dt);
22482  if (IsUsingT32()) {
22483    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22484    if (encoded_dt.IsValid()) {
22485      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22486        EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22487                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22488                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22489        AdvanceIT();
22490        return;
22491      }
22492    }
22493  } else {
22494    // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22495    if (encoded_dt.IsValid()) {
22496      if (cond.Is(al)) {
22497        EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22498                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22499                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22500        return;
22501      }
22502    }
22503  }
22504  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
22505}
22506
22507void Assembler::vqsub(
22508    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22509  VIXL_ASSERT(AllowAssembler());
22510  CheckIT(cond);
22511  Dt_U_size_3 encoded_dt(dt);
22512  if (IsUsingT32()) {
22513    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22514    if (encoded_dt.IsValid()) {
22515      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22516        EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22517                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22518                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22519        AdvanceIT();
22520        return;
22521      }
22522    }
22523  } else {
22524    // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22525    if (encoded_dt.IsValid()) {
22526      if (cond.Is(al)) {
22527        EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22528                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22529                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22530        return;
22531      }
22532    }
22533  }
22534  Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
22535}
22536
22537void Assembler::vraddhn(
22538    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
22539  VIXL_ASSERT(AllowAssembler());
22540  CheckIT(cond);
22541  Dt_size_3 encoded_dt(dt);
22542  if (IsUsingT32()) {
22543    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
22544    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
22545      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22546        EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
22547                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22548        AdvanceIT();
22549        return;
22550      }
22551    }
22552  } else {
22553    // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
22554    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
22555      if (cond.Is(al)) {
22556        EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
22557                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22558        return;
22559      }
22560    }
22561  }
22562  Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
22563}
22564
22565void Assembler::vrecpe(Condition cond,
22566                       DataType dt,
22567                       DRegister rd,
22568                       DRegister rm) {
22569  VIXL_ASSERT(AllowAssembler());
22570  CheckIT(cond);
22571  Dt_F_size_4 encoded_dt(dt);
22572  if (IsUsingT32()) {
22573    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22574    if (encoded_dt.IsValid()) {
22575      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22576        EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22577                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22578                   rd.Encode(22, 12) | rm.Encode(5, 0));
22579        AdvanceIT();
22580        return;
22581      }
22582    }
22583  } else {
22584    // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22585    if (encoded_dt.IsValid()) {
22586      if (cond.Is(al)) {
22587        EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22588                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22589                rd.Encode(22, 12) | rm.Encode(5, 0));
22590        return;
22591      }
22592    }
22593  }
22594  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
22595}
22596
22597void Assembler::vrecpe(Condition cond,
22598                       DataType dt,
22599                       QRegister rd,
22600                       QRegister rm) {
22601  VIXL_ASSERT(AllowAssembler());
22602  CheckIT(cond);
22603  Dt_F_size_4 encoded_dt(dt);
22604  if (IsUsingT32()) {
22605    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22606    if (encoded_dt.IsValid()) {
22607      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22608        EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22609                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22610                   rd.Encode(22, 12) | rm.Encode(5, 0));
22611        AdvanceIT();
22612        return;
22613      }
22614    }
22615  } else {
22616    // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22617    if (encoded_dt.IsValid()) {
22618      if (cond.Is(al)) {
22619        EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22620                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22621                rd.Encode(22, 12) | rm.Encode(5, 0));
22622        return;
22623      }
22624    }
22625  }
22626  Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
22627}
22628
22629void Assembler::vrecps(
22630    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22631  VIXL_ASSERT(AllowAssembler());
22632  CheckIT(cond);
22633  if (IsUsingT32()) {
22634    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22635    if (dt.Is(F32)) {
22636      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22637        EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22638                   rm.Encode(5, 0));
22639        AdvanceIT();
22640        return;
22641      }
22642    }
22643  } else {
22644    // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22645    if (dt.Is(F32)) {
22646      if (cond.Is(al)) {
22647        EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22648                rm.Encode(5, 0));
22649        return;
22650      }
22651    }
22652  }
22653  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
22654}
22655
22656void Assembler::vrecps(
22657    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22658  VIXL_ASSERT(AllowAssembler());
22659  CheckIT(cond);
22660  if (IsUsingT32()) {
22661    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
22662    if (dt.Is(F32)) {
22663      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22664        EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22665                   rm.Encode(5, 0));
22666        AdvanceIT();
22667        return;
22668      }
22669    }
22670  } else {
22671    // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
22672    if (dt.Is(F32)) {
22673      if (cond.Is(al)) {
22674        EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22675                rm.Encode(5, 0));
22676        return;
22677      }
22678    }
22679  }
22680  Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
22681}
22682
22683void Assembler::vrev16(Condition cond,
22684                       DataType dt,
22685                       DRegister rd,
22686                       DRegister rm) {
22687  VIXL_ASSERT(AllowAssembler());
22688  CheckIT(cond);
22689  Dt_size_1 encoded_dt(dt);
22690  if (IsUsingT32()) {
22691    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22692    if (encoded_dt.IsValid()) {
22693      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22694        EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
22695                   rd.Encode(22, 12) | rm.Encode(5, 0));
22696        AdvanceIT();
22697        return;
22698      }
22699    }
22700  } else {
22701    // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22702    if (encoded_dt.IsValid()) {
22703      if (cond.Is(al)) {
22704        EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
22705                rd.Encode(22, 12) | rm.Encode(5, 0));
22706        return;
22707      }
22708    }
22709  }
22710  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
22711}
22712
22713void Assembler::vrev16(Condition cond,
22714                       DataType dt,
22715                       QRegister rd,
22716                       QRegister rm) {
22717  VIXL_ASSERT(AllowAssembler());
22718  CheckIT(cond);
22719  Dt_size_1 encoded_dt(dt);
22720  if (IsUsingT32()) {
22721    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22722    if (encoded_dt.IsValid()) {
22723      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22724        EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
22725                   rd.Encode(22, 12) | rm.Encode(5, 0));
22726        AdvanceIT();
22727        return;
22728      }
22729    }
22730  } else {
22731    // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22732    if (encoded_dt.IsValid()) {
22733      if (cond.Is(al)) {
22734        EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
22735                rd.Encode(22, 12) | rm.Encode(5, 0));
22736        return;
22737      }
22738    }
22739  }
22740  Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
22741}
22742
22743void Assembler::vrev32(Condition cond,
22744                       DataType dt,
22745                       DRegister rd,
22746                       DRegister rm) {
22747  VIXL_ASSERT(AllowAssembler());
22748  CheckIT(cond);
22749  Dt_size_15 encoded_dt(dt);
22750  if (IsUsingT32()) {
22751    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22752    if (encoded_dt.IsValid()) {
22753      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22754        EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
22755                   rd.Encode(22, 12) | rm.Encode(5, 0));
22756        AdvanceIT();
22757        return;
22758      }
22759    }
22760  } else {
22761    // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22762    if (encoded_dt.IsValid()) {
22763      if (cond.Is(al)) {
22764        EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
22765                rd.Encode(22, 12) | rm.Encode(5, 0));
22766        return;
22767      }
22768    }
22769  }
22770  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
22771}
22772
22773void Assembler::vrev32(Condition cond,
22774                       DataType dt,
22775                       QRegister rd,
22776                       QRegister rm) {
22777  VIXL_ASSERT(AllowAssembler());
22778  CheckIT(cond);
22779  Dt_size_15 encoded_dt(dt);
22780  if (IsUsingT32()) {
22781    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22782    if (encoded_dt.IsValid()) {
22783      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22784        EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
22785                   rd.Encode(22, 12) | rm.Encode(5, 0));
22786        AdvanceIT();
22787        return;
22788      }
22789    }
22790  } else {
22791    // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22792    if (encoded_dt.IsValid()) {
22793      if (cond.Is(al)) {
22794        EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
22795                rd.Encode(22, 12) | rm.Encode(5, 0));
22796        return;
22797      }
22798    }
22799  }
22800  Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
22801}
22802
22803void Assembler::vrev64(Condition cond,
22804                       DataType dt,
22805                       DRegister rd,
22806                       DRegister rm) {
22807  VIXL_ASSERT(AllowAssembler());
22808  CheckIT(cond);
22809  Dt_size_7 encoded_dt(dt);
22810  if (IsUsingT32()) {
22811    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22812    if (encoded_dt.IsValid()) {
22813      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22814        EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
22815                   rd.Encode(22, 12) | rm.Encode(5, 0));
22816        AdvanceIT();
22817        return;
22818      }
22819    }
22820  } else {
22821    // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22822    if (encoded_dt.IsValid()) {
22823      if (cond.Is(al)) {
22824        EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
22825                rd.Encode(22, 12) | rm.Encode(5, 0));
22826        return;
22827      }
22828    }
22829  }
22830  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
22831}
22832
22833void Assembler::vrev64(Condition cond,
22834                       DataType dt,
22835                       QRegister rd,
22836                       QRegister rm) {
22837  VIXL_ASSERT(AllowAssembler());
22838  CheckIT(cond);
22839  Dt_size_7 encoded_dt(dt);
22840  if (IsUsingT32()) {
22841    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22842    if (encoded_dt.IsValid()) {
22843      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22844        EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
22845                   rd.Encode(22, 12) | rm.Encode(5, 0));
22846        AdvanceIT();
22847        return;
22848      }
22849    }
22850  } else {
22851    // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22852    if (encoded_dt.IsValid()) {
22853      if (cond.Is(al)) {
22854        EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
22855                rd.Encode(22, 12) | rm.Encode(5, 0));
22856        return;
22857      }
22858    }
22859  }
22860  Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
22861}
22862
22863void Assembler::vrhadd(
22864    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
22865  VIXL_ASSERT(AllowAssembler());
22866  CheckIT(cond);
22867  Dt_U_size_1 encoded_dt(dt);
22868  if (IsUsingT32()) {
22869    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22870    if (encoded_dt.IsValid()) {
22871      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22872        EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22873                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22874                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22875        AdvanceIT();
22876        return;
22877      }
22878    }
22879  } else {
22880    // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22881    if (encoded_dt.IsValid()) {
22882      if (cond.Is(al)) {
22883        EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22884                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22885                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22886        return;
22887      }
22888    }
22889  }
22890  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
22891}
22892
22893void Assembler::vrhadd(
22894    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
22895  VIXL_ASSERT(AllowAssembler());
22896  CheckIT(cond);
22897  Dt_U_size_1 encoded_dt(dt);
22898  if (IsUsingT32()) {
22899    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22900    if (encoded_dt.IsValid()) {
22901      if (cond.Is(al) || AllowStronglyDiscouraged()) {
22902        EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22903                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22904                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22905        AdvanceIT();
22906        return;
22907      }
22908    }
22909  } else {
22910    // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22911    if (encoded_dt.IsValid()) {
22912      if (cond.Is(al)) {
22913        EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22914                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22915                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22916        return;
22917      }
22918    }
22919  }
22920  Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
22921}
22922
22923void Assembler::vrinta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
22924  VIXL_ASSERT(AllowAssembler());
22925  CheckIT(al);
22926  if (IsUsingT32()) {
22927    // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; T1
22928    if (dt1.Is(F32) && dt2.Is(F32)) {
22929      EmitT32_32(0xffba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
22930      AdvanceIT();
22931      return;
22932    }
22933    // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; T1
22934    if (dt1.Is(F64) && dt2.Is(F64)) {
22935      EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22936      AdvanceIT();
22937      return;
22938    }
22939  } else {
22940    // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; A1
22941    if (dt1.Is(F32) && dt2.Is(F32)) {
22942      EmitA32(0xf3ba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
22943      return;
22944    }
22945    // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; A1
22946    if (dt1.Is(F64) && dt2.Is(F64)) {
22947      EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22948      return;
22949    }
22950  }
22951  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
22952}
22953
22954void Assembler::vrinta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
22955  VIXL_ASSERT(AllowAssembler());
22956  CheckIT(al);
22957  if (IsUsingT32()) {
22958    // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; T1
22959    if (dt1.Is(F32) && dt2.Is(F32)) {
22960      EmitT32_32(0xffba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
22961      AdvanceIT();
22962      return;
22963    }
22964  } else {
22965    // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; A1
22966    if (dt1.Is(F32) && dt2.Is(F32)) {
22967      EmitA32(0xf3ba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
22968      return;
22969    }
22970  }
22971  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
22972}
22973
22974void Assembler::vrinta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
22975  VIXL_ASSERT(AllowAssembler());
22976  CheckIT(al);
22977  if (IsUsingT32()) {
22978    // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; T1
22979    if (dt1.Is(F32) && dt2.Is(F32)) {
22980      EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22981      AdvanceIT();
22982      return;
22983    }
22984  } else {
22985    // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; A1
22986    if (dt1.Is(F32) && dt2.Is(F32)) {
22987      EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22988      return;
22989    }
22990  }
22991  Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
22992}
22993
22994void Assembler::vrintm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
22995  VIXL_ASSERT(AllowAssembler());
22996  CheckIT(al);
22997  if (IsUsingT32()) {
22998    // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; T1
22999    if (dt1.Is(F32) && dt2.Is(F32)) {
23000      EmitT32_32(0xffba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
23001      AdvanceIT();
23002      return;
23003    }
23004    // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; T1
23005    if (dt1.Is(F64) && dt2.Is(F64)) {
23006      EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23007      AdvanceIT();
23008      return;
23009    }
23010  } else {
23011    // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; A1
23012    if (dt1.Is(F32) && dt2.Is(F32)) {
23013      EmitA32(0xf3ba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
23014      return;
23015    }
23016    // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; A1
23017    if (dt1.Is(F64) && dt2.Is(F64)) {
23018      EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23019      return;
23020    }
23021  }
23022  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23023}
23024
23025void Assembler::vrintm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23026  VIXL_ASSERT(AllowAssembler());
23027  CheckIT(al);
23028  if (IsUsingT32()) {
23029    // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; T1
23030    if (dt1.Is(F32) && dt2.Is(F32)) {
23031      EmitT32_32(0xffba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23032      AdvanceIT();
23033      return;
23034    }
23035  } else {
23036    // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; A1
23037    if (dt1.Is(F32) && dt2.Is(F32)) {
23038      EmitA32(0xf3ba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23039      return;
23040    }
23041  }
23042  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23043}
23044
23045void Assembler::vrintm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23046  VIXL_ASSERT(AllowAssembler());
23047  CheckIT(al);
23048  if (IsUsingT32()) {
23049    // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; T1
23050    if (dt1.Is(F32) && dt2.Is(F32)) {
23051      EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23052      AdvanceIT();
23053      return;
23054    }
23055  } else {
23056    // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; A1
23057    if (dt1.Is(F32) && dt2.Is(F32)) {
23058      EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23059      return;
23060    }
23061  }
23062  Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23063}
23064
23065void Assembler::vrintn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23066  VIXL_ASSERT(AllowAssembler());
23067  CheckIT(al);
23068  if (IsUsingT32()) {
23069    // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; T1
23070    if (dt1.Is(F32) && dt2.Is(F32)) {
23071      EmitT32_32(0xffba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
23072      AdvanceIT();
23073      return;
23074    }
23075    // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; T1
23076    if (dt1.Is(F64) && dt2.Is(F64)) {
23077      EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23078      AdvanceIT();
23079      return;
23080    }
23081  } else {
23082    // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; A1
23083    if (dt1.Is(F32) && dt2.Is(F32)) {
23084      EmitA32(0xf3ba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
23085      return;
23086    }
23087    // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; A1
23088    if (dt1.Is(F64) && dt2.Is(F64)) {
23089      EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23090      return;
23091    }
23092  }
23093  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23094}
23095
23096void Assembler::vrintn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23097  VIXL_ASSERT(AllowAssembler());
23098  CheckIT(al);
23099  if (IsUsingT32()) {
23100    // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; T1
23101    if (dt1.Is(F32) && dt2.Is(F32)) {
23102      EmitT32_32(0xffba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
23103      AdvanceIT();
23104      return;
23105    }
23106  } else {
23107    // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; A1
23108    if (dt1.Is(F32) && dt2.Is(F32)) {
23109      EmitA32(0xf3ba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
23110      return;
23111    }
23112  }
23113  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23114}
23115
23116void Assembler::vrintn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23117  VIXL_ASSERT(AllowAssembler());
23118  CheckIT(al);
23119  if (IsUsingT32()) {
23120    // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; T1
23121    if (dt1.Is(F32) && dt2.Is(F32)) {
23122      EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23123      AdvanceIT();
23124      return;
23125    }
23126  } else {
23127    // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; A1
23128    if (dt1.Is(F32) && dt2.Is(F32)) {
23129      EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23130      return;
23131    }
23132  }
23133  Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23134}
23135
23136void Assembler::vrintp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23137  VIXL_ASSERT(AllowAssembler());
23138  CheckIT(al);
23139  if (IsUsingT32()) {
23140    // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; T1
23141    if (dt1.Is(F32) && dt2.Is(F32)) {
23142      EmitT32_32(0xffba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
23143      AdvanceIT();
23144      return;
23145    }
23146    // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; T1
23147    if (dt1.Is(F64) && dt2.Is(F64)) {
23148      EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23149      AdvanceIT();
23150      return;
23151    }
23152  } else {
23153    // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; A1
23154    if (dt1.Is(F32) && dt2.Is(F32)) {
23155      EmitA32(0xf3ba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
23156      return;
23157    }
23158    // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; A1
23159    if (dt1.Is(F64) && dt2.Is(F64)) {
23160      EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23161      return;
23162    }
23163  }
23164  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23165}
23166
23167void Assembler::vrintp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23168  VIXL_ASSERT(AllowAssembler());
23169  CheckIT(al);
23170  if (IsUsingT32()) {
23171    // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; T1
23172    if (dt1.Is(F32) && dt2.Is(F32)) {
23173      EmitT32_32(0xffba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23174      AdvanceIT();
23175      return;
23176    }
23177  } else {
23178    // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; A1
23179    if (dt1.Is(F32) && dt2.Is(F32)) {
23180      EmitA32(0xf3ba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23181      return;
23182    }
23183  }
23184  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23185}
23186
23187void Assembler::vrintp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23188  VIXL_ASSERT(AllowAssembler());
23189  CheckIT(al);
23190  if (IsUsingT32()) {
23191    // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; T1
23192    if (dt1.Is(F32) && dt2.Is(F32)) {
23193      EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23194      AdvanceIT();
23195      return;
23196    }
23197  } else {
23198    // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; A1
23199    if (dt1.Is(F32) && dt2.Is(F32)) {
23200      EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23201      return;
23202    }
23203  }
23204  Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23205}
23206
23207void Assembler::vrintr(
23208    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23209  VIXL_ASSERT(AllowAssembler());
23210  CheckIT(cond);
23211  if (IsUsingT32()) {
23212    // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23213    if (dt1.Is(F32) && dt2.Is(F32)) {
23214      EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23215      AdvanceIT();
23216      return;
23217    }
23218  } else {
23219    // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23220    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23221      EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23222              rm.Encode(5, 0));
23223      return;
23224    }
23225  }
23226  Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
23227}
23228
23229void Assembler::vrintr(
23230    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23231  VIXL_ASSERT(AllowAssembler());
23232  CheckIT(cond);
23233  if (IsUsingT32()) {
23234    // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23235    if (dt1.Is(F64) && dt2.Is(F64)) {
23236      EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23237      AdvanceIT();
23238      return;
23239    }
23240  } else {
23241    // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23242    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23243      EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23244              rm.Encode(5, 0));
23245      return;
23246    }
23247  }
23248  Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
23249}
23250
23251void Assembler::vrintx(
23252    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23253  VIXL_ASSERT(AllowAssembler());
23254  CheckIT(cond);
23255  if (IsUsingT32()) {
23256    // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; T1
23257    if (dt1.Is(F32) && dt2.Is(F32)) {
23258      EmitT32_32(0xffba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
23259      AdvanceIT();
23260      return;
23261    }
23262    // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23263    if (dt1.Is(F64) && dt2.Is(F64)) {
23264      EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23265      AdvanceIT();
23266      return;
23267    }
23268  } else {
23269    // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; A1
23270    if (dt1.Is(F32) && dt2.Is(F32)) {
23271      EmitA32(0xf3ba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
23272      return;
23273    }
23274    // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23275    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23276      EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23277              rm.Encode(5, 0));
23278      return;
23279    }
23280  }
23281  Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
23282}
23283
23284void Assembler::vrintx(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23285  VIXL_ASSERT(AllowAssembler());
23286  CheckIT(al);
23287  if (IsUsingT32()) {
23288    // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; T1
23289    if (dt1.Is(F32) && dt2.Is(F32)) {
23290      EmitT32_32(0xffba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23291      AdvanceIT();
23292      return;
23293    }
23294  } else {
23295    // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; A1
23296    if (dt1.Is(F32) && dt2.Is(F32)) {
23297      EmitA32(0xf3ba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23298      return;
23299    }
23300  }
23301  Delegate(kVrintx, &Assembler::vrintx, dt1, dt2, rd, rm);
23302}
23303
23304void Assembler::vrintx(
23305    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23306  VIXL_ASSERT(AllowAssembler());
23307  CheckIT(cond);
23308  if (IsUsingT32()) {
23309    // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23310    if (dt1.Is(F32) && dt2.Is(F32)) {
23311      EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23312      AdvanceIT();
23313      return;
23314    }
23315  } else {
23316    // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23317    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23318      EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23319              rm.Encode(5, 0));
23320      return;
23321    }
23322  }
23323  Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
23324}
23325
23326void Assembler::vrintz(
23327    Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
23328  VIXL_ASSERT(AllowAssembler());
23329  CheckIT(cond);
23330  if (IsUsingT32()) {
23331    // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; T1
23332    if (dt1.Is(F32) && dt2.Is(F32)) {
23333      EmitT32_32(0xffba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
23334      AdvanceIT();
23335      return;
23336    }
23337    // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23338    if (dt1.Is(F64) && dt2.Is(F64)) {
23339      EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23340      AdvanceIT();
23341      return;
23342    }
23343  } else {
23344    // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; A1
23345    if (dt1.Is(F32) && dt2.Is(F32)) {
23346      EmitA32(0xf3ba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
23347      return;
23348    }
23349    // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23350    if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23351      EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23352              rm.Encode(5, 0));
23353      return;
23354    }
23355  }
23356  Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
23357}
23358
23359void Assembler::vrintz(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
23360  VIXL_ASSERT(AllowAssembler());
23361  CheckIT(al);
23362  if (IsUsingT32()) {
23363    // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; T1
23364    if (dt1.Is(F32) && dt2.Is(F32)) {
23365      EmitT32_32(0xffba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23366      AdvanceIT();
23367      return;
23368    }
23369  } else {
23370    // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; A1
23371    if (dt1.Is(F32) && dt2.Is(F32)) {
23372      EmitA32(0xf3ba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23373      return;
23374    }
23375  }
23376  Delegate(kVrintz, &Assembler::vrintz, dt1, dt2, rd, rm);
23377}
23378
23379void Assembler::vrintz(
23380    Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
23381  VIXL_ASSERT(AllowAssembler());
23382  CheckIT(cond);
23383  if (IsUsingT32()) {
23384    // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23385    if (dt1.Is(F32) && dt2.Is(F32)) {
23386      EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23387      AdvanceIT();
23388      return;
23389    }
23390  } else {
23391    // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23392    if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23393      EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23394              rm.Encode(5, 0));
23395      return;
23396    }
23397  }
23398  Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
23399}
23400
23401void Assembler::vrshl(
23402    Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
23403  VIXL_ASSERT(AllowAssembler());
23404  CheckIT(cond);
23405  Dt_U_size_3 encoded_dt(dt);
23406  if (IsUsingT32()) {
23407    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23408    if (encoded_dt.IsValid()) {
23409      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23410        EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23411                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23412                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23413        AdvanceIT();
23414        return;
23415      }
23416    }
23417  } else {
23418    // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23419    if (encoded_dt.IsValid()) {
23420      if (cond.Is(al)) {
23421        EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23422                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23423                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23424        return;
23425      }
23426    }
23427  }
23428  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
23429}
23430
23431void Assembler::vrshl(
23432    Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
23433  VIXL_ASSERT(AllowAssembler());
23434  CheckIT(cond);
23435  Dt_U_size_3 encoded_dt(dt);
23436  if (IsUsingT32()) {
23437    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23438    if (encoded_dt.IsValid()) {
23439      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23440        EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23441                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23442                   rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23443        AdvanceIT();
23444        return;
23445      }
23446    }
23447  } else {
23448    // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23449    if (encoded_dt.IsValid()) {
23450      if (cond.Is(al)) {
23451        EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23452                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23453                rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23454        return;
23455      }
23456    }
23457  }
23458  Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
23459}
23460
23461void Assembler::vrshr(Condition cond,
23462                      DataType dt,
23463                      DRegister rd,
23464                      DRegister rm,
23465                      const DOperand& operand) {
23466  VIXL_ASSERT(AllowAssembler());
23467  CheckIT(cond);
23468  if (operand.IsImmediate()) {
23469    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23470      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23471      Dt_L_imm6_1 encoded_dt(dt);
23472      if (IsUsingT32()) {
23473        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23474        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23475          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23476            uint32_t imm6 = dt.GetSize() - imm;
23477            EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
23478                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23479                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23480                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23481            AdvanceIT();
23482            return;
23483          }
23484        }
23485        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
23486        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23487          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23488            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23489                       rm.Encode(5, 0));
23490            AdvanceIT();
23491            return;
23492          }
23493        }
23494      } else {
23495        // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23496        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23497          if (cond.Is(al)) {
23498            uint32_t imm6 = dt.GetSize() - imm;
23499            EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
23500                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23501                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23502                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23503            return;
23504          }
23505        }
23506        // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
23507        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23508          if (cond.Is(al)) {
23509            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23510                    rm.Encode(5, 0));
23511            return;
23512          }
23513        }
23514      }
23515    }
23516  }
23517  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
23518}
23519
23520void Assembler::vrshr(Condition cond,
23521                      DataType dt,
23522                      QRegister rd,
23523                      QRegister rm,
23524                      const QOperand& operand) {
23525  VIXL_ASSERT(AllowAssembler());
23526  CheckIT(cond);
23527  if (operand.IsImmediate()) {
23528    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23529      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23530      Dt_L_imm6_1 encoded_dt(dt);
23531      if (IsUsingT32()) {
23532        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23533        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23534          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23535            uint32_t imm6 = dt.GetSize() - imm;
23536            EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
23537                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23538                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23539                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23540            AdvanceIT();
23541            return;
23542          }
23543        }
23544        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
23545        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23546          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23547            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23548                       rm.Encode(5, 0));
23549            AdvanceIT();
23550            return;
23551          }
23552        }
23553      } else {
23554        // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23555        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23556          if (cond.Is(al)) {
23557            uint32_t imm6 = dt.GetSize() - imm;
23558            EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
23559                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23560                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23561                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23562            return;
23563          }
23564        }
23565        // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
23566        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23567          if (cond.Is(al)) {
23568            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23569                    rm.Encode(5, 0));
23570            return;
23571          }
23572        }
23573      }
23574    }
23575  }
23576  Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
23577}
23578
23579void Assembler::vrshrn(Condition cond,
23580                       DataType dt,
23581                       DRegister rd,
23582                       QRegister rm,
23583                       const QOperand& operand) {
23584  VIXL_ASSERT(AllowAssembler());
23585  CheckIT(cond);
23586  if (operand.IsImmediate()) {
23587    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23588      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23589      Dt_imm6_3 encoded_dt(dt);
23590      Dt_size_3 encoded_dt_2(dt);
23591      if (IsUsingT32()) {
23592        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
23593        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23594          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23595            uint32_t imm6 = dt.GetSize() / 2 - imm;
23596            EmitT32_32(0xef800850U |
23597                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23598                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23599            AdvanceIT();
23600            return;
23601          }
23602        }
23603        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23604        if (encoded_dt_2.IsValid() && (imm == 0)) {
23605          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23606            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
23607                       rd.Encode(22, 12) | rm.Encode(5, 0));
23608            AdvanceIT();
23609            return;
23610          }
23611        }
23612      } else {
23613        // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
23614        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23615          if (cond.Is(al)) {
23616            uint32_t imm6 = dt.GetSize() / 2 - imm;
23617            EmitA32(0xf2800850U |
23618                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23619                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23620            return;
23621          }
23622        }
23623        // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23624        if (encoded_dt_2.IsValid() && (imm == 0)) {
23625          if (cond.Is(al)) {
23626            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
23627                    rd.Encode(22, 12) | rm.Encode(5, 0));
23628            return;
23629          }
23630        }
23631      }
23632    }
23633  }
23634  Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
23635}
23636
23637void Assembler::vrsqrte(Condition cond,
23638                        DataType dt,
23639                        DRegister rd,
23640                        DRegister rm) {
23641  VIXL_ASSERT(AllowAssembler());
23642  CheckIT(cond);
23643  Dt_F_size_4 encoded_dt(dt);
23644  if (IsUsingT32()) {
23645    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23646    if (encoded_dt.IsValid()) {
23647      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23648        EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23649                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23650                   rd.Encode(22, 12) | rm.Encode(5, 0));
23651        AdvanceIT();
23652        return;
23653      }
23654    }
23655  } else {
23656    // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23657    if (encoded_dt.IsValid()) {
23658      if (cond.Is(al)) {
23659        EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23660                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23661                rd.Encode(22, 12) | rm.Encode(5, 0));
23662        return;
23663      }
23664    }
23665  }
23666  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
23667}
23668
23669void Assembler::vrsqrte(Condition cond,
23670                        DataType dt,
23671                        QRegister rd,
23672                        QRegister rm) {
23673  VIXL_ASSERT(AllowAssembler());
23674  CheckIT(cond);
23675  Dt_F_size_4 encoded_dt(dt);
23676  if (IsUsingT32()) {
23677    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23678    if (encoded_dt.IsValid()) {
23679      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23680        EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23681                   ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23682                   rd.Encode(22, 12) | rm.Encode(5, 0));
23683        AdvanceIT();
23684        return;
23685      }
23686    }
23687  } else {
23688    // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23689    if (encoded_dt.IsValid()) {
23690      if (cond.Is(al)) {
23691        EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23692                ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23693                rd.Encode(22, 12) | rm.Encode(5, 0));
23694        return;
23695      }
23696    }
23697  }
23698  Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
23699}
23700
23701void Assembler::vrsqrts(
23702    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23703  VIXL_ASSERT(AllowAssembler());
23704  CheckIT(cond);
23705  if (IsUsingT32()) {
23706    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23707    if (dt.Is(F32)) {
23708      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23709        EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23710                   rm.Encode(5, 0));
23711        AdvanceIT();
23712        return;
23713      }
23714    }
23715  } else {
23716    // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23717    if (dt.Is(F32)) {
23718      if (cond.Is(al)) {
23719        EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23720                rm.Encode(5, 0));
23721        return;
23722      }
23723    }
23724  }
23725  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
23726}
23727
23728void Assembler::vrsqrts(
23729    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
23730  VIXL_ASSERT(AllowAssembler());
23731  CheckIT(cond);
23732  if (IsUsingT32()) {
23733    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23734    if (dt.Is(F32)) {
23735      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23736        EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23737                   rm.Encode(5, 0));
23738        AdvanceIT();
23739        return;
23740      }
23741    }
23742  } else {
23743    // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23744    if (dt.Is(F32)) {
23745      if (cond.Is(al)) {
23746        EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23747                rm.Encode(5, 0));
23748        return;
23749      }
23750    }
23751  }
23752  Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
23753}
23754
23755void Assembler::vrsra(Condition cond,
23756                      DataType dt,
23757                      DRegister rd,
23758                      DRegister rm,
23759                      const DOperand& operand) {
23760  VIXL_ASSERT(AllowAssembler());
23761  CheckIT(cond);
23762  if (operand.IsImmediate()) {
23763    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23764      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23765      Dt_L_imm6_1 encoded_dt(dt);
23766      if (IsUsingT32()) {
23767        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23768        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23769          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23770            uint32_t imm6 = dt.GetSize() - imm;
23771            EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
23772                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23773                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23774                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23775            AdvanceIT();
23776            return;
23777          }
23778        }
23779      } else {
23780        // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23781        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23782          if (cond.Is(al)) {
23783            uint32_t imm6 = dt.GetSize() - imm;
23784            EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
23785                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23786                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23787                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23788            return;
23789          }
23790        }
23791      }
23792    }
23793  }
23794  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
23795}
23796
23797void Assembler::vrsra(Condition cond,
23798                      DataType dt,
23799                      QRegister rd,
23800                      QRegister rm,
23801                      const QOperand& operand) {
23802  VIXL_ASSERT(AllowAssembler());
23803  CheckIT(cond);
23804  if (operand.IsImmediate()) {
23805    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23806      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23807      Dt_L_imm6_1 encoded_dt(dt);
23808      if (IsUsingT32()) {
23809        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23810        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23811          if (cond.Is(al) || AllowStronglyDiscouraged()) {
23812            uint32_t imm6 = dt.GetSize() - imm;
23813            EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
23814                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23815                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23816                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23817            AdvanceIT();
23818            return;
23819          }
23820        }
23821      } else {
23822        // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23823        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23824          if (cond.Is(al)) {
23825            uint32_t imm6 = dt.GetSize() - imm;
23826            EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
23827                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23828                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23829                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23830            return;
23831          }
23832        }
23833      }
23834    }
23835  }
23836  Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
23837}
23838
23839void Assembler::vrsubhn(
23840    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
23841  VIXL_ASSERT(AllowAssembler());
23842  CheckIT(cond);
23843  Dt_size_3 encoded_dt(dt);
23844  if (IsUsingT32()) {
23845    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23846    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23847      if (cond.Is(al) || AllowStronglyDiscouraged()) {
23848        EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
23849                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23850        AdvanceIT();
23851        return;
23852      }
23853    }
23854  } else {
23855    // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23856    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23857      if (cond.Is(al)) {
23858        EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
23859                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23860        return;
23861      }
23862    }
23863  }
23864  Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
23865}
23866
23867void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23868  VIXL_ASSERT(AllowAssembler());
23869  CheckIT(al);
23870  if (IsUsingT32()) {
23871    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
23872    if (OutsideITBlock() && dt.Is(F64)) {
23873      EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23874                 rm.Encode(5, 0));
23875      AdvanceIT();
23876      return;
23877    }
23878  } else {
23879    // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
23880    if (dt.Is(F64)) {
23881      EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23882              rm.Encode(5, 0));
23883      return;
23884    }
23885  }
23886  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
23887}
23888
23889void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
23890  VIXL_ASSERT(AllowAssembler());
23891  CheckIT(al);
23892  if (IsUsingT32()) {
23893    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
23894    if (OutsideITBlock() && dt.Is(F32)) {
23895      EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23896                 rm.Encode(5, 0));
23897      AdvanceIT();
23898      return;
23899    }
23900  } else {
23901    // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
23902    if (dt.Is(F32)) {
23903      EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23904              rm.Encode(5, 0));
23905      return;
23906    }
23907  }
23908  Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
23909}
23910
23911void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23912  VIXL_ASSERT(AllowAssembler());
23913  CheckIT(al);
23914  if (IsUsingT32()) {
23915    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
23916    if (OutsideITBlock() && dt.Is(F64)) {
23917      EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23918                 rm.Encode(5, 0));
23919      AdvanceIT();
23920      return;
23921    }
23922  } else {
23923    // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
23924    if (dt.Is(F64)) {
23925      EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23926              rm.Encode(5, 0));
23927      return;
23928    }
23929  }
23930  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
23931}
23932
23933void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
23934  VIXL_ASSERT(AllowAssembler());
23935  CheckIT(al);
23936  if (IsUsingT32()) {
23937    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
23938    if (OutsideITBlock() && dt.Is(F32)) {
23939      EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23940                 rm.Encode(5, 0));
23941      AdvanceIT();
23942      return;
23943    }
23944  } else {
23945    // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
23946    if (dt.Is(F32)) {
23947      EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23948              rm.Encode(5, 0));
23949      return;
23950    }
23951  }
23952  Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
23953}
23954
23955void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
23956  VIXL_ASSERT(AllowAssembler());
23957  CheckIT(al);
23958  if (IsUsingT32()) {
23959    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
23960    if (OutsideITBlock() && dt.Is(F64)) {
23961      EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23962                 rm.Encode(5, 0));
23963      AdvanceIT();
23964      return;
23965    }
23966  } else {
23967    // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
23968    if (dt.Is(F64)) {
23969      EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23970              rm.Encode(5, 0));
23971      return;
23972    }
23973  }
23974  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
23975}
23976
23977void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
23978  VIXL_ASSERT(AllowAssembler());
23979  CheckIT(al);
23980  if (IsUsingT32()) {
23981    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
23982    if (OutsideITBlock() && dt.Is(F32)) {
23983      EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23984                 rm.Encode(5, 0));
23985      AdvanceIT();
23986      return;
23987    }
23988  } else {
23989    // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
23990    if (dt.Is(F32)) {
23991      EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23992              rm.Encode(5, 0));
23993      return;
23994    }
23995  }
23996  Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
23997}
23998
23999void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
24000  VIXL_ASSERT(AllowAssembler());
24001  CheckIT(al);
24002  if (IsUsingT32()) {
24003    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
24004    if (OutsideITBlock() && dt.Is(F64)) {
24005      EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24006                 rm.Encode(5, 0));
24007      AdvanceIT();
24008      return;
24009    }
24010  } else {
24011    // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
24012    if (dt.Is(F64)) {
24013      EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24014              rm.Encode(5, 0));
24015      return;
24016    }
24017  }
24018  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
24019}
24020
24021void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
24022  VIXL_ASSERT(AllowAssembler());
24023  CheckIT(al);
24024  if (IsUsingT32()) {
24025    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
24026    if (OutsideITBlock() && dt.Is(F32)) {
24027      EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24028                 rm.Encode(5, 0));
24029      AdvanceIT();
24030      return;
24031    }
24032  } else {
24033    // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
24034    if (dt.Is(F32)) {
24035      EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24036              rm.Encode(5, 0));
24037      return;
24038    }
24039  }
24040  Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
24041}
24042
24043void Assembler::vshl(Condition cond,
24044                     DataType dt,
24045                     DRegister rd,
24046                     DRegister rm,
24047                     const DOperand& operand) {
24048  VIXL_ASSERT(AllowAssembler());
24049  CheckIT(cond);
24050  if (operand.IsImmediate()) {
24051    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24052      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24053      Dt_L_imm6_3 encoded_dt(dt);
24054      if (IsUsingT32()) {
24055        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
24056        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24057          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24058            uint32_t imm6 = imm;
24059            EmitT32_32(0xef800510U |
24060                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24061                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24062                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24063            AdvanceIT();
24064            return;
24065          }
24066        }
24067      } else {
24068        // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
24069        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24070          if (cond.Is(al)) {
24071            uint32_t imm6 = imm;
24072            EmitA32(0xf2800510U |
24073                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24074                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24075                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24076            return;
24077          }
24078        }
24079      }
24080    }
24081  }
24082  if (operand.IsRegister()) {
24083    DRegister rn = operand.GetRegister();
24084    Dt_U_size_3 encoded_dt(dt);
24085    if (IsUsingT32()) {
24086      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24087      if (encoded_dt.IsValid()) {
24088        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24089          EmitT32_32(0xef000400U |
24090                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24091                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24092                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24093          AdvanceIT();
24094          return;
24095        }
24096      }
24097    } else {
24098      // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24099      if (encoded_dt.IsValid()) {
24100        if (cond.Is(al)) {
24101          EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24102                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24103                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24104          return;
24105        }
24106      }
24107    }
24108  }
24109  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
24110}
24111
24112void Assembler::vshl(Condition cond,
24113                     DataType dt,
24114                     QRegister rd,
24115                     QRegister rm,
24116                     const QOperand& operand) {
24117  VIXL_ASSERT(AllowAssembler());
24118  CheckIT(cond);
24119  if (operand.IsImmediate()) {
24120    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24121      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24122      Dt_L_imm6_3 encoded_dt(dt);
24123      if (IsUsingT32()) {
24124        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
24125        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24126          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24127            uint32_t imm6 = imm;
24128            EmitT32_32(0xef800550U |
24129                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24130                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24131                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24132            AdvanceIT();
24133            return;
24134          }
24135        }
24136      } else {
24137        // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
24138        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24139          if (cond.Is(al)) {
24140            uint32_t imm6 = imm;
24141            EmitA32(0xf2800550U |
24142                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24143                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24144                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24145            return;
24146          }
24147        }
24148      }
24149    }
24150  }
24151  if (operand.IsRegister()) {
24152    QRegister rn = operand.GetRegister();
24153    Dt_U_size_3 encoded_dt(dt);
24154    if (IsUsingT32()) {
24155      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24156      if (encoded_dt.IsValid()) {
24157        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24158          EmitT32_32(0xef000440U |
24159                     ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24160                     ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24161                     rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24162          AdvanceIT();
24163          return;
24164        }
24165      }
24166    } else {
24167      // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24168      if (encoded_dt.IsValid()) {
24169        if (cond.Is(al)) {
24170          EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24171                  ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24172                  rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24173          return;
24174        }
24175      }
24176    }
24177  }
24178  Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
24179}
24180
24181void Assembler::vshll(Condition cond,
24182                      DataType dt,
24183                      QRegister rd,
24184                      DRegister rm,
24185                      const DOperand& operand) {
24186  VIXL_ASSERT(AllowAssembler());
24187  CheckIT(cond);
24188  if (operand.IsImmediate()) {
24189    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24190      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24191      Dt_imm6_4 encoded_dt(dt);
24192      Dt_size_16 encoded_dt_2(dt);
24193      if (IsUsingT32()) {
24194        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
24195        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
24196          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24197            uint32_t imm6 = dt.GetSize() + imm;
24198            EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
24199                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24200                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24201            AdvanceIT();
24202            return;
24203          }
24204        }
24205        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
24206        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
24207          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24208            EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
24209                       rd.Encode(22, 12) | rm.Encode(5, 0));
24210            AdvanceIT();
24211            return;
24212          }
24213        }
24214      } else {
24215        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
24216        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
24217          if (cond.Is(al)) {
24218            uint32_t imm6 = dt.GetSize() + imm;
24219            EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
24220                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24221                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24222            return;
24223          }
24224        }
24225        // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
24226        if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
24227          if (cond.Is(al)) {
24228            EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
24229                    rd.Encode(22, 12) | rm.Encode(5, 0));
24230            return;
24231          }
24232        }
24233      }
24234    }
24235  }
24236  Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
24237}
24238
24239void Assembler::vshr(Condition cond,
24240                     DataType dt,
24241                     DRegister rd,
24242                     DRegister rm,
24243                     const DOperand& operand) {
24244  VIXL_ASSERT(AllowAssembler());
24245  CheckIT(cond);
24246  if (operand.IsImmediate()) {
24247    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24248      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24249      Dt_L_imm6_1 encoded_dt(dt);
24250      if (IsUsingT32()) {
24251        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24252        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24253          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24254            uint32_t imm6 = dt.GetSize() - imm;
24255            EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
24256                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24257                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24258                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24259            AdvanceIT();
24260            return;
24261          }
24262        }
24263        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24264        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24265          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24266            EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24267                       rm.Encode(5, 0));
24268            AdvanceIT();
24269            return;
24270          }
24271        }
24272      } else {
24273        // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24274        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24275          if (cond.Is(al)) {
24276            uint32_t imm6 = dt.GetSize() - imm;
24277            EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
24278                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24279                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24280                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24281            return;
24282          }
24283        }
24284        // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24285        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24286          if (cond.Is(al)) {
24287            EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24288                    rm.Encode(5, 0));
24289            return;
24290          }
24291        }
24292      }
24293    }
24294  }
24295  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
24296}
24297
24298void Assembler::vshr(Condition cond,
24299                     DataType dt,
24300                     QRegister rd,
24301                     QRegister rm,
24302                     const QOperand& operand) {
24303  VIXL_ASSERT(AllowAssembler());
24304  CheckIT(cond);
24305  if (operand.IsImmediate()) {
24306    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24307      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24308      Dt_L_imm6_1 encoded_dt(dt);
24309      if (IsUsingT32()) {
24310        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24311        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24312          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24313            uint32_t imm6 = dt.GetSize() - imm;
24314            EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
24315                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24316                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24317                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24318            AdvanceIT();
24319            return;
24320          }
24321        }
24322        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24323        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24324          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24325            EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24326                       rm.Encode(5, 0));
24327            AdvanceIT();
24328            return;
24329          }
24330        }
24331      } else {
24332        // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24333        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24334          if (cond.Is(al)) {
24335            uint32_t imm6 = dt.GetSize() - imm;
24336            EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
24337                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24338                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24339                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24340            return;
24341          }
24342        }
24343        // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24344        if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24345          if (cond.Is(al)) {
24346            EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24347                    rm.Encode(5, 0));
24348            return;
24349          }
24350        }
24351      }
24352    }
24353  }
24354  Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
24355}
24356
24357void Assembler::vshrn(Condition cond,
24358                      DataType dt,
24359                      DRegister rd,
24360                      QRegister rm,
24361                      const QOperand& operand) {
24362  VIXL_ASSERT(AllowAssembler());
24363  CheckIT(cond);
24364  if (operand.IsImmediate()) {
24365    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24366      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24367      Dt_imm6_3 encoded_dt(dt);
24368      Dt_size_3 encoded_dt_2(dt);
24369      if (IsUsingT32()) {
24370        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24371        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24372          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24373            uint32_t imm6 = dt.GetSize() / 2 - imm;
24374            EmitT32_32(0xef800810U |
24375                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24376                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24377            AdvanceIT();
24378            return;
24379          }
24380        }
24381        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24382        if (encoded_dt_2.IsValid() && (imm == 0)) {
24383          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24384            EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24385                       rd.Encode(22, 12) | rm.Encode(5, 0));
24386            AdvanceIT();
24387            return;
24388          }
24389        }
24390      } else {
24391        // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24392        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24393          if (cond.Is(al)) {
24394            uint32_t imm6 = dt.GetSize() / 2 - imm;
24395            EmitA32(0xf2800810U |
24396                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24397                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24398            return;
24399          }
24400        }
24401        // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24402        if (encoded_dt_2.IsValid() && (imm == 0)) {
24403          if (cond.Is(al)) {
24404            EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24405                    rd.Encode(22, 12) | rm.Encode(5, 0));
24406            return;
24407          }
24408        }
24409      }
24410    }
24411  }
24412  Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
24413}
24414
24415void Assembler::vsli(Condition cond,
24416                     DataType dt,
24417                     DRegister rd,
24418                     DRegister rm,
24419                     const DOperand& operand) {
24420  VIXL_ASSERT(AllowAssembler());
24421  CheckIT(cond);
24422  if (operand.IsImmediate()) {
24423    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24424      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24425      Dt_L_imm6_4 encoded_dt(dt);
24426      if (IsUsingT32()) {
24427        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
24428        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24429          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24430            uint32_t imm6 = imm;
24431            EmitT32_32(0xff800510U |
24432                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24433                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24434                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24435            AdvanceIT();
24436            return;
24437          }
24438        }
24439      } else {
24440        // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
24441        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24442          if (cond.Is(al)) {
24443            uint32_t imm6 = imm;
24444            EmitA32(0xf3800510U |
24445                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24446                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24447                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24448            return;
24449          }
24450        }
24451      }
24452    }
24453  }
24454  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
24455}
24456
24457void Assembler::vsli(Condition cond,
24458                     DataType dt,
24459                     QRegister rd,
24460                     QRegister rm,
24461                     const QOperand& operand) {
24462  VIXL_ASSERT(AllowAssembler());
24463  CheckIT(cond);
24464  if (operand.IsImmediate()) {
24465    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24466      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24467      Dt_L_imm6_4 encoded_dt(dt);
24468      if (IsUsingT32()) {
24469        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
24470        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24471          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24472            uint32_t imm6 = imm;
24473            EmitT32_32(0xff800550U |
24474                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24475                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24476                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24477            AdvanceIT();
24478            return;
24479          }
24480        }
24481      } else {
24482        // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
24483        if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24484          if (cond.Is(al)) {
24485            uint32_t imm6 = imm;
24486            EmitA32(0xf3800550U |
24487                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24488                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24489                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24490            return;
24491          }
24492        }
24493      }
24494    }
24495  }
24496  Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
24497}
24498
24499void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
24500  VIXL_ASSERT(AllowAssembler());
24501  CheckIT(cond);
24502  if (IsUsingT32()) {
24503    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24504    if (dt.Is(F32)) {
24505      EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24506      AdvanceIT();
24507      return;
24508    }
24509  } else {
24510    // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24511    if (dt.Is(F32) && cond.IsNotNever()) {
24512      EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24513              rm.Encode(5, 0));
24514      return;
24515    }
24516  }
24517  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
24518}
24519
24520void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
24521  VIXL_ASSERT(AllowAssembler());
24522  CheckIT(cond);
24523  if (IsUsingT32()) {
24524    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24525    if (dt.Is(F64)) {
24526      EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24527      AdvanceIT();
24528      return;
24529    }
24530  } else {
24531    // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24532    if (dt.Is(F64) && cond.IsNotNever()) {
24533      EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24534              rm.Encode(5, 0));
24535      return;
24536    }
24537  }
24538  Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
24539}
24540
24541void Assembler::vsra(Condition cond,
24542                     DataType dt,
24543                     DRegister rd,
24544                     DRegister rm,
24545                     const DOperand& operand) {
24546  VIXL_ASSERT(AllowAssembler());
24547  CheckIT(cond);
24548  if (operand.IsImmediate()) {
24549    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24550      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24551      Dt_L_imm6_1 encoded_dt(dt);
24552      if (IsUsingT32()) {
24553        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24554        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24555          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24556            uint32_t imm6 = dt.GetSize() - imm;
24557            EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
24558                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24559                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24560                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24561            AdvanceIT();
24562            return;
24563          }
24564        }
24565      } else {
24566        // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24567        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24568          if (cond.Is(al)) {
24569            uint32_t imm6 = dt.GetSize() - imm;
24570            EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
24571                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24572                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24573                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24574            return;
24575          }
24576        }
24577      }
24578    }
24579  }
24580  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
24581}
24582
24583void Assembler::vsra(Condition cond,
24584                     DataType dt,
24585                     QRegister rd,
24586                     QRegister rm,
24587                     const QOperand& operand) {
24588  VIXL_ASSERT(AllowAssembler());
24589  CheckIT(cond);
24590  if (operand.IsImmediate()) {
24591    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24592      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24593      Dt_L_imm6_1 encoded_dt(dt);
24594      if (IsUsingT32()) {
24595        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24596        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24597          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24598            uint32_t imm6 = dt.GetSize() - imm;
24599            EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
24600                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24601                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24602                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24603            AdvanceIT();
24604            return;
24605          }
24606        }
24607      } else {
24608        // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24609        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24610          if (cond.Is(al)) {
24611            uint32_t imm6 = dt.GetSize() - imm;
24612            EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
24613                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24614                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24615                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24616            return;
24617          }
24618        }
24619      }
24620    }
24621  }
24622  Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
24623}
24624
24625void Assembler::vsri(Condition cond,
24626                     DataType dt,
24627                     DRegister rd,
24628                     DRegister rm,
24629                     const DOperand& operand) {
24630  VIXL_ASSERT(AllowAssembler());
24631  CheckIT(cond);
24632  if (operand.IsImmediate()) {
24633    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24634      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24635      Dt_L_imm6_4 encoded_dt(dt);
24636      if (IsUsingT32()) {
24637        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
24638        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24639          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24640            uint32_t imm6 = dt.GetSize() - imm;
24641            EmitT32_32(0xff800410U |
24642                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24643                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24644                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24645            AdvanceIT();
24646            return;
24647          }
24648        }
24649      } else {
24650        // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
24651        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24652          if (cond.Is(al)) {
24653            uint32_t imm6 = dt.GetSize() - imm;
24654            EmitA32(0xf3800410U |
24655                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24656                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24657                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24658            return;
24659          }
24660        }
24661      }
24662    }
24663  }
24664  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
24665}
24666
24667void Assembler::vsri(Condition cond,
24668                     DataType dt,
24669                     QRegister rd,
24670                     QRegister rm,
24671                     const QOperand& operand) {
24672  VIXL_ASSERT(AllowAssembler());
24673  CheckIT(cond);
24674  if (operand.IsImmediate()) {
24675    if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24676      uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24677      Dt_L_imm6_4 encoded_dt(dt);
24678      if (IsUsingT32()) {
24679        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
24680        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24681          if (cond.Is(al) || AllowStronglyDiscouraged()) {
24682            uint32_t imm6 = dt.GetSize() - imm;
24683            EmitT32_32(0xff800450U |
24684                       ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24685                       ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24686                       rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24687            AdvanceIT();
24688            return;
24689          }
24690        }
24691      } else {
24692        // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
24693        if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24694          if (cond.Is(al)) {
24695            uint32_t imm6 = dt.GetSize() - imm;
24696            EmitA32(0xf3800450U |
24697                    ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24698                    ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24699                    rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24700            return;
24701          }
24702        }
24703      }
24704    }
24705  }
24706  Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
24707}
24708
24709void Assembler::vst1(Condition cond,
24710                     DataType dt,
24711                     const NeonRegisterList& nreglist,
24712                     const AlignedMemOperand& operand) {
24713  VIXL_ASSERT(AllowAssembler());
24714  CheckIT(cond);
24715  if (operand.IsImmediateZero()) {
24716    Register rn = operand.GetBaseRegister();
24717    Alignment align = operand.GetAlignment();
24718    Dt_size_6 encoded_dt(dt);
24719    Dt_size_7 encoded_dt_2(dt);
24720    Align_align_5 encoded_align_1(align, nreglist);
24721    Align_index_align_1 encoded_align_2(align, nreglist, dt);
24722    if (IsUsingT32()) {
24723      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
24724      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24725          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24726          operand.IsOffset() && encoded_align_1.IsValid() &&
24727          (!rn.IsPC() || AllowUnpredictable())) {
24728        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24729          const DRegister& first = nreglist.GetFirstDRegister();
24730          uint32_t len_encoding;
24731          switch (nreglist.GetLength()) {
24732            default:
24733              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24734            case 1:
24735              len_encoding = 0x7;
24736              break;
24737            case 2:
24738              len_encoding = 0xa;
24739              break;
24740            case 3:
24741              len_encoding = 0x6;
24742              break;
24743            case 4:
24744              len_encoding = 0x2;
24745              break;
24746          }
24747          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
24748                     (encoded_align_1.GetEncodingValue() << 4) |
24749                     first.Encode(22, 12) | (len_encoding << 8) |
24750                     (rn.GetCode() << 16));
24751          AdvanceIT();
24752          return;
24753        }
24754      }
24755      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
24756      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24757          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24758          operand.IsPostIndex() && encoded_align_1.IsValid() &&
24759          (!rn.IsPC() || AllowUnpredictable())) {
24760        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24761          const DRegister& first = nreglist.GetFirstDRegister();
24762          uint32_t len_encoding;
24763          switch (nreglist.GetLength()) {
24764            default:
24765              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24766            case 1:
24767              len_encoding = 0x7;
24768              break;
24769            case 2:
24770              len_encoding = 0xa;
24771              break;
24772            case 3:
24773              len_encoding = 0x6;
24774              break;
24775            case 4:
24776              len_encoding = 0x2;
24777              break;
24778          }
24779          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
24780                     (encoded_align_1.GetEncodingValue() << 4) |
24781                     first.Encode(22, 12) | (len_encoding << 8) |
24782                     (rn.GetCode() << 16));
24783          AdvanceIT();
24784          return;
24785        }
24786      }
24787      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
24788      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24789          (nreglist.GetLength() == 1) && operand.IsOffset() &&
24790          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
24791        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24792          const DRegister& first = nreglist.GetFirstDRegister();
24793          EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
24794                     (encoded_align_2.GetEncodingValue() << 4) |
24795                     first.Encode(22, 12) | (rn.GetCode() << 16));
24796          AdvanceIT();
24797          return;
24798        }
24799      }
24800      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
24801      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24802          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
24803          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
24804        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24805          const DRegister& first = nreglist.GetFirstDRegister();
24806          EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
24807                     (encoded_align_2.GetEncodingValue() << 4) |
24808                     first.Encode(22, 12) | (rn.GetCode() << 16));
24809          AdvanceIT();
24810          return;
24811        }
24812      }
24813    } else {
24814      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
24815      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24816          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24817          operand.IsOffset() && encoded_align_1.IsValid() &&
24818          (!rn.IsPC() || AllowUnpredictable())) {
24819        if (cond.Is(al)) {
24820          const DRegister& first = nreglist.GetFirstDRegister();
24821          uint32_t len_encoding;
24822          switch (nreglist.GetLength()) {
24823            default:
24824              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24825            case 1:
24826              len_encoding = 0x7;
24827              break;
24828            case 2:
24829              len_encoding = 0xa;
24830              break;
24831            case 3:
24832              len_encoding = 0x6;
24833              break;
24834            case 4:
24835              len_encoding = 0x2;
24836              break;
24837          }
24838          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
24839                  (encoded_align_1.GetEncodingValue() << 4) |
24840                  first.Encode(22, 12) | (len_encoding << 8) |
24841                  (rn.GetCode() << 16));
24842          return;
24843        }
24844      }
24845      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
24846      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24847          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24848          operand.IsPostIndex() && encoded_align_1.IsValid() &&
24849          (!rn.IsPC() || AllowUnpredictable())) {
24850        if (cond.Is(al)) {
24851          const DRegister& first = nreglist.GetFirstDRegister();
24852          uint32_t len_encoding;
24853          switch (nreglist.GetLength()) {
24854            default:
24855              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24856            case 1:
24857              len_encoding = 0x7;
24858              break;
24859            case 2:
24860              len_encoding = 0xa;
24861              break;
24862            case 3:
24863              len_encoding = 0x6;
24864              break;
24865            case 4:
24866              len_encoding = 0x2;
24867              break;
24868          }
24869          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
24870                  (encoded_align_1.GetEncodingValue() << 4) |
24871                  first.Encode(22, 12) | (len_encoding << 8) |
24872                  (rn.GetCode() << 16));
24873          return;
24874        }
24875      }
24876      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
24877      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24878          (nreglist.GetLength() == 1) && operand.IsOffset() &&
24879          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
24880        if (cond.Is(al)) {
24881          const DRegister& first = nreglist.GetFirstDRegister();
24882          EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
24883                  (encoded_align_2.GetEncodingValue() << 4) |
24884                  first.Encode(22, 12) | (rn.GetCode() << 16));
24885          return;
24886        }
24887      }
24888      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
24889      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24890          (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
24891          encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
24892        if (cond.Is(al)) {
24893          const DRegister& first = nreglist.GetFirstDRegister();
24894          EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
24895                  (encoded_align_2.GetEncodingValue() << 4) |
24896                  first.Encode(22, 12) | (rn.GetCode() << 16));
24897          return;
24898        }
24899      }
24900    }
24901  }
24902  if (operand.IsPlainRegister()) {
24903    Register rn = operand.GetBaseRegister();
24904    Alignment align = operand.GetAlignment();
24905    Register rm = operand.GetOffsetRegister();
24906    Dt_size_6 encoded_dt(dt);
24907    Dt_size_7 encoded_dt_2(dt);
24908    Align_align_5 encoded_align_1(align, nreglist);
24909    Align_index_align_1 encoded_align_2(align, nreglist, dt);
24910    if (IsUsingT32()) {
24911      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
24912      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24913          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24914          !rm.IsPC() && !rm.IsSP()) {
24915        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24916          const DRegister& first = nreglist.GetFirstDRegister();
24917          uint32_t len_encoding;
24918          switch (nreglist.GetLength()) {
24919            default:
24920              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24921            case 1:
24922              len_encoding = 0x7;
24923              break;
24924            case 2:
24925              len_encoding = 0xa;
24926              break;
24927            case 3:
24928              len_encoding = 0x6;
24929              break;
24930            case 4:
24931              len_encoding = 0x2;
24932              break;
24933          }
24934          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
24935                     (encoded_align_1.GetEncodingValue() << 4) |
24936                     first.Encode(22, 12) | (len_encoding << 8) |
24937                     (rn.GetCode() << 16) | rm.GetCode());
24938          AdvanceIT();
24939          return;
24940        }
24941      }
24942      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
24943      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24944          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
24945        if (cond.Is(al) || AllowStronglyDiscouraged()) {
24946          const DRegister& first = nreglist.GetFirstDRegister();
24947          EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
24948                     (encoded_align_2.GetEncodingValue() << 4) |
24949                     first.Encode(22, 12) | (rn.GetCode() << 16) |
24950                     rm.GetCode());
24951          AdvanceIT();
24952          return;
24953        }
24954      }
24955    } else {
24956      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
24957      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24958          (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24959          !rm.IsPC() && !rm.IsSP()) {
24960        if (cond.Is(al)) {
24961          const DRegister& first = nreglist.GetFirstDRegister();
24962          uint32_t len_encoding;
24963          switch (nreglist.GetLength()) {
24964            default:
24965              VIXL_UNREACHABLE_OR_FALLTHROUGH();
24966            case 1:
24967              len_encoding = 0x7;
24968              break;
24969            case 2:
24970              len_encoding = 0xa;
24971              break;
24972            case 3:
24973              len_encoding = 0x6;
24974              break;
24975            case 4:
24976              len_encoding = 0x2;
24977              break;
24978          }
24979          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
24980                  (encoded_align_1.GetEncodingValue() << 4) |
24981                  first.Encode(22, 12) | (len_encoding << 8) |
24982                  (rn.GetCode() << 16) | rm.GetCode());
24983          return;
24984        }
24985      }
24986      // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
24987      if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24988          (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
24989        if (cond.Is(al)) {
24990          const DRegister& first = nreglist.GetFirstDRegister();
24991          EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
24992                  (encoded_align_2.GetEncodingValue() << 4) |
24993                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
24994          return;
24995        }
24996      }
24997    }
24998  }
24999  Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
25000}
25001
25002void Assembler::vst2(Condition cond,
25003                     DataType dt,
25004                     const NeonRegisterList& nreglist,
25005                     const AlignedMemOperand& operand) {
25006  VIXL_ASSERT(AllowAssembler());
25007  CheckIT(cond);
25008  if (operand.IsImmediateZero()) {
25009    Register rn = operand.GetBaseRegister();
25010    Alignment align = operand.GetAlignment();
25011    Dt_size_7 encoded_dt(dt);
25012    Align_align_2 encoded_align_1(align, nreglist);
25013    Align_index_align_2 encoded_align_2(align, nreglist, dt);
25014    if (IsUsingT32()) {
25015      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25016      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25017          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25018           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25019           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25020          operand.IsOffset() && encoded_align_1.IsValid() &&
25021          (!rn.IsPC() || AllowUnpredictable())) {
25022        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25023          const DRegister& first = nreglist.GetFirstDRegister();
25024          uint32_t len_encoding;
25025          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25026            len_encoding = 0x8;
25027          }
25028          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25029            len_encoding = 0x9;
25030          }
25031          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25032            len_encoding = 0x3;
25033          }
25034          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25035                     (encoded_align_1.GetEncodingValue() << 4) |
25036                     first.Encode(22, 12) | (len_encoding << 8) |
25037                     (rn.GetCode() << 16));
25038          AdvanceIT();
25039          return;
25040        }
25041      }
25042      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25043      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25044          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25045           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25046           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25047          operand.IsPostIndex() && encoded_align_1.IsValid() &&
25048          (!rn.IsPC() || AllowUnpredictable())) {
25049        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25050          const DRegister& first = nreglist.GetFirstDRegister();
25051          uint32_t len_encoding;
25052          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25053            len_encoding = 0x8;
25054          }
25055          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25056            len_encoding = 0x9;
25057          }
25058          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25059            len_encoding = 0x3;
25060          }
25061          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25062                     (encoded_align_1.GetEncodingValue() << 4) |
25063                     first.Encode(22, 12) | (len_encoding << 8) |
25064                     (rn.GetCode() << 16));
25065          AdvanceIT();
25066          return;
25067        }
25068      }
25069      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25070      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25071          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25072           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25073          operand.IsOffset() && encoded_align_2.IsValid() &&
25074          (!rn.IsPC() || AllowUnpredictable())) {
25075        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25076          const DRegister& first = nreglist.GetFirstDRegister();
25077          EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
25078                     (encoded_align_2.GetEncodingValue() << 4) |
25079                     first.Encode(22, 12) | (rn.GetCode() << 16));
25080          AdvanceIT();
25081          return;
25082        }
25083      }
25084      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25085      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25086          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25087           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25088          operand.IsPostIndex() && encoded_align_2.IsValid() &&
25089          (!rn.IsPC() || AllowUnpredictable())) {
25090        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25091          const DRegister& first = nreglist.GetFirstDRegister();
25092          EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
25093                     (encoded_align_2.GetEncodingValue() << 4) |
25094                     first.Encode(22, 12) | (rn.GetCode() << 16));
25095          AdvanceIT();
25096          return;
25097        }
25098      }
25099    } else {
25100      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25101      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25102          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25103           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25104           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25105          operand.IsOffset() && encoded_align_1.IsValid() &&
25106          (!rn.IsPC() || AllowUnpredictable())) {
25107        if (cond.Is(al)) {
25108          const DRegister& first = nreglist.GetFirstDRegister();
25109          uint32_t len_encoding;
25110          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25111            len_encoding = 0x8;
25112          }
25113          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25114            len_encoding = 0x9;
25115          }
25116          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25117            len_encoding = 0x3;
25118          }
25119          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25120                  (encoded_align_1.GetEncodingValue() << 4) |
25121                  first.Encode(22, 12) | (len_encoding << 8) |
25122                  (rn.GetCode() << 16));
25123          return;
25124        }
25125      }
25126      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25127      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25128          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25129           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25130           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25131          operand.IsPostIndex() && encoded_align_1.IsValid() &&
25132          (!rn.IsPC() || AllowUnpredictable())) {
25133        if (cond.Is(al)) {
25134          const DRegister& first = nreglist.GetFirstDRegister();
25135          uint32_t len_encoding;
25136          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25137            len_encoding = 0x8;
25138          }
25139          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25140            len_encoding = 0x9;
25141          }
25142          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25143            len_encoding = 0x3;
25144          }
25145          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25146                  (encoded_align_1.GetEncodingValue() << 4) |
25147                  first.Encode(22, 12) | (len_encoding << 8) |
25148                  (rn.GetCode() << 16));
25149          return;
25150        }
25151      }
25152      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25153      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25154          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25155           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25156          operand.IsOffset() && encoded_align_2.IsValid() &&
25157          (!rn.IsPC() || AllowUnpredictable())) {
25158        if (cond.Is(al)) {
25159          const DRegister& first = nreglist.GetFirstDRegister();
25160          EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
25161                  (encoded_align_2.GetEncodingValue() << 4) |
25162                  first.Encode(22, 12) | (rn.GetCode() << 16));
25163          return;
25164        }
25165      }
25166      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25167      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25168          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25169           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25170          operand.IsPostIndex() && encoded_align_2.IsValid() &&
25171          (!rn.IsPC() || AllowUnpredictable())) {
25172        if (cond.Is(al)) {
25173          const DRegister& first = nreglist.GetFirstDRegister();
25174          EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
25175                  (encoded_align_2.GetEncodingValue() << 4) |
25176                  first.Encode(22, 12) | (rn.GetCode() << 16));
25177          return;
25178        }
25179      }
25180    }
25181  }
25182  if (operand.IsPlainRegister()) {
25183    Register rn = operand.GetBaseRegister();
25184    Alignment align = operand.GetAlignment();
25185    Register rm = operand.GetOffsetRegister();
25186    Dt_size_7 encoded_dt(dt);
25187    Align_align_2 encoded_align_1(align, nreglist);
25188    Align_index_align_2 encoded_align_2(align, nreglist, dt);
25189    if (IsUsingT32()) {
25190      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25191      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25192          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25193           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25194           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25195          !rm.IsPC() && !rm.IsSP()) {
25196        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25197          const DRegister& first = nreglist.GetFirstDRegister();
25198          uint32_t len_encoding;
25199          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25200            len_encoding = 0x8;
25201          }
25202          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25203            len_encoding = 0x9;
25204          }
25205          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25206            len_encoding = 0x3;
25207          }
25208          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25209                     (encoded_align_1.GetEncodingValue() << 4) |
25210                     first.Encode(22, 12) | (len_encoding << 8) |
25211                     (rn.GetCode() << 16) | rm.GetCode());
25212          AdvanceIT();
25213          return;
25214        }
25215      }
25216      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25217      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25218          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25219           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25220          !rm.IsPC() && !rm.IsSP()) {
25221        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25222          const DRegister& first = nreglist.GetFirstDRegister();
25223          EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
25224                     (encoded_align_2.GetEncodingValue() << 4) |
25225                     first.Encode(22, 12) | (rn.GetCode() << 16) |
25226                     rm.GetCode());
25227          AdvanceIT();
25228          return;
25229        }
25230      }
25231    } else {
25232      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25233      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25234          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25235           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25236           (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25237          !rm.IsPC() && !rm.IsSP()) {
25238        if (cond.Is(al)) {
25239          const DRegister& first = nreglist.GetFirstDRegister();
25240          uint32_t len_encoding;
25241          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25242            len_encoding = 0x8;
25243          }
25244          if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25245            len_encoding = 0x9;
25246          }
25247          if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25248            len_encoding = 0x3;
25249          }
25250          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25251                  (encoded_align_1.GetEncodingValue() << 4) |
25252                  first.Encode(22, 12) | (len_encoding << 8) |
25253                  (rn.GetCode() << 16) | rm.GetCode());
25254          return;
25255        }
25256      }
25257      // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25258      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25259          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25260           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25261          !rm.IsPC() && !rm.IsSP()) {
25262        if (cond.Is(al)) {
25263          const DRegister& first = nreglist.GetFirstDRegister();
25264          EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
25265                  (encoded_align_2.GetEncodingValue() << 4) |
25266                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25267          return;
25268        }
25269      }
25270    }
25271  }
25272  Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
25273}
25274
25275void Assembler::vst3(Condition cond,
25276                     DataType dt,
25277                     const NeonRegisterList& nreglist,
25278                     const AlignedMemOperand& operand) {
25279  VIXL_ASSERT(AllowAssembler());
25280  CheckIT(cond);
25281  if (operand.IsImmediateZero()) {
25282    Register rn = operand.GetBaseRegister();
25283    Alignment align = operand.GetAlignment();
25284    Dt_size_7 encoded_dt(dt);
25285    Align_align_3 encoded_align_1(align);
25286    if (IsUsingT32()) {
25287      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25288      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25289          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25290           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25291          operand.IsOffset() && encoded_align_1.IsValid() &&
25292          (!rn.IsPC() || AllowUnpredictable())) {
25293        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25294          const DRegister& first = nreglist.GetFirstDRegister();
25295          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25296          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25297                     (encoded_align_1.GetEncodingValue() << 4) |
25298                     first.Encode(22, 12) | (len_encoding << 8) |
25299                     (rn.GetCode() << 16));
25300          AdvanceIT();
25301          return;
25302        }
25303      }
25304      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25305      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25306          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25307           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25308          operand.IsPostIndex() && encoded_align_1.IsValid() &&
25309          (!rn.IsPC() || AllowUnpredictable())) {
25310        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25311          const DRegister& first = nreglist.GetFirstDRegister();
25312          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25313          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25314                     (encoded_align_1.GetEncodingValue() << 4) |
25315                     first.Encode(22, 12) | (len_encoding << 8) |
25316                     (rn.GetCode() << 16));
25317          AdvanceIT();
25318          return;
25319        }
25320      }
25321    } else {
25322      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25323      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25324          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25325           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25326          operand.IsOffset() && encoded_align_1.IsValid() &&
25327          (!rn.IsPC() || AllowUnpredictable())) {
25328        if (cond.Is(al)) {
25329          const DRegister& first = nreglist.GetFirstDRegister();
25330          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25331          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25332                  (encoded_align_1.GetEncodingValue() << 4) |
25333                  first.Encode(22, 12) | (len_encoding << 8) |
25334                  (rn.GetCode() << 16));
25335          return;
25336        }
25337      }
25338      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25339      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25340          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25341           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25342          operand.IsPostIndex() && encoded_align_1.IsValid() &&
25343          (!rn.IsPC() || AllowUnpredictable())) {
25344        if (cond.Is(al)) {
25345          const DRegister& first = nreglist.GetFirstDRegister();
25346          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25347          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25348                  (encoded_align_1.GetEncodingValue() << 4) |
25349                  first.Encode(22, 12) | (len_encoding << 8) |
25350                  (rn.GetCode() << 16));
25351          return;
25352        }
25353      }
25354    }
25355  }
25356  if (operand.IsPlainRegister()) {
25357    Register rn = operand.GetBaseRegister();
25358    Alignment align = operand.GetAlignment();
25359    Register rm = operand.GetOffsetRegister();
25360    Dt_size_7 encoded_dt(dt);
25361    Align_align_3 encoded_align_1(align);
25362    if (IsUsingT32()) {
25363      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25364      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25365          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25366           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25367          !rm.IsPC() && !rm.IsSP()) {
25368        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25369          const DRegister& first = nreglist.GetFirstDRegister();
25370          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25371          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25372                     (encoded_align_1.GetEncodingValue() << 4) |
25373                     first.Encode(22, 12) | (len_encoding << 8) |
25374                     (rn.GetCode() << 16) | rm.GetCode());
25375          AdvanceIT();
25376          return;
25377        }
25378      }
25379    } else {
25380      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25381      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25382          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25383           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25384          !rm.IsPC() && !rm.IsSP()) {
25385        if (cond.Is(al)) {
25386          const DRegister& first = nreglist.GetFirstDRegister();
25387          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25388          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25389                  (encoded_align_1.GetEncodingValue() << 4) |
25390                  first.Encode(22, 12) | (len_encoding << 8) |
25391                  (rn.GetCode() << 16) | rm.GetCode());
25392          return;
25393        }
25394      }
25395    }
25396  }
25397  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
25398}
25399
25400void Assembler::vst3(Condition cond,
25401                     DataType dt,
25402                     const NeonRegisterList& nreglist,
25403                     const MemOperand& operand) {
25404  VIXL_ASSERT(AllowAssembler());
25405  CheckIT(cond);
25406  if (operand.IsImmediateZero()) {
25407    Register rn = operand.GetBaseRegister();
25408    Dt_size_7 encoded_dt(dt);
25409    Index_1 encoded_align_1(nreglist, dt);
25410    if (IsUsingT32()) {
25411      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
25412      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25413          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25414           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25415          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
25416        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25417          const DRegister& first = nreglist.GetFirstDRegister();
25418          EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
25419                     (encoded_align_1.GetEncodingValue() << 4) |
25420                     first.Encode(22, 12) | (rn.GetCode() << 16));
25421          AdvanceIT();
25422          return;
25423        }
25424      }
25425      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
25426      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25427          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25428           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25429          operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
25430        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25431          const DRegister& first = nreglist.GetFirstDRegister();
25432          EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
25433                     (encoded_align_1.GetEncodingValue() << 4) |
25434                     first.Encode(22, 12) | (rn.GetCode() << 16));
25435          AdvanceIT();
25436          return;
25437        }
25438      }
25439    } else {
25440      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
25441      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25442          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25443           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25444          operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
25445        if (cond.Is(al)) {
25446          const DRegister& first = nreglist.GetFirstDRegister();
25447          EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
25448                  (encoded_align_1.GetEncodingValue() << 4) |
25449                  first.Encode(22, 12) | (rn.GetCode() << 16));
25450          return;
25451        }
25452      }
25453      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
25454      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25455          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25456           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25457          operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
25458        if (cond.Is(al)) {
25459          const DRegister& first = nreglist.GetFirstDRegister();
25460          EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
25461                  (encoded_align_1.GetEncodingValue() << 4) |
25462                  first.Encode(22, 12) | (rn.GetCode() << 16));
25463          return;
25464        }
25465      }
25466    }
25467  }
25468  if (operand.IsPlainRegister()) {
25469    Register rn = operand.GetBaseRegister();
25470    Sign sign = operand.GetSign();
25471    Register rm = operand.GetOffsetRegister();
25472    Dt_size_7 encoded_dt(dt);
25473    Index_1 encoded_align_1(nreglist, dt);
25474    if (IsUsingT32()) {
25475      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
25476      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25477          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25478           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25479          sign.IsPlus() && operand.IsPostIndex()) {
25480        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25481          const DRegister& first = nreglist.GetFirstDRegister();
25482          EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
25483                     (encoded_align_1.GetEncodingValue() << 4) |
25484                     first.Encode(22, 12) | (rn.GetCode() << 16) |
25485                     rm.GetCode());
25486          AdvanceIT();
25487          return;
25488        }
25489      }
25490    } else {
25491      // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
25492      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25493          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25494           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25495          sign.IsPlus() && operand.IsPostIndex()) {
25496        if (cond.Is(al)) {
25497          const DRegister& first = nreglist.GetFirstDRegister();
25498          EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
25499                  (encoded_align_1.GetEncodingValue() << 4) |
25500                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25501          return;
25502        }
25503      }
25504    }
25505  }
25506  Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
25507}
25508
25509void Assembler::vst4(Condition cond,
25510                     DataType dt,
25511                     const NeonRegisterList& nreglist,
25512                     const AlignedMemOperand& operand) {
25513  VIXL_ASSERT(AllowAssembler());
25514  CheckIT(cond);
25515  if (operand.IsImmediateZero()) {
25516    Register rn = operand.GetBaseRegister();
25517    Alignment align = operand.GetAlignment();
25518    Dt_size_7 encoded_dt(dt);
25519    Align_align_4 encoded_align_1(align);
25520    Align_index_align_3 encoded_align_2(align, nreglist, dt);
25521    if (IsUsingT32()) {
25522      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25523      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25524          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25525           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25526          operand.IsOffset() && encoded_align_1.IsValid() &&
25527          (!rn.IsPC() || AllowUnpredictable())) {
25528        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25529          const DRegister& first = nreglist.GetFirstDRegister();
25530          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25531          EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25532                     (encoded_align_1.GetEncodingValue() << 4) |
25533                     first.Encode(22, 12) | (len_encoding << 8) |
25534                     (rn.GetCode() << 16));
25535          AdvanceIT();
25536          return;
25537        }
25538      }
25539      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25540      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25541          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25542           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25543          operand.IsPostIndex() && encoded_align_1.IsValid() &&
25544          (!rn.IsPC() || AllowUnpredictable())) {
25545        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25546          const DRegister& first = nreglist.GetFirstDRegister();
25547          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25548          EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25549                     (encoded_align_1.GetEncodingValue() << 4) |
25550                     first.Encode(22, 12) | (len_encoding << 8) |
25551                     (rn.GetCode() << 16));
25552          AdvanceIT();
25553          return;
25554        }
25555      }
25556      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25557      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25558          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25559           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25560          operand.IsOffset() && encoded_align_2.IsValid() &&
25561          (!rn.IsPC() || AllowUnpredictable())) {
25562        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25563          const DRegister& first = nreglist.GetFirstDRegister();
25564          EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
25565                     (encoded_align_2.GetEncodingValue() << 4) |
25566                     first.Encode(22, 12) | (rn.GetCode() << 16));
25567          AdvanceIT();
25568          return;
25569        }
25570      }
25571      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25572      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25573          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25574           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25575          operand.IsPostIndex() && encoded_align_2.IsValid() &&
25576          (!rn.IsPC() || AllowUnpredictable())) {
25577        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25578          const DRegister& first = nreglist.GetFirstDRegister();
25579          EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
25580                     (encoded_align_2.GetEncodingValue() << 4) |
25581                     first.Encode(22, 12) | (rn.GetCode() << 16));
25582          AdvanceIT();
25583          return;
25584        }
25585      }
25586    } else {
25587      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25588      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25589          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25590           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25591          operand.IsOffset() && encoded_align_1.IsValid() &&
25592          (!rn.IsPC() || AllowUnpredictable())) {
25593        if (cond.Is(al)) {
25594          const DRegister& first = nreglist.GetFirstDRegister();
25595          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25596          EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25597                  (encoded_align_1.GetEncodingValue() << 4) |
25598                  first.Encode(22, 12) | (len_encoding << 8) |
25599                  (rn.GetCode() << 16));
25600          return;
25601        }
25602      }
25603      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25604      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25605          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25606           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25607          operand.IsPostIndex() && encoded_align_1.IsValid() &&
25608          (!rn.IsPC() || AllowUnpredictable())) {
25609        if (cond.Is(al)) {
25610          const DRegister& first = nreglist.GetFirstDRegister();
25611          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25612          EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25613                  (encoded_align_1.GetEncodingValue() << 4) |
25614                  first.Encode(22, 12) | (len_encoding << 8) |
25615                  (rn.GetCode() << 16));
25616          return;
25617        }
25618      }
25619      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25620      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25621          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25622           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25623          operand.IsOffset() && encoded_align_2.IsValid() &&
25624          (!rn.IsPC() || AllowUnpredictable())) {
25625        if (cond.Is(al)) {
25626          const DRegister& first = nreglist.GetFirstDRegister();
25627          EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
25628                  (encoded_align_2.GetEncodingValue() << 4) |
25629                  first.Encode(22, 12) | (rn.GetCode() << 16));
25630          return;
25631        }
25632      }
25633      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25634      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25635          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25636           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25637          operand.IsPostIndex() && encoded_align_2.IsValid() &&
25638          (!rn.IsPC() || AllowUnpredictable())) {
25639        if (cond.Is(al)) {
25640          const DRegister& first = nreglist.GetFirstDRegister();
25641          EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
25642                  (encoded_align_2.GetEncodingValue() << 4) |
25643                  first.Encode(22, 12) | (rn.GetCode() << 16));
25644          return;
25645        }
25646      }
25647    }
25648  }
25649  if (operand.IsPlainRegister()) {
25650    Register rn = operand.GetBaseRegister();
25651    Alignment align = operand.GetAlignment();
25652    Register rm = operand.GetOffsetRegister();
25653    Dt_size_7 encoded_dt(dt);
25654    Align_align_4 encoded_align_1(align);
25655    Align_index_align_3 encoded_align_2(align, nreglist, dt);
25656    if (IsUsingT32()) {
25657      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25658      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25659          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25660           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25661          !rm.IsPC() && !rm.IsSP()) {
25662        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25663          const DRegister& first = nreglist.GetFirstDRegister();
25664          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25665          EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25666                     (encoded_align_1.GetEncodingValue() << 4) |
25667                     first.Encode(22, 12) | (len_encoding << 8) |
25668                     (rn.GetCode() << 16) | rm.GetCode());
25669          AdvanceIT();
25670          return;
25671        }
25672      }
25673      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25674      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25675          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25676           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25677          !rm.IsPC() && !rm.IsSP()) {
25678        if (cond.Is(al) || AllowStronglyDiscouraged()) {
25679          const DRegister& first = nreglist.GetFirstDRegister();
25680          EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
25681                     (encoded_align_2.GetEncodingValue() << 4) |
25682                     first.Encode(22, 12) | (rn.GetCode() << 16) |
25683                     rm.GetCode());
25684          AdvanceIT();
25685          return;
25686        }
25687      }
25688    } else {
25689      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25690      if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25691          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25692           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25693          !rm.IsPC() && !rm.IsSP()) {
25694        if (cond.Is(al)) {
25695          const DRegister& first = nreglist.GetFirstDRegister();
25696          uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25697          EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25698                  (encoded_align_1.GetEncodingValue() << 4) |
25699                  first.Encode(22, 12) | (len_encoding << 8) |
25700                  (rn.GetCode() << 16) | rm.GetCode());
25701          return;
25702        }
25703      }
25704      // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25705      if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25706          ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25707           (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25708          !rm.IsPC() && !rm.IsSP()) {
25709        if (cond.Is(al)) {
25710          const DRegister& first = nreglist.GetFirstDRegister();
25711          EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
25712                  (encoded_align_2.GetEncodingValue() << 4) |
25713                  first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25714          return;
25715        }
25716      }
25717    }
25718  }
25719  Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
25720}
25721
25722void Assembler::vstm(Condition cond,
25723                     DataType dt,
25724                     Register rn,
25725                     WriteBack write_back,
25726                     DRegisterList dreglist) {
25727  VIXL_ASSERT(AllowAssembler());
25728  CheckIT(cond);
25729  USE(dt);
25730  if (IsUsingT32()) {
25731    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
25732    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
25733      const DRegister& dreg = dreglist.GetFirstDRegister();
25734      unsigned len = dreglist.GetLength() * 2;
25735      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
25736                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25737                 (len & 0xff));
25738      AdvanceIT();
25739      return;
25740    }
25741  } else {
25742    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
25743    if (cond.IsNotNever() &&
25744        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
25745      const DRegister& dreg = dreglist.GetFirstDRegister();
25746      unsigned len = dreglist.GetLength() * 2;
25747      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25748              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25749              (len & 0xff));
25750      return;
25751    }
25752  }
25753  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
25754}
25755
25756void Assembler::vstm(Condition cond,
25757                     DataType dt,
25758                     Register rn,
25759                     WriteBack write_back,
25760                     SRegisterList sreglist) {
25761  VIXL_ASSERT(AllowAssembler());
25762  CheckIT(cond);
25763  USE(dt);
25764  if (IsUsingT32()) {
25765    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
25766    const SRegister& sreg = sreglist.GetFirstSRegister();
25767    unsigned len = sreglist.GetLength();
25768    EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
25769               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25770               (len & 0xff));
25771    AdvanceIT();
25772    return;
25773  } else {
25774    // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
25775    if (cond.IsNotNever()) {
25776      const SRegister& sreg = sreglist.GetFirstSRegister();
25777      unsigned len = sreglist.GetLength();
25778      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25779              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25780              (len & 0xff));
25781      return;
25782    }
25783  }
25784  Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
25785}
25786
25787void Assembler::vstmdb(Condition cond,
25788                       DataType dt,
25789                       Register rn,
25790                       WriteBack write_back,
25791                       DRegisterList dreglist) {
25792  VIXL_ASSERT(AllowAssembler());
25793  CheckIT(cond);
25794  USE(dt);
25795  if (IsUsingT32()) {
25796    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
25797    if (write_back.DoesWriteBack() &&
25798        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
25799      const DRegister& dreg = dreglist.GetFirstDRegister();
25800      unsigned len = dreglist.GetLength() * 2;
25801      EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
25802                 (len & 0xff));
25803      AdvanceIT();
25804      return;
25805    }
25806  } else {
25807    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
25808    if (write_back.DoesWriteBack() && cond.IsNotNever() &&
25809        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
25810      const DRegister& dreg = dreglist.GetFirstDRegister();
25811      unsigned len = dreglist.GetLength() * 2;
25812      EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25813              dreg.Encode(22, 12) | (len & 0xff));
25814      return;
25815    }
25816  }
25817  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
25818}
25819
25820void Assembler::vstmdb(Condition cond,
25821                       DataType dt,
25822                       Register rn,
25823                       WriteBack write_back,
25824                       SRegisterList sreglist) {
25825  VIXL_ASSERT(AllowAssembler());
25826  CheckIT(cond);
25827  USE(dt);
25828  if (IsUsingT32()) {
25829    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
25830    if (write_back.DoesWriteBack()) {
25831      const SRegister& sreg = sreglist.GetFirstSRegister();
25832      unsigned len = sreglist.GetLength();
25833      EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
25834                 (len & 0xff));
25835      AdvanceIT();
25836      return;
25837    }
25838  } else {
25839    // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
25840    if (write_back.DoesWriteBack() && cond.IsNotNever()) {
25841      const SRegister& sreg = sreglist.GetFirstSRegister();
25842      unsigned len = sreglist.GetLength();
25843      EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25844              sreg.Encode(22, 12) | (len & 0xff));
25845      return;
25846    }
25847  }
25848  Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
25849}
25850
25851void Assembler::vstmia(Condition cond,
25852                       DataType dt,
25853                       Register rn,
25854                       WriteBack write_back,
25855                       DRegisterList dreglist) {
25856  VIXL_ASSERT(AllowAssembler());
25857  CheckIT(cond);
25858  USE(dt);
25859  if (IsUsingT32()) {
25860    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
25861    if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
25862      const DRegister& dreg = dreglist.GetFirstDRegister();
25863      unsigned len = dreglist.GetLength() * 2;
25864      EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
25865                 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25866                 (len & 0xff));
25867      AdvanceIT();
25868      return;
25869    }
25870  } else {
25871    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
25872    if (cond.IsNotNever() &&
25873        ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
25874      const DRegister& dreg = dreglist.GetFirstDRegister();
25875      unsigned len = dreglist.GetLength() * 2;
25876      EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25877              (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25878              (len & 0xff));
25879      return;
25880    }
25881  }
25882  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
25883}
25884
25885void Assembler::vstmia(Condition cond,
25886                       DataType dt,
25887                       Register rn,
25888                       WriteBack write_back,
25889                       SRegisterList sreglist) {
25890  VIXL_ASSERT(AllowAssembler());
25891  CheckIT(cond);
25892  USE(dt);
25893  if (IsUsingT32()) {
25894    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
25895    const SRegister& sreg = sreglist.GetFirstSRegister();
25896    unsigned len = sreglist.GetLength();
25897    EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
25898               (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25899               (len & 0xff));
25900    AdvanceIT();
25901    return;
25902  } else {
25903    // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
25904    if (cond.IsNotNever()) {
25905      const SRegister& sreg = sreglist.GetFirstSRegister();
25906      unsigned len = sreglist.GetLength();
25907      EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25908              (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25909              (len & 0xff));
25910      return;
25911    }
25912  }
25913  Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
25914}
25915
25916void Assembler::vstr(Condition cond,
25917                     DataType dt,
25918                     DRegister rd,
25919                     const MemOperand& operand) {
25920  VIXL_ASSERT(AllowAssembler());
25921  CheckIT(cond);
25922  if (operand.IsImmediate()) {
25923    Register rn = operand.GetBaseRegister();
25924    int32_t offset = operand.GetOffsetImmediate();
25925    if (IsUsingT32()) {
25926      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
25927      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
25928          ((offset % 4) == 0) && operand.IsOffset()) {
25929        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25930        uint32_t offset_ = abs(offset) >> 2;
25931        EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
25932                   offset_ | (sign << 23));
25933        AdvanceIT();
25934        return;
25935      }
25936    } else {
25937      // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
25938      if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
25939          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
25940        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25941        uint32_t offset_ = abs(offset) >> 2;
25942        EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25943                (rn.GetCode() << 16) | offset_ | (sign << 23));
25944        return;
25945      }
25946    }
25947  }
25948  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
25949}
25950
25951void Assembler::vstr(Condition cond,
25952                     DataType dt,
25953                     SRegister rd,
25954                     const MemOperand& operand) {
25955  VIXL_ASSERT(AllowAssembler());
25956  CheckIT(cond);
25957  if (operand.IsImmediate()) {
25958    Register rn = operand.GetBaseRegister();
25959    int32_t offset = operand.GetOffsetImmediate();
25960    if (IsUsingT32()) {
25961      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
25962      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
25963          ((offset % 4) == 0) && operand.IsOffset()) {
25964        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25965        uint32_t offset_ = abs(offset) >> 2;
25966        EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
25967                   offset_ | (sign << 23));
25968        AdvanceIT();
25969        return;
25970      }
25971    } else {
25972      // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
25973      if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
25974          ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
25975        uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25976        uint32_t offset_ = abs(offset) >> 2;
25977        EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25978                (rn.GetCode() << 16) | offset_ | (sign << 23));
25979        return;
25980      }
25981    }
25982  }
25983  Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
25984}
25985
25986void Assembler::vsub(
25987    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
25988  VIXL_ASSERT(AllowAssembler());
25989  CheckIT(cond);
25990  Dt_size_2 encoded_dt(dt);
25991  if (IsUsingT32()) {
25992    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
25993    if (dt.Is(F32)) {
25994      if (cond.Is(al) || AllowStronglyDiscouraged()) {
25995        EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25996                   rm.Encode(5, 0));
25997        AdvanceIT();
25998        return;
25999      }
26000    }
26001    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
26002    if (dt.Is(F64)) {
26003      EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26004                 rm.Encode(5, 0));
26005      AdvanceIT();
26006      return;
26007    }
26008    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
26009    if (encoded_dt.IsValid()) {
26010      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26011        EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
26012                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26013        AdvanceIT();
26014        return;
26015      }
26016    }
26017  } else {
26018    // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
26019    if (dt.Is(F32)) {
26020      if (cond.Is(al)) {
26021        EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26022                rm.Encode(5, 0));
26023        return;
26024      }
26025    }
26026    // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
26027    if (dt.Is(F64) && cond.IsNotNever()) {
26028      EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26029              rn.Encode(7, 16) | rm.Encode(5, 0));
26030      return;
26031    }
26032    // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
26033    if (encoded_dt.IsValid()) {
26034      if (cond.Is(al)) {
26035        EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
26036                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26037        return;
26038      }
26039    }
26040  }
26041  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26042}
26043
26044void Assembler::vsub(
26045    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
26046  VIXL_ASSERT(AllowAssembler());
26047  CheckIT(cond);
26048  Dt_size_2 encoded_dt(dt);
26049  if (IsUsingT32()) {
26050    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
26051    if (dt.Is(F32)) {
26052      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26053        EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26054                   rm.Encode(5, 0));
26055        AdvanceIT();
26056        return;
26057      }
26058    }
26059    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
26060    if (encoded_dt.IsValid()) {
26061      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26062        EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
26063                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26064        AdvanceIT();
26065        return;
26066      }
26067    }
26068  } else {
26069    // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
26070    if (dt.Is(F32)) {
26071      if (cond.Is(al)) {
26072        EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26073                rm.Encode(5, 0));
26074        return;
26075      }
26076    }
26077    // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
26078    if (encoded_dt.IsValid()) {
26079      if (cond.Is(al)) {
26080        EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
26081                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26082        return;
26083      }
26084    }
26085  }
26086  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26087}
26088
26089void Assembler::vsub(
26090    Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
26091  VIXL_ASSERT(AllowAssembler());
26092  CheckIT(cond);
26093  if (IsUsingT32()) {
26094    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
26095    if (dt.Is(F32)) {
26096      EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26097                 rm.Encode(5, 0));
26098      AdvanceIT();
26099      return;
26100    }
26101  } else {
26102    // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
26103    if (dt.Is(F32) && cond.IsNotNever()) {
26104      EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26105              rn.Encode(7, 16) | rm.Encode(5, 0));
26106      return;
26107    }
26108  }
26109  Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26110}
26111
26112void Assembler::vsubhn(
26113    Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
26114  VIXL_ASSERT(AllowAssembler());
26115  CheckIT(cond);
26116  Dt_size_3 encoded_dt(dt);
26117  if (IsUsingT32()) {
26118    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
26119    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
26120      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26121        EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
26122                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26123        AdvanceIT();
26124        return;
26125      }
26126    }
26127  } else {
26128    // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
26129    if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
26130      if (cond.Is(al)) {
26131        EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
26132                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26133        return;
26134      }
26135    }
26136  }
26137  Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
26138}
26139
26140void Assembler::vsubl(
26141    Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
26142  VIXL_ASSERT(AllowAssembler());
26143  CheckIT(cond);
26144  Dt_U_size_1 encoded_dt(dt);
26145  if (IsUsingT32()) {
26146    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
26147    if (encoded_dt.IsValid()) {
26148      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26149        EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26150                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
26151                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26152        AdvanceIT();
26153        return;
26154      }
26155    }
26156  } else {
26157    // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
26158    if (encoded_dt.IsValid()) {
26159      if (cond.Is(al)) {
26160        EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26161                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
26162                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26163        return;
26164      }
26165    }
26166  }
26167  Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
26168}
26169
26170void Assembler::vsubw(
26171    Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
26172  VIXL_ASSERT(AllowAssembler());
26173  CheckIT(cond);
26174  Dt_U_size_1 encoded_dt(dt);
26175  if (IsUsingT32()) {
26176    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
26177    if (encoded_dt.IsValid()) {
26178      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26179        EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26180                   ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
26181                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26182        AdvanceIT();
26183        return;
26184      }
26185    }
26186  } else {
26187    // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
26188    if (encoded_dt.IsValid()) {
26189      if (cond.Is(al)) {
26190        EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26191                ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
26192                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26193        return;
26194      }
26195    }
26196  }
26197  Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
26198}
26199
26200void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26201  VIXL_ASSERT(AllowAssembler());
26202  CheckIT(cond);
26203  USE(dt);
26204  if (IsUsingT32()) {
26205    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
26206    if (cond.Is(al) || AllowStronglyDiscouraged()) {
26207      EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
26208      AdvanceIT();
26209      return;
26210    }
26211  } else {
26212    // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
26213    if (cond.Is(al)) {
26214      EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
26215      return;
26216    }
26217  }
26218  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
26219}
26220
26221void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26222  VIXL_ASSERT(AllowAssembler());
26223  CheckIT(cond);
26224  USE(dt);
26225  if (IsUsingT32()) {
26226    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
26227    if (cond.Is(al) || AllowStronglyDiscouraged()) {
26228      EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
26229      AdvanceIT();
26230      return;
26231    }
26232  } else {
26233    // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
26234    if (cond.Is(al)) {
26235      EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
26236      return;
26237    }
26238  }
26239  Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
26240}
26241
26242void Assembler::vtbl(Condition cond,
26243                     DataType dt,
26244                     DRegister rd,
26245                     const NeonRegisterList& nreglist,
26246                     DRegister rm) {
26247  VIXL_ASSERT(AllowAssembler());
26248  CheckIT(cond);
26249  if (IsUsingT32()) {
26250    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
26251    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26252        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26253      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26254        const DRegister& first = nreglist.GetFirstDRegister();
26255        uint32_t len_encoding = nreglist.GetLength() - 1;
26256        EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
26257                   (len_encoding << 8) | rm.Encode(5, 0));
26258        AdvanceIT();
26259        return;
26260      }
26261    }
26262  } else {
26263    // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
26264    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26265        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26266      if (cond.Is(al)) {
26267        const DRegister& first = nreglist.GetFirstDRegister();
26268        uint32_t len_encoding = nreglist.GetLength() - 1;
26269        EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
26270                (len_encoding << 8) | rm.Encode(5, 0));
26271        return;
26272      }
26273    }
26274  }
26275  Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
26276}
26277
26278void Assembler::vtbx(Condition cond,
26279                     DataType dt,
26280                     DRegister rd,
26281                     const NeonRegisterList& nreglist,
26282                     DRegister rm) {
26283  VIXL_ASSERT(AllowAssembler());
26284  CheckIT(cond);
26285  if (IsUsingT32()) {
26286    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
26287    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26288        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26289      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26290        const DRegister& first = nreglist.GetFirstDRegister();
26291        uint32_t len_encoding = nreglist.GetLength() - 1;
26292        EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
26293                   (len_encoding << 8) | rm.Encode(5, 0));
26294        AdvanceIT();
26295        return;
26296      }
26297    }
26298  } else {
26299    // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
26300    if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26301        (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26302      if (cond.Is(al)) {
26303        const DRegister& first = nreglist.GetFirstDRegister();
26304        uint32_t len_encoding = nreglist.GetLength() - 1;
26305        EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
26306                (len_encoding << 8) | rm.Encode(5, 0));
26307        return;
26308      }
26309    }
26310  }
26311  Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
26312}
26313
26314void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26315  VIXL_ASSERT(AllowAssembler());
26316  CheckIT(cond);
26317  Dt_size_7 encoded_dt(dt);
26318  if (IsUsingT32()) {
26319    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26320    if (encoded_dt.IsValid()) {
26321      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26322        EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
26323                   rd.Encode(22, 12) | rm.Encode(5, 0));
26324        AdvanceIT();
26325        return;
26326      }
26327    }
26328  } else {
26329    // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26330    if (encoded_dt.IsValid()) {
26331      if (cond.Is(al)) {
26332        EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
26333                rd.Encode(22, 12) | rm.Encode(5, 0));
26334        return;
26335      }
26336    }
26337  }
26338  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
26339}
26340
26341void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26342  VIXL_ASSERT(AllowAssembler());
26343  CheckIT(cond);
26344  Dt_size_7 encoded_dt(dt);
26345  if (IsUsingT32()) {
26346    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26347    if (encoded_dt.IsValid()) {
26348      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26349        EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
26350                   rd.Encode(22, 12) | rm.Encode(5, 0));
26351        AdvanceIT();
26352        return;
26353      }
26354    }
26355  } else {
26356    // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26357    if (encoded_dt.IsValid()) {
26358      if (cond.Is(al)) {
26359        EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
26360                rd.Encode(22, 12) | rm.Encode(5, 0));
26361        return;
26362      }
26363    }
26364  }
26365  Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
26366}
26367
26368void Assembler::vtst(
26369    Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
26370  VIXL_ASSERT(AllowAssembler());
26371  CheckIT(cond);
26372  Dt_size_7 encoded_dt(dt);
26373  if (IsUsingT32()) {
26374    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
26375    if (encoded_dt.IsValid()) {
26376      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26377        EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
26378                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26379        AdvanceIT();
26380        return;
26381      }
26382    }
26383  } else {
26384    // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
26385    if (encoded_dt.IsValid()) {
26386      if (cond.Is(al)) {
26387        EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
26388                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26389        return;
26390      }
26391    }
26392  }
26393  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
26394}
26395
26396void Assembler::vtst(
26397    Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
26398  VIXL_ASSERT(AllowAssembler());
26399  CheckIT(cond);
26400  Dt_size_7 encoded_dt(dt);
26401  if (IsUsingT32()) {
26402    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
26403    if (encoded_dt.IsValid()) {
26404      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26405        EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
26406                   rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26407        AdvanceIT();
26408        return;
26409      }
26410    }
26411  } else {
26412    // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
26413    if (encoded_dt.IsValid()) {
26414      if (cond.Is(al)) {
26415        EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
26416                rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26417        return;
26418      }
26419    }
26420  }
26421  Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
26422}
26423
26424void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26425  VIXL_ASSERT(AllowAssembler());
26426  CheckIT(cond);
26427  Dt_size_15 encoded_dt(dt);
26428  if (IsUsingT32()) {
26429    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26430    if (encoded_dt.IsValid()) {
26431      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26432        EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
26433                   rd.Encode(22, 12) | rm.Encode(5, 0));
26434        AdvanceIT();
26435        return;
26436      }
26437    }
26438    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
26439    if (dt.Is(Untyped32)) {
26440      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26441        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26442        AdvanceIT();
26443        return;
26444      }
26445    }
26446  } else {
26447    // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26448    if (encoded_dt.IsValid()) {
26449      if (cond.Is(al)) {
26450        EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
26451                rd.Encode(22, 12) | rm.Encode(5, 0));
26452        return;
26453      }
26454    }
26455    // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
26456    if (dt.Is(Untyped32)) {
26457      if (cond.Is(al)) {
26458        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26459        return;
26460      }
26461    }
26462  }
26463  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
26464}
26465
26466void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26467  VIXL_ASSERT(AllowAssembler());
26468  CheckIT(cond);
26469  Dt_size_7 encoded_dt(dt);
26470  if (IsUsingT32()) {
26471    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26472    if (encoded_dt.IsValid()) {
26473      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26474        EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
26475                   rd.Encode(22, 12) | rm.Encode(5, 0));
26476        AdvanceIT();
26477        return;
26478      }
26479    }
26480  } else {
26481    // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26482    if (encoded_dt.IsValid()) {
26483      if (cond.Is(al)) {
26484        EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
26485                rd.Encode(22, 12) | rm.Encode(5, 0));
26486        return;
26487      }
26488    }
26489  }
26490  Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
26491}
26492
26493void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
26494  VIXL_ASSERT(AllowAssembler());
26495  CheckIT(cond);
26496  Dt_size_15 encoded_dt(dt);
26497  if (IsUsingT32()) {
26498    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26499    if (encoded_dt.IsValid()) {
26500      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26501        EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
26502                   rd.Encode(22, 12) | rm.Encode(5, 0));
26503        AdvanceIT();
26504        return;
26505      }
26506    }
26507    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
26508    if (dt.Is(Untyped32)) {
26509      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26510        EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26511        AdvanceIT();
26512        return;
26513      }
26514    }
26515  } else {
26516    // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26517    if (encoded_dt.IsValid()) {
26518      if (cond.Is(al)) {
26519        EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
26520                rd.Encode(22, 12) | rm.Encode(5, 0));
26521        return;
26522      }
26523    }
26524    // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
26525    if (dt.Is(Untyped32)) {
26526      if (cond.Is(al)) {
26527        EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26528        return;
26529      }
26530    }
26531  }
26532  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
26533}
26534
26535void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
26536  VIXL_ASSERT(AllowAssembler());
26537  CheckIT(cond);
26538  Dt_size_7 encoded_dt(dt);
26539  if (IsUsingT32()) {
26540    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26541    if (encoded_dt.IsValid()) {
26542      if (cond.Is(al) || AllowStronglyDiscouraged()) {
26543        EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
26544                   rd.Encode(22, 12) | rm.Encode(5, 0));
26545        AdvanceIT();
26546        return;
26547      }
26548    }
26549  } else {
26550    // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26551    if (encoded_dt.IsValid()) {
26552      if (cond.Is(al)) {
26553        EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
26554                rd.Encode(22, 12) | rm.Encode(5, 0));
26555        return;
26556      }
26557    }
26558  }
26559  Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
26560}
26561
26562void Assembler::yield(Condition cond, EncodingSize size) {
26563  VIXL_ASSERT(AllowAssembler());
26564  CheckIT(cond);
26565  if (IsUsingT32()) {
26566    // YIELD{<c>}{<q>} ; T1
26567    if (!size.IsWide()) {
26568      EmitT32_16(0xbf10);
26569      AdvanceIT();
26570      return;
26571    }
26572    // YIELD{<c>}.W ; T2
26573    if (!size.IsNarrow()) {
26574      EmitT32_32(0xf3af8001U);
26575      AdvanceIT();
26576      return;
26577    }
26578  } else {
26579    // YIELD{<c>}{<q>} ; A1
26580    if (cond.IsNotNever()) {
26581      EmitA32(0x0320f001U | (cond.GetCondition() << 28));
26582      return;
26583    }
26584  }
26585  Delegate(kYield, &Assembler::yield, cond, size);
26586}
26587// End of generated code.
26588
26589}  // namespace aarch32
26590}  // namespace vixl
26591