blob: 3028ce8ede1f1272f9ebc5994f17a98ec623e889 [file] [log] [blame]
Alexandre Ramesd3832962016-07-04 15:03:43 +01001// 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
Pierre Langlois78973f22016-08-10 14:35:56 +010027extern "C" {
Alexandre Ramesd3832962016-07-04 15:03:43 +010028#include <stdint.h>
Pierre Langlois78973f22016-08-10 14:35:56 +010029}
30
31#include <cassert>
32#include <cstdio>
33#include <cstdlib>
34#include <cstring>
Alexandre Ramesd3832962016-07-04 15:03:43 +010035#include <iostream> // NOLINT
Pierre Langlois78973f22016-08-10 14:35:56 +010036
Alexandre Ramesd3832962016-07-04 15:03:43 +010037#include "utils-vixl.h"
38#include "aarch32/constants-aarch32.h"
39#include "aarch32/instructions-aarch32.h"
40#include "aarch32/operand-aarch32.h"
41#include "aarch32/assembler-aarch32.h"
42
43namespace vixl {
44namespace aarch32 {
45
46void Assembler::EmitT32_16(uint16_t instr) {
47 VIXL_ASSERT(buffer_.Is16bitAligned());
48 buffer_.Emit16(instr);
49}
50
51
52void Assembler::EmitT32_32(uint32_t instr) {
53 VIXL_ASSERT(buffer_.Is16bitAligned());
54 buffer_.Emit16(static_cast<uint16_t>(instr >> 16));
55 buffer_.Emit16(static_cast<uint16_t>(instr & 0xffff));
56}
57
58
59void Assembler::EmitA32(uint32_t instr) {
60 VIXL_ASSERT(buffer_.Is32bitAligned());
61 buffer_.Emit32(instr);
62}
63
64
65#ifdef VIXL_DEBUG
66void Assembler::PerformCheckIT(Condition condition) {
67 if (it_mask_ == 0) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010068 VIXL_ASSERT(IsUsingA32() || condition.Is(al));
Alexandre Ramesd3832962016-07-04 15:03:43 +010069 } 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.
Jacob Bramley10dae1a2016-07-27 09:45:13 +010076 if (IsUsingA32()) AdvanceIT();
Alexandre Ramesd3832962016-07-04 15:03:43 +010077 }
78}
79#endif
80
81
Vincent Belliarde42218c2016-10-19 13:24:28 -070082void Assembler::BindHelper(Label* label) {
83 VIXL_ASSERT(!label->IsBound());
84 label->Bind(GetCursorOffset(), IsUsingT32());
85
86 for (Label::ForwardRefList::iterator ref = label->GetFirstForwardRef();
87 ref != label->GetEndForwardRef();
88 ref++) {
89 EncodeLabelFor(*ref, label);
90 }
91}
92
93
Alexandre Ramesd3832962016-07-04 15:03:43 +010094uint32_t Assembler::Link(uint32_t instr,
95 Label* label,
96 const Label::LabelEmitOperator& op) {
97 if (label->IsBound()) {
98 return op.Encode(instr,
99 GetCursorOffset() + GetArchitectureStatePCOffset(),
100 label);
101 }
Jacob Bramley10dae1a2016-07-27 09:45:13 +0100102 label->AddForwardRef(GetCursorOffset(), IsUsingT32(), op);
Alexandre Ramesd3832962016-07-04 15:03:43 +0100103 return instr;
104}
105
106
107void Assembler::EncodeLabelFor(const Label::ForwardReference& forward,
108 Label* label) {
109 const uint32_t location = forward.GetLocation();
110 const uint32_t from = location + forward.GetStatePCOffset();
111 const Label::LabelEmitOperator& encoder = forward.GetEmitOperator();
Jacob Bramley10dae1a2016-07-27 09:45:13 +0100112 if (forward.IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +0100113 uint16_t* instr_ptr = buffer_.GetOffsetAddress<uint16_t*>(location);
114 if (Is16BitEncoding(instr_ptr[0])) {
115 // The Encode methods always deals with uint32_t types so we need
116 // to explicitely cast it.
117 uint32_t instr = static_cast<uint32_t>(instr_ptr[0]);
118 instr = encoder.Encode(instr, from, label);
119 // The Encode method should not ever set the top 16 bits.
120 VIXL_ASSERT((instr & ~0xffff) == 0);
121 instr_ptr[0] = static_cast<uint16_t>(instr);
122 } else {
123 uint32_t instr =
124 instr_ptr[1] | (static_cast<uint32_t>(instr_ptr[0]) << 16);
125 instr = encoder.Encode(instr, from, label);
126 instr_ptr[0] = static_cast<uint16_t>(instr >> 16);
127 instr_ptr[1] = static_cast<uint16_t>(instr);
128 }
129 } else {
130 uint32_t* instr_ptr = buffer_.GetOffsetAddress<uint32_t*>(location);
131 instr_ptr[0] = encoder.Encode(instr_ptr[0], from, label);
132 }
133}
134
135
Alexandre Ramesd3832962016-07-04 15:03:43 +0100136// Start of generated code.
137class Dt_L_imm6_1 : public EncodingValue {
138 uint32_t type_;
139
140 public:
141 explicit Dt_L_imm6_1(DataType dt);
142 uint32_t GetTypeEncodingValue() const { return type_; }
143};
144
145Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
146 switch (dt.GetValue()) {
147 case S8:
148 type_ = 0x0;
149 SetEncodingValue(0x1);
150 break;
151 case U8:
152 type_ = 0x1;
153 SetEncodingValue(0x1);
154 break;
155 case S16:
156 type_ = 0x0;
157 SetEncodingValue(0x2);
158 break;
159 case U16:
160 type_ = 0x1;
161 SetEncodingValue(0x2);
162 break;
163 case S32:
164 type_ = 0x0;
165 SetEncodingValue(0x4);
166 break;
167 case U32:
168 type_ = 0x1;
169 SetEncodingValue(0x4);
170 break;
171 case S64:
172 type_ = 0x0;
173 SetEncodingValue(0x8);
174 break;
175 case U64:
176 type_ = 0x1;
177 SetEncodingValue(0x8);
178 break;
179 default:
180 VIXL_UNREACHABLE();
181 type_ = 0x0;
182 break;
183 }
184}
185
186class Dt_L_imm6_2 : public EncodingValue {
187 uint32_t type_;
188
189 public:
190 explicit Dt_L_imm6_2(DataType dt);
191 uint32_t GetTypeEncodingValue() const { return type_; }
192};
193
194Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
195 switch (dt.GetValue()) {
196 case S8:
197 type_ = 0x1;
198 SetEncodingValue(0x1);
199 break;
200 case S16:
201 type_ = 0x1;
202 SetEncodingValue(0x2);
203 break;
204 case S32:
205 type_ = 0x1;
206 SetEncodingValue(0x4);
207 break;
208 case S64:
209 type_ = 0x1;
210 SetEncodingValue(0x8);
211 break;
212 default:
213 VIXL_UNREACHABLE();
214 type_ = 0x0;
215 break;
216 }
217}
218
219class Dt_L_imm6_3 : public EncodingValue {
220 public:
221 explicit Dt_L_imm6_3(DataType dt);
222};
223
224Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
225 switch (dt.GetValue()) {
226 case I8:
227 SetEncodingValue(0x1);
228 break;
229 case I16:
230 SetEncodingValue(0x2);
231 break;
232 case I32:
233 SetEncodingValue(0x4);
234 break;
235 case I64:
236 SetEncodingValue(0x8);
237 break;
238 default:
239 break;
240 }
241}
242
243class Dt_L_imm6_4 : public EncodingValue {
244 public:
245 explicit Dt_L_imm6_4(DataType dt);
246};
247
248Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
249 switch (dt.GetValue()) {
250 case Untyped8:
251 SetEncodingValue(0x1);
252 break;
253 case Untyped16:
254 SetEncodingValue(0x2);
255 break;
256 case Untyped32:
257 SetEncodingValue(0x4);
258 break;
259 case Untyped64:
260 SetEncodingValue(0x8);
261 break;
262 default:
263 break;
264 }
265}
266
267class Dt_imm6_1 : public EncodingValue {
268 uint32_t type_;
269
270 public:
271 explicit Dt_imm6_1(DataType dt);
272 uint32_t GetTypeEncodingValue() const { return type_; }
273};
274
275Dt_imm6_1::Dt_imm6_1(DataType dt) {
276 switch (dt.GetValue()) {
277 case S16:
278 type_ = 0x0;
279 SetEncodingValue(0x1);
280 break;
281 case U16:
282 type_ = 0x1;
283 SetEncodingValue(0x1);
284 break;
285 case S32:
286 type_ = 0x0;
287 SetEncodingValue(0x2);
288 break;
289 case U32:
290 type_ = 0x1;
291 SetEncodingValue(0x2);
292 break;
293 case S64:
294 type_ = 0x0;
295 SetEncodingValue(0x4);
296 break;
297 case U64:
298 type_ = 0x1;
299 SetEncodingValue(0x4);
300 break;
301 default:
302 VIXL_UNREACHABLE();
303 type_ = 0x0;
304 break;
305 }
306}
307
308class Dt_imm6_2 : public EncodingValue {
309 uint32_t type_;
310
311 public:
312 explicit Dt_imm6_2(DataType dt);
313 uint32_t GetTypeEncodingValue() const { return type_; }
314};
315
316Dt_imm6_2::Dt_imm6_2(DataType dt) {
317 switch (dt.GetValue()) {
318 case S16:
319 type_ = 0x1;
320 SetEncodingValue(0x1);
321 break;
322 case S32:
323 type_ = 0x1;
324 SetEncodingValue(0x2);
325 break;
326 case S64:
327 type_ = 0x1;
328 SetEncodingValue(0x4);
329 break;
330 default:
331 VIXL_UNREACHABLE();
332 type_ = 0x0;
333 break;
334 }
335}
336
337class Dt_imm6_3 : public EncodingValue {
338 public:
339 explicit Dt_imm6_3(DataType dt);
340};
341
342Dt_imm6_3::Dt_imm6_3(DataType dt) {
343 switch (dt.GetValue()) {
344 case I16:
345 SetEncodingValue(0x1);
346 break;
347 case I32:
348 SetEncodingValue(0x2);
349 break;
350 case I64:
351 SetEncodingValue(0x4);
352 break;
353 default:
354 break;
355 }
356}
357
358class Dt_imm6_4 : public EncodingValue {
359 uint32_t type_;
360
361 public:
362 explicit Dt_imm6_4(DataType dt);
363 uint32_t GetTypeEncodingValue() const { return type_; }
364};
365
366Dt_imm6_4::Dt_imm6_4(DataType dt) {
367 switch (dt.GetValue()) {
368 case S8:
369 type_ = 0x0;
370 SetEncodingValue(0x1);
371 break;
372 case U8:
373 type_ = 0x1;
374 SetEncodingValue(0x1);
375 break;
376 case S16:
377 type_ = 0x0;
378 SetEncodingValue(0x2);
379 break;
380 case U16:
381 type_ = 0x1;
382 SetEncodingValue(0x2);
383 break;
384 case S32:
385 type_ = 0x0;
386 SetEncodingValue(0x4);
387 break;
388 case U32:
389 type_ = 0x1;
390 SetEncodingValue(0x4);
391 break;
392 default:
393 VIXL_UNREACHABLE();
394 type_ = 0x0;
395 break;
396 }
397}
398
399class Dt_op_U_size_1 : public EncodingValue {
400 public:
401 explicit Dt_op_U_size_1(DataType dt);
402};
403
404Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
405 switch (dt.GetValue()) {
406 case S8:
407 SetEncodingValue(0x0);
408 break;
409 case S16:
410 SetEncodingValue(0x1);
411 break;
412 case S32:
413 SetEncodingValue(0x2);
414 break;
415 case U8:
416 SetEncodingValue(0x4);
417 break;
418 case U16:
419 SetEncodingValue(0x5);
420 break;
421 case U32:
422 SetEncodingValue(0x6);
423 break;
424 case P8:
425 SetEncodingValue(0x8);
426 break;
427 case P64:
428 SetEncodingValue(0xa);
429 break;
430 default:
431 break;
432 }
433}
434
435class Dt_op_size_1 : public EncodingValue {
436 public:
437 explicit Dt_op_size_1(DataType dt);
438};
439
440Dt_op_size_1::Dt_op_size_1(DataType dt) {
441 switch (dt.GetValue()) {
442 case I8:
443 SetEncodingValue(0x0);
444 break;
445 case I16:
446 SetEncodingValue(0x1);
447 break;
448 case I32:
449 SetEncodingValue(0x2);
450 break;
451 case P8:
452 SetEncodingValue(0x4);
453 break;
454 default:
455 break;
456 }
457}
458
459class Dt_op_size_2 : public EncodingValue {
460 public:
461 explicit Dt_op_size_2(DataType dt);
462};
463
464Dt_op_size_2::Dt_op_size_2(DataType dt) {
465 switch (dt.GetValue()) {
466 case S8:
467 SetEncodingValue(0x0);
468 break;
469 case S16:
470 SetEncodingValue(0x1);
471 break;
472 case S32:
473 SetEncodingValue(0x2);
474 break;
475 case U8:
476 SetEncodingValue(0x4);
477 break;
478 case U16:
479 SetEncodingValue(0x5);
480 break;
481 case U32:
482 SetEncodingValue(0x6);
483 break;
484 default:
485 break;
486 }
487}
488
489class Dt_op_size_3 : public EncodingValue {
490 public:
491 explicit Dt_op_size_3(DataType dt);
492};
493
494Dt_op_size_3::Dt_op_size_3(DataType dt) {
495 switch (dt.GetValue()) {
496 case S16:
497 SetEncodingValue(0x0);
498 break;
499 case S32:
500 SetEncodingValue(0x1);
501 break;
502 case S64:
503 SetEncodingValue(0x2);
504 break;
505 case U16:
506 SetEncodingValue(0x4);
507 break;
508 case U32:
509 SetEncodingValue(0x5);
510 break;
511 case U64:
512 SetEncodingValue(0x6);
513 break;
514 default:
515 break;
516 }
517}
518
519class Dt_U_imm3H_1 : public EncodingValue {
520 public:
521 explicit Dt_U_imm3H_1(DataType dt);
522};
523
524Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
525 switch (dt.GetValue()) {
526 case S8:
527 SetEncodingValue(0x1);
528 break;
529 case S16:
530 SetEncodingValue(0x2);
531 break;
532 case S32:
533 SetEncodingValue(0x4);
534 break;
535 case U8:
536 SetEncodingValue(0x9);
537 break;
538 case U16:
539 SetEncodingValue(0xa);
540 break;
541 case U32:
542 SetEncodingValue(0xc);
543 break;
544 default:
545 break;
546 }
547}
548
549class Dt_U_opc1_opc2_1 : public EncodingValue {
550 public:
551 explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
552};
553
554Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
555 switch (dt.GetValue()) {
556 case S8:
557 if ((lane.GetLane() & 7) != lane.GetLane()) {
558 return;
559 }
560 SetEncodingValue(0x8 | lane.GetLane());
561 break;
562 case S16:
563 if ((lane.GetLane() & 3) != lane.GetLane()) {
564 return;
565 }
566 SetEncodingValue(0x1 | (lane.GetLane() << 1));
567 break;
568 case U8:
569 if ((lane.GetLane() & 7) != lane.GetLane()) {
570 return;
571 }
572 SetEncodingValue(0x18 | lane.GetLane());
573 break;
574 case U16:
575 if ((lane.GetLane() & 3) != lane.GetLane()) {
576 return;
577 }
578 SetEncodingValue(0x11 | (lane.GetLane() << 1));
579 break;
580 case Untyped32:
581 if ((lane.GetLane() & 1) != lane.GetLane()) {
582 return;
583 }
584 SetEncodingValue(0x0 | (lane.GetLane() << 2));
585 break;
586 case kDataTypeValueNone:
587 if ((lane.GetLane() & 1) != lane.GetLane()) {
588 return;
589 }
590 SetEncodingValue(0x0 | (lane.GetLane() << 2));
591 break;
592 default:
593 break;
594 }
595}
596
597class Dt_opc1_opc2_1 : public EncodingValue {
598 public:
599 explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
600};
601
602Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
603 switch (dt.GetValue()) {
604 case Untyped8:
605 if ((lane.GetLane() & 7) != lane.GetLane()) {
606 return;
607 }
608 SetEncodingValue(0x8 | lane.GetLane());
609 break;
610 case Untyped16:
611 if ((lane.GetLane() & 3) != lane.GetLane()) {
612 return;
613 }
614 SetEncodingValue(0x1 | (lane.GetLane() << 1));
615 break;
616 case Untyped32:
617 if ((lane.GetLane() & 1) != lane.GetLane()) {
618 return;
619 }
620 SetEncodingValue(0x0 | (lane.GetLane() << 2));
621 break;
622 case kDataTypeValueNone:
623 if ((lane.GetLane() & 1) != lane.GetLane()) {
624 return;
625 }
626 SetEncodingValue(0x0 | (lane.GetLane() << 2));
627 break;
628 default:
629 break;
630 }
631}
632
633class Dt_imm4_1 : public EncodingValue {
634 public:
635 explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
636};
637
638Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
639 switch (dt.GetValue()) {
640 case Untyped8:
641 if ((lane.GetLane() & 7) != lane.GetLane()) {
642 return;
643 }
644 SetEncodingValue(0x1 | (lane.GetLane() << 1));
645 break;
646 case Untyped16:
647 if ((lane.GetLane() & 3) != lane.GetLane()) {
648 return;
649 }
650 SetEncodingValue(0x2 | (lane.GetLane() << 2));
651 break;
652 case Untyped32:
653 if ((lane.GetLane() & 1) != lane.GetLane()) {
654 return;
655 }
656 SetEncodingValue(0x4 | (lane.GetLane() << 3));
657 break;
658 default:
659 break;
660 }
661}
662
663class Dt_B_E_1 : public EncodingValue {
664 public:
665 explicit Dt_B_E_1(DataType dt);
666};
667
668Dt_B_E_1::Dt_B_E_1(DataType dt) {
669 switch (dt.GetValue()) {
670 case Untyped8:
671 SetEncodingValue(0x2);
672 break;
673 case Untyped16:
674 SetEncodingValue(0x1);
675 break;
676 case Untyped32:
677 SetEncodingValue(0x0);
678 break;
679 default:
680 break;
681 }
682}
683
684class Dt_op_1 : public EncodingValue {
685 public:
686 Dt_op_1(DataType dt1, DataType dt2);
687};
688
689Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
690 if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
691 SetEncodingValue(0x0);
692 return;
693 }
694 if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
695 SetEncodingValue(0x1);
696 return;
697 }
698 if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
699 SetEncodingValue(0x2);
700 return;
701 }
702 if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
703 SetEncodingValue(0x3);
704 return;
705 }
706}
707
708class Dt_op_2 : public EncodingValue {
709 public:
710 explicit Dt_op_2(DataType dt);
711};
712
713Dt_op_2::Dt_op_2(DataType dt) {
714 switch (dt.GetValue()) {
715 case U32:
716 SetEncodingValue(0x0);
717 break;
718 case S32:
719 SetEncodingValue(0x1);
720 break;
721 default:
722 break;
723 }
724}
725
726class Dt_op_3 : public EncodingValue {
727 public:
728 explicit Dt_op_3(DataType dt);
729};
730
731Dt_op_3::Dt_op_3(DataType dt) {
732 switch (dt.GetValue()) {
733 case S32:
734 SetEncodingValue(0x0);
735 break;
736 case U32:
737 SetEncodingValue(0x1);
738 break;
739 default:
740 break;
741 }
742}
743
744class Dt_U_sx_1 : public EncodingValue {
745 public:
746 explicit Dt_U_sx_1(DataType dt);
747};
748
749Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
750 switch (dt.GetValue()) {
751 case S16:
752 SetEncodingValue(0x0);
753 break;
754 case S32:
755 SetEncodingValue(0x1);
756 break;
757 case U16:
758 SetEncodingValue(0x2);
759 break;
760 case U32:
761 SetEncodingValue(0x3);
762 break;
763 default:
764 break;
765 }
766}
767
768class Dt_op_U_1 : public EncodingValue {
769 public:
770 Dt_op_U_1(DataType dt1, DataType dt2);
771};
772
773Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
774 if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
775 SetEncodingValue(0x0);
776 return;
777 }
778 if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
779 SetEncodingValue(0x1);
780 return;
781 }
782 if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
783 SetEncodingValue(0x2);
784 return;
785 }
786 if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
787 SetEncodingValue(0x3);
788 return;
789 }
790}
791
792class Dt_sz_1 : public EncodingValue {
793 public:
794 explicit Dt_sz_1(DataType dt);
795};
796
797Dt_sz_1::Dt_sz_1(DataType dt) {
798 switch (dt.GetValue()) {
799 case F32:
800 SetEncodingValue(0x0);
801 break;
802 default:
803 break;
804 }
805}
806
807class Dt_F_size_1 : public EncodingValue {
808 public:
809 explicit Dt_F_size_1(DataType dt);
810};
811
812Dt_F_size_1::Dt_F_size_1(DataType dt) {
813 switch (dt.GetValue()) {
814 case S8:
815 SetEncodingValue(0x0);
816 break;
817 case S16:
818 SetEncodingValue(0x1);
819 break;
820 case S32:
821 SetEncodingValue(0x2);
822 break;
823 case F32:
824 SetEncodingValue(0x6);
825 break;
826 default:
827 break;
828 }
829}
830
831class Dt_F_size_2 : public EncodingValue {
832 public:
833 explicit Dt_F_size_2(DataType dt);
834};
835
836Dt_F_size_2::Dt_F_size_2(DataType dt) {
837 switch (dt.GetValue()) {
838 case I8:
839 SetEncodingValue(0x0);
840 break;
841 case I16:
842 SetEncodingValue(0x1);
843 break;
844 case I32:
845 SetEncodingValue(0x2);
846 break;
847 case F32:
848 SetEncodingValue(0x6);
849 break;
850 default:
851 break;
852 }
853}
854
855class Dt_F_size_3 : public EncodingValue {
856 public:
857 explicit Dt_F_size_3(DataType dt);
858};
859
860Dt_F_size_3::Dt_F_size_3(DataType dt) {
861 switch (dt.GetValue()) {
862 case I16:
863 SetEncodingValue(0x1);
864 break;
865 case I32:
866 SetEncodingValue(0x2);
867 break;
868 case F32:
869 SetEncodingValue(0x6);
870 break;
871 default:
872 break;
873 }
874}
875
876class Dt_F_size_4 : public EncodingValue {
877 public:
878 explicit Dt_F_size_4(DataType dt);
879};
880
881Dt_F_size_4::Dt_F_size_4(DataType dt) {
882 switch (dt.GetValue()) {
883 case U32:
884 SetEncodingValue(0x2);
885 break;
886 case F32:
887 SetEncodingValue(0x6);
888 break;
889 default:
890 break;
891 }
892}
893
894class Dt_U_size_1 : public EncodingValue {
895 public:
896 explicit Dt_U_size_1(DataType dt);
897};
898
899Dt_U_size_1::Dt_U_size_1(DataType dt) {
900 switch (dt.GetValue()) {
901 case S8:
902 SetEncodingValue(0x0);
903 break;
904 case S16:
905 SetEncodingValue(0x1);
906 break;
907 case S32:
908 SetEncodingValue(0x2);
909 break;
910 case U8:
911 SetEncodingValue(0x4);
912 break;
913 case U16:
914 SetEncodingValue(0x5);
915 break;
916 case U32:
917 SetEncodingValue(0x6);
918 break;
919 default:
920 break;
921 }
922}
923
924class Dt_U_size_2 : public EncodingValue {
925 public:
926 explicit Dt_U_size_2(DataType dt);
927};
928
929Dt_U_size_2::Dt_U_size_2(DataType dt) {
930 switch (dt.GetValue()) {
931 case S16:
932 SetEncodingValue(0x1);
933 break;
934 case S32:
935 SetEncodingValue(0x2);
936 break;
937 case U16:
938 SetEncodingValue(0x5);
939 break;
940 case U32:
941 SetEncodingValue(0x6);
942 break;
943 default:
944 break;
945 }
946}
947
948class Dt_U_size_3 : public EncodingValue {
949 public:
950 explicit Dt_U_size_3(DataType dt);
951};
952
953Dt_U_size_3::Dt_U_size_3(DataType dt) {
954 switch (dt.GetValue()) {
955 case S8:
956 SetEncodingValue(0x0);
957 break;
958 case S16:
959 SetEncodingValue(0x1);
960 break;
961 case S32:
962 SetEncodingValue(0x2);
963 break;
964 case S64:
965 SetEncodingValue(0x3);
966 break;
967 case U8:
968 SetEncodingValue(0x4);
969 break;
970 case U16:
971 SetEncodingValue(0x5);
972 break;
973 case U32:
974 SetEncodingValue(0x6);
975 break;
976 case U64:
977 SetEncodingValue(0x7);
978 break;
979 default:
980 break;
981 }
982}
983
984class Dt_size_1 : public EncodingValue {
985 public:
986 explicit Dt_size_1(DataType dt);
987};
988
989Dt_size_1::Dt_size_1(DataType dt) {
990 switch (dt.GetValue()) {
991 case Untyped8:
992 SetEncodingValue(0x0);
993 break;
994 default:
995 break;
996 }
997}
998
999class Dt_size_2 : public EncodingValue {
1000 public:
1001 explicit Dt_size_2(DataType dt);
1002};
1003
1004Dt_size_2::Dt_size_2(DataType dt) {
1005 switch (dt.GetValue()) {
1006 case I8:
1007 SetEncodingValue(0x0);
1008 break;
1009 case I16:
1010 SetEncodingValue(0x1);
1011 break;
1012 case I32:
1013 SetEncodingValue(0x2);
1014 break;
1015 case I64:
1016 SetEncodingValue(0x3);
1017 break;
1018 default:
1019 break;
1020 }
1021}
1022
1023class Dt_size_3 : public EncodingValue {
1024 public:
1025 explicit Dt_size_3(DataType dt);
1026};
1027
1028Dt_size_3::Dt_size_3(DataType dt) {
1029 switch (dt.GetValue()) {
1030 case I16:
1031 SetEncodingValue(0x0);
1032 break;
1033 case I32:
1034 SetEncodingValue(0x1);
1035 break;
1036 case I64:
1037 SetEncodingValue(0x2);
1038 break;
1039 default:
1040 break;
1041 }
1042}
1043
1044class Dt_size_4 : public EncodingValue {
1045 public:
1046 explicit Dt_size_4(DataType dt);
1047};
1048
1049Dt_size_4::Dt_size_4(DataType dt) {
1050 switch (dt.GetValue()) {
1051 case I8:
1052 SetEncodingValue(0x0);
1053 break;
1054 case I16:
1055 SetEncodingValue(0x1);
1056 break;
1057 case I32:
1058 SetEncodingValue(0x2);
1059 break;
1060 default:
1061 break;
1062 }
1063}
1064
1065class Dt_size_5 : public EncodingValue {
1066 public:
1067 explicit Dt_size_5(DataType dt);
1068};
1069
1070Dt_size_5::Dt_size_5(DataType dt) {
1071 switch (dt.GetValue()) {
1072 case S8:
1073 SetEncodingValue(0x0);
1074 break;
1075 case S16:
1076 SetEncodingValue(0x1);
1077 break;
1078 case S32:
1079 SetEncodingValue(0x2);
1080 break;
1081 default:
1082 break;
1083 }
1084}
1085
1086class Dt_size_6 : public EncodingValue {
1087 public:
1088 explicit Dt_size_6(DataType dt);
1089};
1090
1091Dt_size_6::Dt_size_6(DataType dt) {
1092 switch (dt.GetValue()) {
1093 case Untyped8:
1094 SetEncodingValue(0x0);
1095 break;
1096 case Untyped16:
1097 SetEncodingValue(0x1);
1098 break;
1099 case Untyped32:
1100 SetEncodingValue(0x2);
1101 break;
1102 case Untyped64:
1103 SetEncodingValue(0x3);
1104 break;
1105 default:
1106 break;
1107 }
1108}
1109
1110class Dt_size_7 : public EncodingValue {
1111 public:
1112 explicit Dt_size_7(DataType dt);
1113};
1114
1115Dt_size_7::Dt_size_7(DataType dt) {
1116 switch (dt.GetValue()) {
1117 case Untyped8:
1118 SetEncodingValue(0x0);
1119 break;
1120 case Untyped16:
1121 SetEncodingValue(0x1);
1122 break;
1123 case Untyped32:
1124 SetEncodingValue(0x2);
1125 break;
1126 default:
1127 break;
1128 }
1129}
1130
1131class Dt_size_8 : public EncodingValue {
1132 public:
1133 Dt_size_8(DataType dt, Alignment align);
1134};
1135
1136Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
1137 switch (dt.GetValue()) {
1138 case Untyped8:
1139 SetEncodingValue(0x0);
1140 break;
1141 case Untyped16:
1142 SetEncodingValue(0x1);
1143 break;
1144 case Untyped32:
1145 if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
1146 SetEncodingValue(0x2);
1147 } else if (align.Is(k128BitAlign)) {
1148 SetEncodingValue(0x3);
1149 }
1150 break;
1151 default:
1152 break;
1153 }
1154}
1155
1156class Dt_size_9 : public EncodingValue {
1157 uint32_t type_;
1158
1159 public:
1160 explicit Dt_size_9(DataType dt);
1161 uint32_t GetTypeEncodingValue() const { return type_; }
1162};
1163
1164Dt_size_9::Dt_size_9(DataType dt) {
1165 switch (dt.GetValue()) {
1166 case I16:
1167 type_ = 0x0;
1168 SetEncodingValue(0x1);
1169 break;
1170 case I32:
1171 type_ = 0x0;
1172 SetEncodingValue(0x2);
1173 break;
1174 case F32:
1175 type_ = 0x1;
1176 SetEncodingValue(0x2);
1177 break;
1178 default:
1179 VIXL_UNREACHABLE();
1180 type_ = 0x0;
1181 break;
1182 }
1183}
1184
1185class Dt_size_10 : public EncodingValue {
1186 public:
1187 explicit Dt_size_10(DataType dt);
1188};
1189
1190Dt_size_10::Dt_size_10(DataType dt) {
1191 switch (dt.GetValue()) {
1192 case S8:
1193 case U8:
1194 case I8:
1195 SetEncodingValue(0x0);
1196 break;
1197 case S16:
1198 case U16:
1199 case I16:
1200 SetEncodingValue(0x1);
1201 break;
1202 case S32:
1203 case U32:
1204 case I32:
1205 SetEncodingValue(0x2);
1206 break;
1207 default:
1208 break;
1209 }
1210}
1211
1212class Dt_size_11 : public EncodingValue {
1213 uint32_t type_;
1214
1215 public:
1216 explicit Dt_size_11(DataType dt);
1217 uint32_t GetTypeEncodingValue() const { return type_; }
1218};
1219
1220Dt_size_11::Dt_size_11(DataType dt) {
1221 switch (dt.GetValue()) {
1222 case S16:
1223 type_ = 0x0;
1224 SetEncodingValue(0x1);
1225 break;
1226 case U16:
1227 type_ = 0x1;
1228 SetEncodingValue(0x1);
1229 break;
1230 case S32:
1231 type_ = 0x0;
1232 SetEncodingValue(0x2);
1233 break;
1234 case U32:
1235 type_ = 0x1;
1236 SetEncodingValue(0x2);
1237 break;
1238 default:
1239 VIXL_UNREACHABLE();
1240 type_ = 0x0;
1241 break;
1242 }
1243}
1244
1245class Dt_size_12 : public EncodingValue {
1246 uint32_t type_;
1247
1248 public:
1249 explicit Dt_size_12(DataType dt);
1250 uint32_t GetTypeEncodingValue() const { return type_; }
1251};
1252
1253Dt_size_12::Dt_size_12(DataType dt) {
1254 switch (dt.GetValue()) {
1255 case S8:
1256 type_ = 0x0;
1257 SetEncodingValue(0x0);
1258 break;
1259 case U8:
1260 type_ = 0x1;
1261 SetEncodingValue(0x0);
1262 break;
1263 case S16:
1264 type_ = 0x0;
1265 SetEncodingValue(0x1);
1266 break;
1267 case U16:
1268 type_ = 0x1;
1269 SetEncodingValue(0x1);
1270 break;
1271 case S32:
1272 type_ = 0x0;
1273 SetEncodingValue(0x2);
1274 break;
1275 case U32:
1276 type_ = 0x1;
1277 SetEncodingValue(0x2);
1278 break;
1279 default:
1280 VIXL_UNREACHABLE();
1281 type_ = 0x0;
1282 break;
1283 }
1284}
1285
1286class Dt_size_13 : public EncodingValue {
1287 public:
1288 explicit Dt_size_13(DataType dt);
1289};
1290
1291Dt_size_13::Dt_size_13(DataType dt) {
1292 switch (dt.GetValue()) {
1293 case S16:
1294 SetEncodingValue(0x1);
1295 break;
1296 case S32:
1297 SetEncodingValue(0x2);
1298 break;
1299 default:
1300 break;
1301 }
1302}
1303
1304class Dt_size_14 : public EncodingValue {
1305 public:
1306 explicit Dt_size_14(DataType dt);
1307};
1308
1309Dt_size_14::Dt_size_14(DataType dt) {
1310 switch (dt.GetValue()) {
1311 case S16:
1312 SetEncodingValue(0x0);
1313 break;
1314 case S32:
1315 SetEncodingValue(0x1);
1316 break;
1317 case S64:
1318 SetEncodingValue(0x2);
1319 break;
1320 default:
1321 break;
1322 }
1323}
1324
1325class Dt_size_15 : public EncodingValue {
1326 public:
1327 explicit Dt_size_15(DataType dt);
1328};
1329
1330Dt_size_15::Dt_size_15(DataType dt) {
1331 switch (dt.GetValue()) {
1332 case Untyped8:
1333 SetEncodingValue(0x0);
1334 break;
1335 case Untyped16:
1336 SetEncodingValue(0x1);
1337 break;
1338 default:
1339 break;
1340 }
1341}
1342
1343class Dt_size_16 : public EncodingValue {
1344 public:
1345 explicit Dt_size_16(DataType dt);
1346};
1347
1348Dt_size_16::Dt_size_16(DataType dt) {
1349 switch (dt.GetValue()) {
1350 case I8:
1351 SetEncodingValue(0x0);
1352 break;
1353 case I16:
1354 SetEncodingValue(0x1);
1355 break;
1356 case I32:
1357 SetEncodingValue(0x2);
1358 break;
1359 default:
1360 break;
1361 }
1362}
1363
1364class Index_1 : public EncodingValue {
1365 public:
1366 Index_1(const NeonRegisterList& nreglist, DataType dt);
1367};
1368
1369Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1370 switch (dt.GetValue()) {
1371 case Untyped8: {
1372 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1373 return;
1374 }
1375 uint32_t value = nreglist.GetTransferLane() << 1;
1376 if (!nreglist.IsSingleSpaced()) return;
1377 SetEncodingValue(value);
1378 break;
1379 }
1380 case Untyped16: {
1381 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1382 return;
1383 }
1384 uint32_t value = nreglist.GetTransferLane() << 2;
1385 if (nreglist.IsDoubleSpaced()) value |= 2;
1386 SetEncodingValue(value);
1387 break;
1388 }
1389 case Untyped32: {
1390 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1391 return;
1392 }
1393 uint32_t value = nreglist.GetTransferLane() << 3;
1394 if (nreglist.IsDoubleSpaced()) value |= 4;
1395 SetEncodingValue(value);
1396 break;
1397 }
1398 default:
1399 break;
1400 }
1401}
1402
1403class Align_index_align_1 : public EncodingValue {
1404 public:
1405 Align_index_align_1(Alignment align,
1406 const NeonRegisterList& nreglist,
1407 DataType dt);
1408};
1409
1410Align_index_align_1::Align_index_align_1(Alignment align,
1411 const NeonRegisterList& nreglist,
1412 DataType dt) {
1413 switch (dt.GetValue()) {
1414 case Untyped8: {
1415 uint32_t value;
1416 if (align.GetType() == kNoAlignment) {
1417 value = 0;
1418 } else {
1419 return;
1420 }
1421 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1422 return;
1423 }
1424 value |= nreglist.GetTransferLane() << 1;
1425 SetEncodingValue(value);
1426 break;
1427 }
1428 case Untyped16: {
1429 uint32_t value;
1430 if (align.GetType() == k16BitAlign) {
1431 value = 1;
1432 } else if (align.GetType() == kNoAlignment) {
1433 value = 0;
1434 } else {
1435 return;
1436 }
1437 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1438 return;
1439 }
1440 value |= nreglist.GetTransferLane() << 2;
1441 SetEncodingValue(value);
1442 break;
1443 }
1444 case Untyped32: {
1445 uint32_t value;
1446 if (align.GetType() == k32BitAlign) {
1447 value = 3;
1448 } else if (align.GetType() == kNoAlignment) {
1449 value = 0;
1450 } else {
1451 return;
1452 }
1453 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1454 return;
1455 }
1456 value |= nreglist.GetTransferLane() << 3;
1457 SetEncodingValue(value);
1458 break;
1459 }
1460 default:
1461 break;
1462 }
1463}
1464
1465class Align_index_align_2 : public EncodingValue {
1466 public:
1467 Align_index_align_2(Alignment align,
1468 const NeonRegisterList& nreglist,
1469 DataType dt);
1470};
1471
1472Align_index_align_2::Align_index_align_2(Alignment align,
1473 const NeonRegisterList& nreglist,
1474 DataType dt) {
1475 switch (dt.GetValue()) {
1476 case Untyped8: {
1477 uint32_t value;
1478 if (align.GetType() == k16BitAlign) {
1479 value = 1;
1480 } else if (align.GetType() == kNoAlignment) {
1481 value = 0;
1482 } else {
1483 return;
1484 }
1485 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1486 return;
1487 }
1488 value |= nreglist.GetTransferLane() << 1;
1489 if (!nreglist.IsSingleSpaced()) return;
1490 SetEncodingValue(value);
1491 break;
1492 }
1493 case Untyped16: {
1494 uint32_t value;
1495 if (align.GetType() == k32BitAlign) {
1496 value = 1;
1497 } else if (align.GetType() == kNoAlignment) {
1498 value = 0;
1499 } else {
1500 return;
1501 }
1502 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1503 return;
1504 }
1505 value |= nreglist.GetTransferLane() << 2;
1506 if (nreglist.IsDoubleSpaced()) value |= 2;
1507 SetEncodingValue(value);
1508 break;
1509 }
1510 case Untyped32: {
1511 uint32_t value;
1512 if (align.GetType() == k64BitAlign) {
1513 value = 1;
1514 } else if (align.GetType() == kNoAlignment) {
1515 value = 0;
1516 } else {
1517 return;
1518 }
1519 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1520 return;
1521 }
1522 value |= nreglist.GetTransferLane() << 3;
1523 if (nreglist.IsDoubleSpaced()) value |= 4;
1524 SetEncodingValue(value);
1525 break;
1526 }
1527 default:
1528 break;
1529 }
1530}
1531
1532class Align_index_align_3 : public EncodingValue {
1533 public:
1534 Align_index_align_3(Alignment align,
1535 const NeonRegisterList& nreglist,
1536 DataType dt);
1537};
1538
1539Align_index_align_3::Align_index_align_3(Alignment align,
1540 const NeonRegisterList& nreglist,
1541 DataType dt) {
1542 switch (dt.GetValue()) {
1543 case Untyped8: {
1544 uint32_t value;
1545 if (align.GetType() == k32BitAlign) {
1546 value = 1;
1547 } else if (align.GetType() == kNoAlignment) {
1548 value = 0;
1549 } else {
1550 return;
1551 }
1552 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1553 return;
1554 }
1555 value |= nreglist.GetTransferLane() << 1;
1556 if (!nreglist.IsSingleSpaced()) return;
1557 SetEncodingValue(value);
1558 break;
1559 }
1560 case Untyped16: {
1561 uint32_t value;
1562 if (align.GetType() == k64BitAlign) {
1563 value = 1;
1564 } else if (align.GetType() == kNoAlignment) {
1565 value = 0;
1566 } else {
1567 return;
1568 }
1569 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1570 return;
1571 }
1572 value |= nreglist.GetTransferLane() << 2;
1573 if (nreglist.IsDoubleSpaced()) value |= 2;
1574 SetEncodingValue(value);
1575 break;
1576 }
1577 case Untyped32: {
1578 uint32_t value;
1579 if (align.GetType() == k64BitAlign) {
1580 value = 1;
1581 } else if (align.GetType() == k128BitAlign) {
1582 value = 2;
1583 } else if (align.GetType() == kNoAlignment) {
1584 value = 0;
1585 } else {
1586 return;
1587 }
1588 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1589 return;
1590 }
1591 value |= nreglist.GetTransferLane() << 3;
1592 if (nreglist.IsDoubleSpaced()) value |= 4;
1593 SetEncodingValue(value);
1594 break;
1595 }
1596 default:
1597 break;
1598 }
1599}
1600
1601class Align_a_1 : public EncodingValue {
1602 public:
1603 Align_a_1(Alignment align, DataType dt);
1604};
1605
1606Align_a_1::Align_a_1(Alignment align, DataType dt) {
1607 switch (align.GetType()) {
1608 case k16BitAlign:
1609 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1610 break;
1611 case k32BitAlign:
1612 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1613 break;
1614 case kNoAlignment:
1615 SetEncodingValue(0x0);
1616 break;
1617 default:
1618 break;
1619 }
1620}
1621
1622class Align_a_2 : public EncodingValue {
1623 public:
1624 Align_a_2(Alignment align, DataType dt);
1625};
1626
1627Align_a_2::Align_a_2(Alignment align, DataType dt) {
1628 switch (align.GetType()) {
1629 case k16BitAlign:
1630 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1631 break;
1632 case k32BitAlign:
1633 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1634 break;
1635 case k64BitAlign:
1636 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1637 break;
1638 case kNoAlignment:
1639 SetEncodingValue(0x0);
1640 break;
1641 default:
1642 break;
1643 }
1644}
1645
1646class Align_a_3 : public EncodingValue {
1647 public:
1648 Align_a_3(Alignment align, DataType dt);
1649};
1650
1651Align_a_3::Align_a_3(Alignment align, DataType dt) {
1652 switch (align.GetType()) {
1653 case k32BitAlign:
1654 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1655 break;
1656 case k64BitAlign:
1657 if (dt.Is(Untyped16))
1658 SetEncodingValue(0x1);
1659 else if (dt.Is(Untyped32))
1660 SetEncodingValue(0x1);
1661 break;
1662 case k128BitAlign:
1663 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1664 break;
1665 case kNoAlignment:
1666 SetEncodingValue(0x0);
1667 break;
1668 default:
1669 break;
1670 }
1671}
1672
1673class Align_align_1 : public EncodingValue {
1674 public:
1675 Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1676};
1677
1678Align_align_1::Align_align_1(Alignment align,
1679 const NeonRegisterList& nreglist) {
1680 switch (align.GetType()) {
1681 case k64BitAlign:
1682 SetEncodingValue(0x1);
1683 break;
1684 case k128BitAlign:
1685 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1686 SetEncodingValue(0x2);
1687 break;
1688 case k256BitAlign:
1689 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1690 SetEncodingValue(0x3);
1691 break;
1692 case kNoAlignment:
1693 SetEncodingValue(0x0);
1694 break;
1695 default:
1696 break;
1697 }
1698}
1699
1700class Align_align_2 : public EncodingValue {
1701 public:
1702 Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1703};
1704
1705Align_align_2::Align_align_2(Alignment align,
1706 const NeonRegisterList& nreglist) {
1707 switch (align.GetType()) {
1708 case k64BitAlign:
1709 SetEncodingValue(0x1);
1710 break;
1711 case k128BitAlign:
1712 SetEncodingValue(0x2);
1713 break;
1714 case k256BitAlign:
1715 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1716 break;
1717 case kNoAlignment:
1718 SetEncodingValue(0x0);
1719 break;
1720 default:
1721 break;
1722 }
1723}
1724
1725class Align_align_3 : public EncodingValue {
1726 public:
1727 explicit Align_align_3(Alignment align);
1728};
1729
1730Align_align_3::Align_align_3(Alignment align) {
1731 switch (align.GetType()) {
1732 case k64BitAlign:
1733 SetEncodingValue(0x1);
1734 break;
1735 case kNoAlignment:
1736 SetEncodingValue(0x0);
1737 break;
1738 default:
1739 break;
1740 }
1741}
1742
1743class Align_align_4 : public EncodingValue {
1744 public:
1745 explicit Align_align_4(Alignment align);
1746};
1747
1748Align_align_4::Align_align_4(Alignment align) {
1749 switch (align.GetType()) {
1750 case k64BitAlign:
1751 SetEncodingValue(0x1);
1752 break;
1753 case k128BitAlign:
1754 SetEncodingValue(0x2);
1755 break;
1756 case k256BitAlign:
1757 SetEncodingValue(0x3);
1758 break;
1759 case kNoAlignment:
1760 SetEncodingValue(0x0);
1761 break;
1762 default:
1763 break;
1764 }
1765}
1766
1767class Align_align_5 : public EncodingValue {
1768 public:
1769 Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1770};
1771
1772Align_align_5::Align_align_5(Alignment align,
1773 const NeonRegisterList& nreglist) {
1774 switch (align.GetType()) {
1775 case k64BitAlign:
1776 SetEncodingValue(0x1);
1777 break;
1778 case k128BitAlign:
1779 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1780 SetEncodingValue(0x2);
1781 break;
1782 case k256BitAlign:
1783 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1784 break;
1785 case kNoAlignment:
1786 SetEncodingValue(0x0);
1787 break;
1788 default:
1789 break;
1790 }
1791}
1792
1793
1794void Assembler::adc(Condition cond,
1795 EncodingSize size,
1796 Register rd,
1797 Register rn,
1798 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07001799 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01001800 CheckIT(cond);
1801 if (operand.IsImmediate()) {
1802 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001803 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001804 ImmediateT32 immediate_t32(imm);
1805 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1806 if (!size.IsNarrow() && immediate_t32.IsValid()) {
1807 EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1808 (immediate_t32.GetEncodingValue() & 0xff) |
1809 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1810 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1811 AdvanceIT();
1812 return;
1813 }
1814 } else {
1815 ImmediateA32 immediate_a32(imm);
1816 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1817 if (immediate_a32.IsValid() && cond.IsNotNever()) {
1818 EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1819 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1820 immediate_a32.GetEncodingValue());
1821 return;
1822 }
1823 }
1824 }
1825 if (operand.IsImmediateShiftedRegister()) {
1826 Register rm = operand.GetBaseRegister();
1827 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001828 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001829 // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1830 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1831 rm.IsLow()) {
1832 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1833 AdvanceIT();
1834 return;
1835 }
1836 }
1837 }
1838 Shift shift = operand.GetShift();
1839 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001840 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001841 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1842 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
1843 uint32_t amount_ = amount % 32;
1844 EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1845 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1846 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1847 AdvanceIT();
1848 return;
1849 }
1850 } else {
1851 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1852 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1853 uint32_t amount_ = amount % 32;
1854 EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1855 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1856 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1857 return;
1858 }
1859 }
1860 }
1861 if (operand.IsRegisterShiftedRegister()) {
1862 Register rm = operand.GetBaseRegister();
1863 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001864 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001865 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1866 if (cond.IsNotNever()) {
1867 EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
1868 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1869 (shift.GetType() << 5) |
1870 (operand.GetShiftRegister().GetCode() << 8));
1871 return;
1872 }
1873 }
1874 }
1875 Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
1876}
1877
1878void Assembler::adcs(Condition cond,
1879 EncodingSize size,
1880 Register rd,
1881 Register rn,
1882 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07001883 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01001884 CheckIT(cond);
1885 if (operand.IsImmediate()) {
1886 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001887 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001888 ImmediateT32 immediate_t32(imm);
1889 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
1890 if (!size.IsNarrow() && immediate_t32.IsValid()) {
1891 EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1892 (immediate_t32.GetEncodingValue() & 0xff) |
1893 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1894 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1895 AdvanceIT();
1896 return;
1897 }
1898 } else {
1899 ImmediateA32 immediate_a32(imm);
1900 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1901 if (immediate_a32.IsValid() && cond.IsNotNever()) {
1902 EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
1903 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1904 immediate_a32.GetEncodingValue());
1905 return;
1906 }
1907 }
1908 }
1909 if (operand.IsImmediateShiftedRegister()) {
1910 Register rm = operand.GetBaseRegister();
1911 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001912 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001913 // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1914 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1915 rm.IsLow()) {
1916 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1917 AdvanceIT();
1918 return;
1919 }
1920 }
1921 }
1922 Shift shift = operand.GetShift();
1923 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001924 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001925 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
1926 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
1927 uint32_t amount_ = amount % 32;
1928 EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1929 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1930 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1931 AdvanceIT();
1932 return;
1933 }
1934 } else {
1935 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1936 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1937 uint32_t amount_ = amount % 32;
1938 EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
1939 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1940 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1941 return;
1942 }
1943 }
1944 }
1945 if (operand.IsRegisterShiftedRegister()) {
1946 Register rm = operand.GetBaseRegister();
1947 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001948 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001949 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
1950 if (cond.IsNotNever()) {
1951 EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
1952 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1953 (shift.GetType() << 5) |
1954 (operand.GetShiftRegister().GetCode() << 8));
1955 return;
1956 }
1957 }
1958 }
1959 Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
1960}
1961
1962void Assembler::add(Condition cond,
1963 EncodingSize size,
1964 Register rd,
1965 Register rn,
1966 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07001967 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01001968 CheckIT(cond);
1969 if (operand.IsImmediate()) {
1970 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001971 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001972 ImmediateT32 immediate_t32(imm);
1973 // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
1974 if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
1975 ((imm % 4) == 0)) {
1976 uint32_t imm_ = imm >> 2;
1977 EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
1978 AdvanceIT();
1979 return;
1980 }
1981 // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
1982 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
1983 (imm <= 7)) {
1984 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
1985 AdvanceIT();
1986 return;
1987 }
1988 // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
1989 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1990 (imm <= 255)) {
1991 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
1992 AdvanceIT();
1993 return;
1994 }
1995 // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
1996 if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
1997 ((imm % 4) == 0)) {
1998 uint32_t imm_ = imm >> 2;
1999 EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2000 AdvanceIT();
2001 return;
2002 }
2003 // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2004 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2005 ((imm % 4) == 0)) {
2006 uint32_t imm_ = imm >> 2;
2007 EmitT32_16(0xb000 | imm_);
2008 AdvanceIT();
2009 return;
2010 }
2011 // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2012 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) {
2013 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2014 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2015 AdvanceIT();
2016 return;
2017 }
2018 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2019 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp)) {
2020 EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2021 (immediate_t32.GetEncodingValue() & 0xff) |
2022 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2023 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2024 AdvanceIT();
2025 return;
2026 }
2027 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2028 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
2029 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2030 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2031 AdvanceIT();
2032 return;
2033 }
2034 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2035 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid()) {
2036 EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2037 (immediate_t32.GetEncodingValue() & 0xff) |
2038 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2039 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2040 AdvanceIT();
2041 return;
2042 }
2043 // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2044 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095)) {
2045 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2046 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2047 AdvanceIT();
2048 return;
2049 }
2050 } else {
2051 ImmediateA32 immediate_a32(imm);
2052 // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2053 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2054 EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2055 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2056 return;
2057 }
2058 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2059 if (immediate_a32.IsValid() && cond.IsNotNever() &&
2060 ((rn.GetCode() & 0xd) != 0xd)) {
2061 EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2062 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2063 immediate_a32.GetEncodingValue());
2064 return;
2065 }
2066 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2067 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2068 EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2069 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2070 return;
2071 }
2072 }
2073 }
2074 if (operand.IsImmediateShiftedRegister()) {
2075 Register rm = operand.GetBaseRegister();
2076 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002077 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002078 // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2079 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2080 rm.IsLow()) {
2081 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2082 (rm.GetCode() << 6));
2083 AdvanceIT();
2084 return;
2085 }
2086 // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
2087 if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp)) {
2088 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2089 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2090 AdvanceIT();
2091 return;
2092 }
2093 // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
2094 if (!size.IsWide() && rd.Is(rm) && rn.Is(sp)) {
2095 EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2096 ((rd.GetCode() & 0x8) << 4));
2097 AdvanceIT();
2098 return;
2099 }
2100 // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2101 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2102 EmitT32_16(0x4485 | (rm.GetCode() << 3));
2103 AdvanceIT();
2104 return;
2105 }
2106 }
2107 }
2108 Shift shift = operand.GetShift();
2109 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002110 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002111 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2112 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp)) {
2113 uint32_t amount_ = amount % 32;
2114 EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2115 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2116 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2117 AdvanceIT();
2118 return;
2119 }
2120 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2121 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount)) {
2122 uint32_t amount_ = amount % 32;
2123 EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2124 (operand.GetTypeEncodingValue() << 4) |
2125 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2126 AdvanceIT();
2127 return;
2128 }
2129 } else {
2130 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2131 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2132 uint32_t amount_ = amount % 32;
2133 EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2134 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2135 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2136 return;
2137 }
2138 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2139 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2140 uint32_t amount_ = amount % 32;
2141 EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2142 (rd.GetCode() << 12) | rm.GetCode() |
2143 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2144 return;
2145 }
2146 }
2147 }
2148 if (operand.IsRegisterShiftedRegister()) {
2149 Register rm = operand.GetBaseRegister();
2150 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002151 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002152 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2153 if (cond.IsNotNever()) {
2154 EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2155 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2156 (shift.GetType() << 5) |
2157 (operand.GetShiftRegister().GetCode() << 8));
2158 return;
2159 }
2160 }
2161 }
2162 Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2163}
2164
2165void Assembler::add(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002166 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002167 CheckIT(cond);
2168 if (operand.IsImmediate()) {
2169 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002170 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002171 // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2172 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2173 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2174 AdvanceIT();
2175 return;
2176 }
2177 }
2178 }
2179 if (operand.IsPlainRegister()) {
2180 Register rm = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002181 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002182 // ADD<c>{<q>} <Rdn>, <Rm> ; T2
2183 if (InITBlock() && !rm.Is(sp)) {
2184 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2185 (rm.GetCode() << 3));
2186 AdvanceIT();
2187 return;
2188 }
2189 }
2190 }
2191 Delegate(kAdd, &Assembler::add, cond, rd, operand);
2192}
2193
2194void Assembler::adds(Condition cond,
2195 EncodingSize size,
2196 Register rd,
2197 Register rn,
2198 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002199 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002200 CheckIT(cond);
2201 if (operand.IsImmediate()) {
2202 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002203 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002204 ImmediateT32 immediate_t32(imm);
2205 // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2206 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2207 (imm <= 7)) {
2208 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2209 AdvanceIT();
2210 return;
2211 }
2212 // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2213 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2214 (imm <= 255)) {
2215 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2216 AdvanceIT();
2217 return;
2218 }
2219 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2220 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2221 !rd.Is(pc)) {
2222 EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2223 (immediate_t32.GetEncodingValue() & 0xff) |
2224 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2225 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2226 AdvanceIT();
2227 return;
2228 }
2229 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2230 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2231 !rd.Is(pc)) {
2232 EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2233 (immediate_t32.GetEncodingValue() & 0xff) |
2234 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2235 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2236 AdvanceIT();
2237 return;
2238 }
2239 } else {
2240 ImmediateA32 immediate_a32(imm);
2241 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2242 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2243 EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2244 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2245 immediate_a32.GetEncodingValue());
2246 return;
2247 }
2248 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2249 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2250 EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2251 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2252 return;
2253 }
2254 }
2255 }
2256 if (operand.IsImmediateShiftedRegister()) {
2257 Register rm = operand.GetBaseRegister();
2258 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002259 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002260 // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2261 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2262 rm.IsLow()) {
2263 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2264 (rm.GetCode() << 6));
2265 AdvanceIT();
2266 return;
2267 }
2268 }
2269 }
2270 Shift shift = operand.GetShift();
2271 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002272 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002273 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2274 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2275 !rd.Is(pc)) {
2276 uint32_t amount_ = amount % 32;
2277 EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2278 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2279 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2280 AdvanceIT();
2281 return;
2282 }
2283 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2284 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2285 !rd.Is(pc)) {
2286 uint32_t amount_ = amount % 32;
2287 EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2288 (operand.GetTypeEncodingValue() << 4) |
2289 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2290 AdvanceIT();
2291 return;
2292 }
2293 } else {
2294 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2295 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2296 uint32_t amount_ = amount % 32;
2297 EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2298 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2299 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2300 return;
2301 }
2302 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2303 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2304 uint32_t amount_ = amount % 32;
2305 EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2306 (rd.GetCode() << 12) | rm.GetCode() |
2307 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2308 return;
2309 }
2310 }
2311 }
2312 if (operand.IsRegisterShiftedRegister()) {
2313 Register rm = operand.GetBaseRegister();
2314 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002315 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002316 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2317 if (cond.IsNotNever()) {
2318 EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2319 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2320 (shift.GetType() << 5) |
2321 (operand.GetShiftRegister().GetCode() << 8));
2322 return;
2323 }
2324 }
2325 }
2326 Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2327}
2328
2329void Assembler::adds(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002330 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002331 CheckIT(al);
2332 if (operand.IsImmediate()) {
2333 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002334 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002335 // ADDS{<q>} <Rdn>, #<imm8> ; T2
2336 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2337 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2338 AdvanceIT();
2339 return;
2340 }
2341 }
2342 }
2343 Delegate(kAdds, &Assembler::adds, rd, operand);
2344}
2345
2346void Assembler::addw(Condition cond,
2347 Register rd,
2348 Register rn,
2349 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002350 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002351 CheckIT(cond);
2352 if (operand.IsImmediate()) {
2353 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002354 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002355 // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
2356 if (rn.Is(pc) && (imm <= 4095)) {
2357 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2358 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2359 AdvanceIT();
2360 return;
2361 }
2362 // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
2363 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
2364 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2365 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2366 AdvanceIT();
2367 return;
2368 }
2369 // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
2370 if (rn.Is(sp) && (imm <= 4095)) {
2371 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2372 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2373 AdvanceIT();
2374 return;
2375 }
2376 }
2377 }
2378 Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2379}
2380
2381void Assembler::adr(Condition cond,
2382 EncodingSize size,
2383 Register rd,
2384 Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002385 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002386 CheckIT(cond);
2387 Label::Offset offset =
2388 label->IsBound()
2389 ? label->GetLocation() -
2390 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2391 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002392 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002393 int32_t neg_offset = -offset;
2394 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2395 if (!size.IsWide() && rd.IsLow() &&
2396 ((label->IsBound() && (offset >= 0) && (offset <= 1020) &&
2397 ((offset & 0x3) == 0)) ||
2398 (!label->IsBound() && size.IsNarrow()))) {
2399 static class EmitOp : public Label::LabelEmitOperator {
2400 public:
2401 EmitOp() : Label::LabelEmitOperator(0, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002402 virtual uint32_t Encode(uint32_t instr,
2403 Label::Offset pc,
2404 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002405 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2406 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2407 ((offset & 0x3) == 0));
2408 const int32_t target = offset >> 2;
2409 return instr | (target & 0xff);
2410 }
2411 } immop;
2412 EmitT32_16(Link(0xa000 | (rd.GetCode() << 8), label, immop));
2413 AdvanceIT();
2414 return;
2415 }
2416 // ADR{<c>}{<q>} <Rd>, <label> ; T2
2417 if (!size.IsNarrow() && label->IsBound() && (neg_offset > 0) &&
2418 (neg_offset <= 4095)) {
2419 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2420 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2421 AdvanceIT();
2422 return;
2423 }
2424 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2425 if (!size.IsNarrow() &&
2426 (!label->IsBound() || ((offset >= 0) && (offset <= 4095)))) {
2427 static class EmitOp : public Label::LabelEmitOperator {
2428 public:
2429 EmitOp() : Label::LabelEmitOperator(0, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002430 virtual uint32_t Encode(uint32_t instr,
2431 Label::Offset pc,
2432 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002433 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2434 int32_t target;
2435 if ((offset >= 0) && (offset <= 4095) && !label->IsMinusZero()) {
2436 target = offset;
2437 } else {
2438 target = -offset;
2439 VIXL_ASSERT((target >= 0) && (target <= 4095));
2440 // Emit the T2 encoding.
2441 instr |= 0x00a00000;
2442 }
2443 return instr | (target & 0xff) | ((target & 0x700) << 4) |
2444 ((target & 0x800) << 15);
2445 }
2446 } immop;
2447 EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8), label, immop));
2448 AdvanceIT();
2449 return;
2450 }
2451 } else {
2452 ImmediateA32 positive_immediate_a32(offset);
2453 ImmediateA32 negative_immediate_a32(-offset);
2454 // ADR{<c>}{<q>} <Rd>, <label> ; A1
2455 if ((!label->IsBound() || positive_immediate_a32.IsValid()) &&
2456 cond.IsNotNever()) {
2457 static class EmitOp : public Label::LabelEmitOperator {
2458 public:
2459 EmitOp() : Label::LabelEmitOperator(0, 255) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002460 virtual uint32_t Encode(uint32_t instr,
2461 Label::Offset pc,
2462 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002463 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
2464 int32_t target;
2465 ImmediateA32 positive_immediate_a32(offset);
2466 if (positive_immediate_a32.IsValid()) {
2467 target = positive_immediate_a32.GetEncodingValue();
2468 } else {
2469 ImmediateA32 negative_immediate_a32(-offset);
2470 VIXL_ASSERT(negative_immediate_a32.IsValid());
2471 // Emit the A2 encoding.
2472 target = negative_immediate_a32.GetEncodingValue();
2473 instr = (instr & ~0x00f00000) | 0x00400000;
2474 }
2475 return instr | (target & 0xfff);
2476 }
2477 } immop;
2478 EmitA32(
2479 Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
2480 label,
2481 immop));
2482 return;
2483 }
2484 // ADR{<c>}{<q>} <Rd>, <label> ; A2
2485 if (label->IsBound() && negative_immediate_a32.IsValid() &&
2486 cond.IsNotNever()) {
2487 EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2488 negative_immediate_a32.GetEncodingValue());
2489 return;
2490 }
2491 }
2492 Delegate(kAdr, &Assembler::adr, cond, size, rd, label);
2493}
2494
2495void Assembler::and_(Condition cond,
2496 EncodingSize size,
2497 Register rd,
2498 Register rn,
2499 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002500 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002501 CheckIT(cond);
2502 if (operand.IsImmediate()) {
2503 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002504 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002505 ImmediateT32 immediate_t32(imm);
2506 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2507 if (!size.IsNarrow() && immediate_t32.IsValid()) {
2508 EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2509 (immediate_t32.GetEncodingValue() & 0xff) |
2510 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2511 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2512 AdvanceIT();
2513 return;
2514 }
2515 } else {
2516 ImmediateA32 immediate_a32(imm);
2517 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2518 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2519 EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2520 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2521 immediate_a32.GetEncodingValue());
2522 return;
2523 }
2524 }
2525 }
2526 if (operand.IsImmediateShiftedRegister()) {
2527 Register rm = operand.GetBaseRegister();
2528 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002529 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002530 // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2531 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2532 rm.IsLow()) {
2533 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2534 AdvanceIT();
2535 return;
2536 }
2537 }
2538 }
2539 Shift shift = operand.GetShift();
2540 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002541 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002542 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2543 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
2544 uint32_t amount_ = amount % 32;
2545 EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2546 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2547 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2548 AdvanceIT();
2549 return;
2550 }
2551 } else {
2552 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2553 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2554 uint32_t amount_ = amount % 32;
2555 EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2556 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2557 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2558 return;
2559 }
2560 }
2561 }
2562 if (operand.IsRegisterShiftedRegister()) {
2563 Register rm = operand.GetBaseRegister();
2564 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002565 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002566 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2567 if (cond.IsNotNever()) {
2568 EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2569 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2570 (shift.GetType() << 5) |
2571 (operand.GetShiftRegister().GetCode() << 8));
2572 return;
2573 }
2574 }
2575 }
2576 Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2577}
2578
2579void Assembler::ands(Condition cond,
2580 EncodingSize size,
2581 Register rd,
2582 Register rn,
2583 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002584 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002585 CheckIT(cond);
2586 if (operand.IsImmediate()) {
2587 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002588 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002589 ImmediateT32 immediate_t32(imm);
2590 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
2591 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc)) {
2592 EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2593 (immediate_t32.GetEncodingValue() & 0xff) |
2594 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2595 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2596 AdvanceIT();
2597 return;
2598 }
2599 } else {
2600 ImmediateA32 immediate_a32(imm);
2601 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2602 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2603 EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2604 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2605 immediate_a32.GetEncodingValue());
2606 return;
2607 }
2608 }
2609 }
2610 if (operand.IsImmediateShiftedRegister()) {
2611 Register rm = operand.GetBaseRegister();
2612 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002613 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002614 // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2615 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2616 rm.IsLow()) {
2617 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2618 AdvanceIT();
2619 return;
2620 }
2621 }
2622 }
2623 Shift shift = operand.GetShift();
2624 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002625 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002626 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
2627 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc)) {
2628 uint32_t amount_ = amount % 32;
2629 EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2630 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2631 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2632 AdvanceIT();
2633 return;
2634 }
2635 } else {
2636 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2637 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2638 uint32_t amount_ = amount % 32;
2639 EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2640 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2641 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2642 return;
2643 }
2644 }
2645 }
2646 if (operand.IsRegisterShiftedRegister()) {
2647 Register rm = operand.GetBaseRegister();
2648 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002649 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002650 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
2651 if (cond.IsNotNever()) {
2652 EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2653 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2654 (shift.GetType() << 5) |
2655 (operand.GetShiftRegister().GetCode() << 8));
2656 return;
2657 }
2658 }
2659 }
2660 Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2661}
2662
2663void Assembler::asr(Condition cond,
2664 EncodingSize size,
2665 Register rd,
2666 Register rm,
2667 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002668 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002669 CheckIT(cond);
2670 if (operand.IsImmediate()) {
2671 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002673 // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2674 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2675 (imm >= 1) && (imm <= 32)) {
2676 uint32_t amount_ = imm % 32;
2677 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2678 (amount_ << 6));
2679 AdvanceIT();
2680 return;
2681 }
2682 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2683 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
2684 uint32_t amount_ = imm % 32;
2685 EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2686 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2687 AdvanceIT();
2688 return;
2689 }
2690 } else {
2691 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2692 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2693 uint32_t amount_ = imm % 32;
2694 EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2695 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2696 return;
2697 }
2698 }
2699 }
2700 if (operand.IsPlainRegister()) {
2701 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002702 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002703 // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2704 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2705 rs.IsLow()) {
2706 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2707 AdvanceIT();
2708 return;
2709 }
2710 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2711 if (!size.IsNarrow()) {
2712 EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2713 rs.GetCode());
2714 AdvanceIT();
2715 return;
2716 }
2717 } else {
2718 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2719 if (cond.IsNotNever()) {
2720 EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2721 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2722 return;
2723 }
2724 }
2725 }
2726 Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2727}
2728
2729void Assembler::asrs(Condition cond,
2730 EncodingSize size,
2731 Register rd,
2732 Register rm,
2733 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002734 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002735 CheckIT(cond);
2736 if (operand.IsImmediate()) {
2737 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002738 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002739 // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2740 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2741 (imm >= 1) && (imm <= 32)) {
2742 uint32_t amount_ = imm % 32;
2743 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2744 (amount_ << 6));
2745 AdvanceIT();
2746 return;
2747 }
2748 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
2749 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
2750 uint32_t amount_ = imm % 32;
2751 EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2752 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2753 AdvanceIT();
2754 return;
2755 }
2756 } else {
2757 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2758 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2759 uint32_t amount_ = imm % 32;
2760 EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2761 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2762 return;
2763 }
2764 }
2765 }
2766 if (operand.IsPlainRegister()) {
2767 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002768 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002769 // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2770 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2771 rs.IsLow()) {
2772 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2773 AdvanceIT();
2774 return;
2775 }
2776 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
2777 if (!size.IsNarrow()) {
2778 EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2779 rs.GetCode());
2780 AdvanceIT();
2781 return;
2782 }
2783 } else {
2784 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
2785 if (cond.IsNotNever()) {
2786 EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
2787 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2788 return;
2789 }
2790 }
2791 }
2792 Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
2793}
2794
2795void Assembler::b(Condition cond, EncodingSize size, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002796 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002797 Label::Offset offset =
2798 label->IsBound()
2799 ? label->GetLocation() -
2800 (GetCursorOffset() + GetArchitectureStatePCOffset())
2801 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002802 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002803 // B<c>{<q>} <label> ; T1
2804 if (OutsideITBlock() && !size.IsWide() &&
2805 ((label->IsBound() && (offset >= -256) && (offset <= 254) &&
2806 ((offset & 0x1) == 0)) ||
2807 (!label->IsBound() && size.IsNarrow())) &&
2808 !cond.Is(al) && cond.IsNotNever()) {
2809 static class EmitOp : public Label::LabelEmitOperator {
2810 public:
2811 EmitOp() : Label::LabelEmitOperator(-256, 254) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002812 virtual uint32_t Encode(uint32_t instr,
2813 Label::Offset pc,
2814 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002815 Label::Offset offset = label->GetLocation() - pc;
2816 VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
2817 ((offset & 0x1) == 0));
2818 const int32_t target = offset >> 1;
2819 return instr | (target & 0xff);
2820 }
2821 } immop;
2822 EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8), label, immop));
2823 AdvanceIT();
2824 return;
2825 }
2826 // B{<c>}{<q>} <label> ; T2
2827 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
2828 ((label->IsBound() && (offset >= -2048) && (offset <= 2046) &&
2829 ((offset & 0x1) == 0)) ||
2830 (!label->IsBound() && size.IsNarrow()))) {
2831 CheckIT(cond);
2832 static class EmitOp : public Label::LabelEmitOperator {
2833 public:
2834 EmitOp() : Label::LabelEmitOperator(-2048, 2046) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002835 virtual uint32_t Encode(uint32_t instr,
2836 Label::Offset pc,
2837 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002838 Label::Offset offset = label->GetLocation() - pc;
2839 VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
2840 ((offset & 0x1) == 0));
2841 const int32_t target = offset >> 1;
2842 return instr | (target & 0x7ff);
2843 }
2844 } immop;
2845 EmitT32_16(Link(0xe000, label, immop));
2846 AdvanceIT();
2847 return;
2848 }
2849 // B<c>{<q>} <label> ; T3
2850 if (OutsideITBlock() && !size.IsNarrow() &&
2851 ((label->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
2852 ((offset & 0x1) == 0)) ||
2853 !label->IsBound()) &&
2854 !cond.Is(al) && cond.IsNotNever()) {
2855 static class EmitOp : public Label::LabelEmitOperator {
2856 public:
2857 EmitOp() : Label::LabelEmitOperator(-1048576, 1048574) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002858 virtual uint32_t Encode(uint32_t instr,
2859 Label::Offset pc,
2860 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002861 Label::Offset offset = label->GetLocation() - pc;
2862 VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
2863 ((offset & 0x1) == 0));
2864 const int32_t target = offset >> 1;
2865 return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
2866 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
2867 ((target & 0x80000) << 7);
2868 }
2869 } immop;
2870 EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22), label, immop));
2871 AdvanceIT();
2872 return;
2873 }
2874 // B{<c>}{<q>} <label> ; T4
2875 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
2876 ((label->IsBound() && (offset >= -16777216) && (offset <= 16777214) &&
2877 ((offset & 0x1) == 0)) ||
2878 !label->IsBound())) {
2879 CheckIT(cond);
2880 static class EmitOp : public Label::LabelEmitOperator {
2881 public:
2882 EmitOp() : Label::LabelEmitOperator(-16777216, 16777214) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002883 virtual uint32_t Encode(uint32_t instr,
2884 Label::Offset pc,
2885 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002886 Label::Offset offset = label->GetLocation() - pc;
2887 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
2888 ((offset & 0x1) == 0));
2889 int32_t target = offset >> 1;
2890 uint32_t S = target & (1 << 23);
2891 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
2892 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
2893 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
2894 ((target & 0x800000) << 3);
2895 }
2896 } immop;
2897 EmitT32_32(Link(0xf0009000U, label, immop));
2898 AdvanceIT();
2899 return;
2900 }
2901 } else {
2902 // B{<c>}{<q>} <label> ; A1
2903 if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554428) &&
2904 ((offset & 0x3) == 0)) ||
2905 !label->IsBound()) &&
2906 cond.IsNotNever()) {
2907 static class EmitOp : public Label::LabelEmitOperator {
2908 public:
2909 EmitOp() : Label::LabelEmitOperator(-33554432, 33554428) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002910 virtual uint32_t Encode(uint32_t instr,
2911 Label::Offset pc,
2912 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002913 Label::Offset offset = label->GetLocation() - pc;
2914 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
2915 ((offset & 0x3) == 0));
2916 const int32_t target = offset >> 2;
2917 return instr | (target & 0xffffff);
2918 }
2919 } immop;
2920 EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28), label, immop));
2921 return;
2922 }
2923 }
2924 Delegate(kB, &Assembler::b, cond, size, label);
2925}
2926
2927void Assembler::bfc(Condition cond,
2928 Register rd,
2929 uint32_t lsb,
2930 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002931 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002932 CheckIT(cond);
2933 if (operand.IsImmediate()) {
2934 uint32_t width = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002936 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
2937 if ((lsb <= 31) &&
2938 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2939 uint32_t msb = lsb + width - 1;
2940 EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
2941 ((lsb & 0x1c) << 10) | msb);
2942 AdvanceIT();
2943 return;
2944 }
2945 } else {
2946 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
2947 if ((lsb <= 31) && cond.IsNotNever() &&
2948 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2949 uint32_t msb = lsb + width - 1;
2950 EmitA32(0x07c0001fU | (cond.GetCondition() << 28) |
2951 (rd.GetCode() << 12) | (lsb << 7) | (msb << 16));
2952 return;
2953 }
2954 }
2955 }
2956 Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, operand);
2957}
2958
2959void Assembler::bfi(Condition cond,
2960 Register rd,
2961 Register rn,
2962 uint32_t lsb,
2963 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002964 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002965 CheckIT(cond);
2966 if (operand.IsImmediate()) {
2967 uint32_t width = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002968 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002969 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
2970 if ((lsb <= 31) && !rn.Is(pc) &&
2971 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2972 uint32_t msb = lsb + width - 1;
2973 EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2974 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
2975 AdvanceIT();
2976 return;
2977 }
2978 } else {
2979 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
2980 if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
2981 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
2982 uint32_t msb = lsb + width - 1;
2983 EmitA32(0x07c00010U | (cond.GetCondition() << 28) |
2984 (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) | (msb << 16));
2985 return;
2986 }
2987 }
2988 }
2989 Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, operand);
2990}
2991
2992void Assembler::bic(Condition cond,
2993 EncodingSize size,
2994 Register rd,
2995 Register rn,
2996 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002997 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002998 CheckIT(cond);
2999 if (operand.IsImmediate()) {
3000 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003001 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003002 ImmediateT32 immediate_t32(imm);
3003 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3004 if (!size.IsNarrow() && immediate_t32.IsValid()) {
3005 EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3006 (immediate_t32.GetEncodingValue() & 0xff) |
3007 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3008 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3009 AdvanceIT();
3010 return;
3011 }
3012 } else {
3013 ImmediateA32 immediate_a32(imm);
3014 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3015 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3016 EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3017 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3018 immediate_a32.GetEncodingValue());
3019 return;
3020 }
3021 }
3022 }
3023 if (operand.IsImmediateShiftedRegister()) {
3024 Register rm = operand.GetBaseRegister();
3025 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003026 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003027 // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3028 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3029 rm.IsLow()) {
3030 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3031 AdvanceIT();
3032 return;
3033 }
3034 }
3035 }
3036 Shift shift = operand.GetShift();
3037 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003038 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003039 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3040 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3041 uint32_t amount_ = amount % 32;
3042 EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3043 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3044 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3045 AdvanceIT();
3046 return;
3047 }
3048 } else {
3049 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3050 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3051 uint32_t amount_ = amount % 32;
3052 EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3053 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3054 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3055 return;
3056 }
3057 }
3058 }
3059 if (operand.IsRegisterShiftedRegister()) {
3060 Register rm = operand.GetBaseRegister();
3061 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003062 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003063 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3064 if (cond.IsNotNever()) {
3065 EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3066 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3067 (shift.GetType() << 5) |
3068 (operand.GetShiftRegister().GetCode() << 8));
3069 return;
3070 }
3071 }
3072 }
3073 Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3074}
3075
3076void Assembler::bics(Condition cond,
3077 EncodingSize size,
3078 Register rd,
3079 Register rn,
3080 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003081 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003082 CheckIT(cond);
3083 if (operand.IsImmediate()) {
3084 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003085 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003086 ImmediateT32 immediate_t32(imm);
3087 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3088 if (!size.IsNarrow() && immediate_t32.IsValid()) {
3089 EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3090 (immediate_t32.GetEncodingValue() & 0xff) |
3091 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3092 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3093 AdvanceIT();
3094 return;
3095 }
3096 } else {
3097 ImmediateA32 immediate_a32(imm);
3098 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3099 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3100 EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3101 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3102 immediate_a32.GetEncodingValue());
3103 return;
3104 }
3105 }
3106 }
3107 if (operand.IsImmediateShiftedRegister()) {
3108 Register rm = operand.GetBaseRegister();
3109 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003110 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003111 // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3112 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3113 rm.IsLow()) {
3114 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3115 AdvanceIT();
3116 return;
3117 }
3118 }
3119 }
3120 Shift shift = operand.GetShift();
3121 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003122 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003123 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3124 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3125 uint32_t amount_ = amount % 32;
3126 EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3127 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3128 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3129 AdvanceIT();
3130 return;
3131 }
3132 } else {
3133 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3134 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3135 uint32_t amount_ = amount % 32;
3136 EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3137 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3138 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3139 return;
3140 }
3141 }
3142 }
3143 if (operand.IsRegisterShiftedRegister()) {
3144 Register rm = operand.GetBaseRegister();
3145 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003146 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003147 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3148 if (cond.IsNotNever()) {
3149 EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3150 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3151 (shift.GetType() << 5) |
3152 (operand.GetShiftRegister().GetCode() << 8));
3153 return;
3154 }
3155 }
3156 }
3157 Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3158}
3159
3160void Assembler::bkpt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003161 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003162 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003163 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003164 // BKPT{<q>} {#}<imm> ; T1
3165 if ((imm <= 255)) {
3166 EmitT32_16(0xbe00 | imm);
3167 AdvanceIT();
3168 return;
3169 }
3170 } else {
3171 // BKPT{<q>} {#}<imm> ; A1
3172 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3173 EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3174 ((imm & 0xfff0) << 4));
3175 return;
3176 }
3177 }
3178 Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3179}
3180
3181void Assembler::bl(Condition cond, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003182 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003183 CheckIT(cond);
3184 Label::Offset offset =
3185 label->IsBound()
3186 ? label->GetLocation() -
3187 (GetCursorOffset() + GetArchitectureStatePCOffset())
3188 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003189 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003190 // BL{<c>}{<q>} <label> ; T1
3191 if (((label->IsBound() && (offset >= -16777216) && (offset <= 16777214) &&
3192 ((offset & 0x1) == 0)) ||
3193 !label->IsBound())) {
3194 static class EmitOp : public Label::LabelEmitOperator {
3195 public:
3196 EmitOp() : Label::LabelEmitOperator(-16777216, 16777214) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003197 virtual uint32_t Encode(uint32_t instr,
3198 Label::Offset pc,
3199 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003200 Label::Offset offset = label->GetLocation() - pc;
3201 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3202 ((offset & 0x1) == 0));
3203 int32_t target = offset >> 1;
3204 uint32_t S = target & (1 << 23);
3205 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3206 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3207 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3208 ((target & 0x800000) << 3);
3209 }
3210 } immop;
3211 EmitT32_32(Link(0xf000d000U, label, immop));
3212 AdvanceIT();
3213 return;
3214 }
3215 } else {
3216 // BL{<c>}{<q>} <label> ; A1
3217 if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554428) &&
3218 ((offset & 0x3) == 0)) ||
3219 !label->IsBound()) &&
3220 cond.IsNotNever()) {
3221 static class EmitOp : public Label::LabelEmitOperator {
3222 public:
3223 EmitOp() : Label::LabelEmitOperator(-33554432, 33554428) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003224 virtual uint32_t Encode(uint32_t instr,
3225 Label::Offset pc,
3226 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003227 Label::Offset offset = label->GetLocation() - pc;
3228 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3229 ((offset & 0x3) == 0));
3230 const int32_t target = offset >> 2;
3231 return instr | (target & 0xffffff);
3232 }
3233 } immop;
3234 EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28), label, immop));
3235 return;
3236 }
3237 }
3238 Delegate(kBl, &Assembler::bl, cond, label);
3239}
3240
3241void Assembler::blx(Condition cond, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003243 CheckIT(cond);
3244 Label::Offset offset =
3245 label->IsBound()
3246 ? label->GetLocation() -
3247 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3248 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003249 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003250 // BLX{<c>}{<q>} <label> ; T2
3251 if (((label->IsBound() && (offset >= -16777216) && (offset <= 16777212) &&
3252 ((offset & 0x3) == 0)) ||
3253 !label->IsBound())) {
3254 static class EmitOp : public Label::LabelEmitOperator {
3255 public:
3256 EmitOp() : Label::LabelEmitOperator(-16777216, 16777212) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003257 virtual uint32_t Encode(uint32_t instr,
3258 Label::Offset pc,
3259 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003260 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
3261 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3262 ((offset & 0x3) == 0));
3263 int32_t target = offset >> 2;
3264 uint32_t S = target & (1 << 22);
3265 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3266 return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3267 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3268 ((target & 0x400000) << 4);
3269 }
3270 } immop;
3271 EmitT32_32(Link(0xf000c000U, label, immop));
3272 AdvanceIT();
3273 return;
3274 }
3275 } else {
3276 // BLX{<c>}{<q>} <label> ; A2
3277 if (((label->IsBound() && (offset >= -33554432) && (offset <= 33554430) &&
3278 ((offset & 0x1) == 0)) ||
3279 !label->IsBound())) {
3280 if (cond.Is(al) || AllowStronglyDiscouraged()) {
3281 static class EmitOp : public Label::LabelEmitOperator {
3282 public:
3283 EmitOp() : Label::LabelEmitOperator(-33554432, 33554430) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003284 virtual uint32_t Encode(uint32_t instr,
3285 Label::Offset pc,
3286 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003287 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
3288 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3289 ((offset & 0x1) == 0));
3290 const int32_t target = offset >> 1;
3291 return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3292 }
3293 } immop;
3294 EmitA32(Link(0xfa000000U, label, immop));
3295 return;
3296 }
3297 }
3298 }
3299 Delegate(kBlx, &Assembler::blx, cond, label);
3300}
3301
3302void Assembler::blx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003303 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003304 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003305 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003306 // BLX{<c>}{<q>} <Rm> ; T1
3307 EmitT32_16(0x4780 | (rm.GetCode() << 3));
3308 AdvanceIT();
3309 return;
3310 } else {
3311 // BLX{<c>}{<q>} <Rm> ; A1
3312 if (cond.IsNotNever()) {
3313 EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3314 return;
3315 }
3316 }
3317 Delegate(kBlx, &Assembler::blx, cond, rm);
3318}
3319
3320void Assembler::bx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003321 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003322 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003323 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003324 // BX{<c>}{<q>} <Rm> ; T1
3325 EmitT32_16(0x4700 | (rm.GetCode() << 3));
3326 AdvanceIT();
3327 return;
3328 } else {
3329 // BX{<c>}{<q>} <Rm> ; A1
3330 if (cond.IsNotNever()) {
3331 EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3332 return;
3333 }
3334 }
3335 Delegate(kBx, &Assembler::bx, cond, rm);
3336}
3337
3338void Assembler::bxj(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003339 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003340 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003341 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003342 // BXJ{<c>}{<q>} <Rm> ; T1
3343 EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3344 AdvanceIT();
3345 return;
3346 } else {
3347 // BXJ{<c>}{<q>} <Rm> ; A1
3348 if (cond.IsNotNever()) {
3349 EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3350 return;
3351 }
3352 }
3353 Delegate(kBxj, &Assembler::bxj, cond, rm);
3354}
3355
3356void Assembler::cbnz(Register rn, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003357 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003358 CheckIT(al);
3359 Label::Offset offset =
3360 label->IsBound()
3361 ? label->GetLocation() -
3362 (GetCursorOffset() + GetArchitectureStatePCOffset())
3363 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003364 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003365 // CBNZ{<q>} <Rn>, <label> ; T1
3366 if (rn.IsLow() && ((label->IsBound() && (offset >= 0) && (offset <= 126) &&
3367 ((offset & 0x1) == 0)) ||
3368 !label->IsBound())) {
3369 static class EmitOp : public Label::LabelEmitOperator {
3370 public:
3371 EmitOp() : Label::LabelEmitOperator(0, 126) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003372 virtual uint32_t Encode(uint32_t instr,
3373 Label::Offset pc,
3374 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003375 Label::Offset offset = label->GetLocation() - pc;
3376 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3377 ((offset & 0x1) == 0));
3378 const int32_t target = offset >> 1;
3379 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3380 }
3381 } immop;
3382 EmitT32_16(Link(0xb900 | rn.GetCode(), label, immop));
3383 AdvanceIT();
3384 return;
3385 }
3386 }
3387 Delegate(kCbnz, &Assembler::cbnz, rn, label);
3388}
3389
3390void Assembler::cbz(Register rn, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003391 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003392 CheckIT(al);
3393 Label::Offset offset =
3394 label->IsBound()
3395 ? label->GetLocation() -
3396 (GetCursorOffset() + GetArchitectureStatePCOffset())
3397 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003398 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003399 // CBZ{<q>} <Rn>, <label> ; T1
3400 if (rn.IsLow() && ((label->IsBound() && (offset >= 0) && (offset <= 126) &&
3401 ((offset & 0x1) == 0)) ||
3402 !label->IsBound())) {
3403 static class EmitOp : public Label::LabelEmitOperator {
3404 public:
3405 EmitOp() : Label::LabelEmitOperator(0, 126) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003406 virtual uint32_t Encode(uint32_t instr,
3407 Label::Offset pc,
3408 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003409 Label::Offset offset = label->GetLocation() - pc;
3410 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3411 ((offset & 0x1) == 0));
3412 const int32_t target = offset >> 1;
3413 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3414 }
3415 } immop;
3416 EmitT32_16(Link(0xb100 | rn.GetCode(), label, immop));
3417 AdvanceIT();
3418 return;
3419 }
3420 }
3421 Delegate(kCbz, &Assembler::cbz, rn, label);
3422}
3423
3424void Assembler::clrex(Condition cond) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003425 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003426 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003427 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003428 // CLREX{<c>}{<q>} ; T1
3429 EmitT32_32(0xf3bf8f2fU);
3430 AdvanceIT();
3431 return;
3432 } else {
3433 // CLREX{<c>}{<q>} ; A1
3434 if (cond.Is(al)) {
3435 EmitA32(0xf57ff01fU);
3436 return;
3437 }
3438 }
3439 Delegate(kClrex, &Assembler::clrex, cond);
3440}
3441
3442void Assembler::clz(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003443 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003444 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003445 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003446 // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
3447 EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3448 (rm.GetCode() << 16));
3449 AdvanceIT();
3450 return;
3451 } else {
3452 // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
3453 if (cond.IsNotNever()) {
3454 EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3455 rm.GetCode());
3456 return;
3457 }
3458 }
3459 Delegate(kClz, &Assembler::clz, cond, rd, rm);
3460}
3461
3462void Assembler::cmn(Condition cond,
3463 EncodingSize size,
3464 Register rn,
3465 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003466 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003467 CheckIT(cond);
3468 if (operand.IsImmediate()) {
3469 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003470 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003471 ImmediateT32 immediate_t32(imm);
3472 // CMN{<c>}{<q>} <Rn>, #<const> ; T1
3473 if (!size.IsNarrow() && immediate_t32.IsValid()) {
3474 EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3475 (immediate_t32.GetEncodingValue() & 0xff) |
3476 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3477 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3478 AdvanceIT();
3479 return;
3480 }
3481 } else {
3482 ImmediateA32 immediate_a32(imm);
3483 // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3484 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3485 EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3486 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3487 return;
3488 }
3489 }
3490 }
3491 if (operand.IsImmediateShiftedRegister()) {
3492 Register rm = operand.GetBaseRegister();
3493 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003494 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003495 // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3496 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3497 EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3498 AdvanceIT();
3499 return;
3500 }
3501 }
3502 }
3503 Shift shift = operand.GetShift();
3504 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003505 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003506 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
3507 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3508 uint32_t amount_ = amount % 32;
3509 EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3510 (operand.GetTypeEncodingValue() << 4) |
3511 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3512 AdvanceIT();
3513 return;
3514 }
3515 } else {
3516 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3517 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3518 uint32_t amount_ = amount % 32;
3519 EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3520 (rn.GetCode() << 16) | rm.GetCode() |
3521 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3522 return;
3523 }
3524 }
3525 }
3526 if (operand.IsRegisterShiftedRegister()) {
3527 Register rm = operand.GetBaseRegister();
3528 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003529 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003530 // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3531 if (cond.IsNotNever()) {
3532 EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3533 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3534 (operand.GetShiftRegister().GetCode() << 8));
3535 return;
3536 }
3537 }
3538 }
3539 Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3540}
3541
3542void Assembler::cmp(Condition cond,
3543 EncodingSize size,
3544 Register rn,
3545 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003546 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003547 CheckIT(cond);
3548 if (operand.IsImmediate()) {
3549 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003550 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003551 ImmediateT32 immediate_t32(imm);
3552 // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3553 if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3554 EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3555 AdvanceIT();
3556 return;
3557 }
3558 // CMP{<c>}{<q>} <Rn>, #<const> ; T2
3559 if (!size.IsNarrow() && immediate_t32.IsValid()) {
3560 EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3561 (immediate_t32.GetEncodingValue() & 0xff) |
3562 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3563 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3564 AdvanceIT();
3565 return;
3566 }
3567 } else {
3568 ImmediateA32 immediate_a32(imm);
3569 // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3570 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3571 EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3572 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3573 return;
3574 }
3575 }
3576 }
3577 if (operand.IsImmediateShiftedRegister()) {
3578 Register rm = operand.GetBaseRegister();
3579 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003580 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003581 // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3582 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3583 EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3584 AdvanceIT();
3585 return;
3586 }
3587 // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
3588 if (!size.IsWide()) {
3589 EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3590 ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3591 AdvanceIT();
3592 return;
3593 }
3594 }
3595 }
3596 Shift shift = operand.GetShift();
3597 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003598 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003599 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
3600 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3601 uint32_t amount_ = amount % 32;
3602 EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3603 (operand.GetTypeEncodingValue() << 4) |
3604 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3605 AdvanceIT();
3606 return;
3607 }
3608 } else {
3609 // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3610 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3611 uint32_t amount_ = amount % 32;
3612 EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3613 (rn.GetCode() << 16) | rm.GetCode() |
3614 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3615 return;
3616 }
3617 }
3618 }
3619 if (operand.IsRegisterShiftedRegister()) {
3620 Register rm = operand.GetBaseRegister();
3621 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003622 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003623 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
3624 if (cond.IsNotNever()) {
3625 EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3626 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
3627 (operand.GetShiftRegister().GetCode() << 8));
3628 return;
3629 }
3630 }
3631 }
3632 Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
3633}
3634
3635void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003636 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003637 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003638 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003639 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
3640 EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3641 rm.GetCode());
3642 AdvanceIT();
3643 return;
3644 } else {
3645 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
3646 if ((cond.Is(al) || AllowUnpredictable())) {
3647 EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3648 (rn.GetCode() << 16) | rm.GetCode());
3649 return;
3650 }
3651 }
3652 Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
3653}
3654
3655void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003656 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003657 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003658 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003659 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
3660 EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3661 rm.GetCode());
3662 AdvanceIT();
3663 return;
3664 } else {
3665 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
3666 if ((cond.Is(al) || AllowUnpredictable())) {
3667 EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3668 (rn.GetCode() << 16) | rm.GetCode());
3669 return;
3670 }
3671 }
3672 Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
3673}
3674
3675void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003676 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003677 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003678 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003679 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
3680 EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3681 rm.GetCode());
3682 AdvanceIT();
3683 return;
3684 } else {
3685 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
3686 if ((cond.Is(al) || AllowUnpredictable())) {
3687 EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3688 (rn.GetCode() << 16) | rm.GetCode());
3689 return;
3690 }
3691 }
3692 Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
3693}
3694
3695void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003696 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003697 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003698 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003699 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
3700 EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3701 rm.GetCode());
3702 AdvanceIT();
3703 return;
3704 } else {
3705 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
3706 if ((cond.Is(al) || AllowUnpredictable())) {
3707 EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3708 (rn.GetCode() << 16) | rm.GetCode());
3709 return;
3710 }
3711 }
3712 Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
3713}
3714
3715void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003716 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003717 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003718 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003719 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
3720 EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3721 rm.GetCode());
3722 AdvanceIT();
3723 return;
3724 } else {
3725 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
3726 if ((cond.Is(al) || AllowUnpredictable())) {
3727 EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3728 (rn.GetCode() << 16) | rm.GetCode());
3729 return;
3730 }
3731 }
3732 Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
3733}
3734
3735void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003736 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003737 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003738 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003739 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
3740 EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3741 rm.GetCode());
3742 AdvanceIT();
3743 return;
3744 } else {
3745 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
3746 if ((cond.Is(al) || AllowUnpredictable())) {
3747 EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3748 (rn.GetCode() << 16) | rm.GetCode());
3749 return;
3750 }
3751 }
3752 Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
3753}
3754
3755void Assembler::dmb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003756 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003757 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003758 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003759 // DMB{<c>}{<q>} {<option>} ; T1
3760 EmitT32_32(0xf3bf8f50U | option.GetType());
3761 AdvanceIT();
3762 return;
3763 } else {
3764 // DMB{<c>}{<q>} {<option>} ; A1
3765 if (cond.Is(al)) {
3766 EmitA32(0xf57ff050U | option.GetType());
3767 return;
3768 }
3769 }
3770 Delegate(kDmb, &Assembler::dmb, cond, option);
3771}
3772
3773void Assembler::dsb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003774 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003775 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003776 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003777 // DSB{<c>}{<q>} {<option>} ; T1
3778 EmitT32_32(0xf3bf8f40U | option.GetType());
3779 AdvanceIT();
3780 return;
3781 } else {
3782 // DSB{<c>}{<q>} {<option>} ; A1
3783 if (cond.Is(al)) {
3784 EmitA32(0xf57ff040U | option.GetType());
3785 return;
3786 }
3787 }
3788 Delegate(kDsb, &Assembler::dsb, cond, option);
3789}
3790
3791void Assembler::eor(Condition cond,
3792 EncodingSize size,
3793 Register rd,
3794 Register rn,
3795 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003796 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003797 CheckIT(cond);
3798 if (operand.IsImmediate()) {
3799 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003800 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003801 ImmediateT32 immediate_t32(imm);
3802 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3803 if (!size.IsNarrow() && immediate_t32.IsValid()) {
3804 EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3805 (immediate_t32.GetEncodingValue() & 0xff) |
3806 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3807 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3808 AdvanceIT();
3809 return;
3810 }
3811 } else {
3812 ImmediateA32 immediate_a32(imm);
3813 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3814 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3815 EmitA32(0x02200000U | (cond.GetCondition() << 28) |
3816 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3817 immediate_a32.GetEncodingValue());
3818 return;
3819 }
3820 }
3821 }
3822 if (operand.IsImmediateShiftedRegister()) {
3823 Register rm = operand.GetBaseRegister();
3824 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003825 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003826 // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3827 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3828 rm.IsLow()) {
3829 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
3830 AdvanceIT();
3831 return;
3832 }
3833 }
3834 }
3835 Shift shift = operand.GetShift();
3836 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003837 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003838 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3839 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
3840 uint32_t amount_ = amount % 32;
3841 EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3842 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3843 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3844 AdvanceIT();
3845 return;
3846 }
3847 } else {
3848 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3849 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3850 uint32_t amount_ = amount % 32;
3851 EmitA32(0x00200000U | (cond.GetCondition() << 28) |
3852 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3853 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3854 return;
3855 }
3856 }
3857 }
3858 if (operand.IsRegisterShiftedRegister()) {
3859 Register rm = operand.GetBaseRegister();
3860 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003861 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003862 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3863 if (cond.IsNotNever()) {
3864 EmitA32(0x00200010U | (cond.GetCondition() << 28) |
3865 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3866 (shift.GetType() << 5) |
3867 (operand.GetShiftRegister().GetCode() << 8));
3868 return;
3869 }
3870 }
3871 }
3872 Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
3873}
3874
3875void Assembler::eors(Condition cond,
3876 EncodingSize size,
3877 Register rd,
3878 Register rn,
3879 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003880 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003881 CheckIT(cond);
3882 if (operand.IsImmediate()) {
3883 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003884 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003885 ImmediateT32 immediate_t32(imm);
3886 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
3887 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc)) {
3888 EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3889 (immediate_t32.GetEncodingValue() & 0xff) |
3890 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3891 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3892 AdvanceIT();
3893 return;
3894 }
3895 } else {
3896 ImmediateA32 immediate_a32(imm);
3897 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3898 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3899 EmitA32(0x02300000U | (cond.GetCondition() << 28) |
3900 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3901 immediate_a32.GetEncodingValue());
3902 return;
3903 }
3904 }
3905 }
3906 if (operand.IsImmediateShiftedRegister()) {
3907 Register rm = operand.GetBaseRegister();
3908 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003909 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003910 // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3911 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3912 rm.IsLow()) {
3913 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
3914 AdvanceIT();
3915 return;
3916 }
3917 }
3918 }
3919 Shift shift = operand.GetShift();
3920 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003921 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003922 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
3923 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc)) {
3924 uint32_t amount_ = amount % 32;
3925 EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3926 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3927 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3928 AdvanceIT();
3929 return;
3930 }
3931 } else {
3932 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3933 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3934 uint32_t amount_ = amount % 32;
3935 EmitA32(0x00300000U | (cond.GetCondition() << 28) |
3936 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3937 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3938 return;
3939 }
3940 }
3941 }
3942 if (operand.IsRegisterShiftedRegister()) {
3943 Register rm = operand.GetBaseRegister();
3944 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003945 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003946 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
3947 if (cond.IsNotNever()) {
3948 EmitA32(0x00300010U | (cond.GetCondition() << 28) |
3949 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3950 (shift.GetType() << 5) |
3951 (operand.GetShiftRegister().GetCode() << 8));
3952 return;
3953 }
3954 }
3955 }
3956 Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
3957}
3958
3959void Assembler::fldmdbx(Condition cond,
3960 Register rn,
3961 WriteBack write_back,
3962 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003963 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003964 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003965 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003966 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
3967 if (write_back.DoesWriteBack() &&
3968 (((dreglist.GetLength() <= 16) &&
3969 (dreglist.GetLastDRegister().GetCode() < 16)) ||
3970 AllowUnpredictable())) {
3971 const DRegister& dreg = dreglist.GetFirstDRegister();
3972 unsigned len = dreglist.GetLength() * 2;
3973 EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
3974 (len & 0xff));
3975 AdvanceIT();
3976 return;
3977 }
3978 } else {
3979 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
3980 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
3981 (((dreglist.GetLength() <= 16) &&
3982 (dreglist.GetLastDRegister().GetCode() < 16)) ||
3983 AllowUnpredictable())) {
3984 const DRegister& dreg = dreglist.GetFirstDRegister();
3985 unsigned len = dreglist.GetLength() * 2;
3986 EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
3987 dreg.Encode(22, 12) | (len & 0xff));
3988 return;
3989 }
3990 }
3991 Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
3992}
3993
3994void Assembler::fldmiax(Condition cond,
3995 Register rn,
3996 WriteBack write_back,
3997 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003998 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003999 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004000 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004001 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4002 if ((((dreglist.GetLength() <= 16) &&
4003 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4004 AllowUnpredictable())) {
4005 const DRegister& dreg = dreglist.GetFirstDRegister();
4006 unsigned len = dreglist.GetLength() * 2;
4007 EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4008 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4009 (len & 0xff));
4010 AdvanceIT();
4011 return;
4012 }
4013 } else {
4014 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4015 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4016 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4017 AllowUnpredictable())) {
4018 const DRegister& dreg = dreglist.GetFirstDRegister();
4019 unsigned len = dreglist.GetLength() * 2;
4020 EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4021 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4022 (len & 0xff));
4023 return;
4024 }
4025 }
4026 Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4027}
4028
4029void Assembler::fstmdbx(Condition cond,
4030 Register rn,
4031 WriteBack write_back,
4032 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004033 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004034 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004035 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004036 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4037 if (write_back.DoesWriteBack() &&
4038 (((dreglist.GetLength() <= 16) &&
4039 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4040 AllowUnpredictable())) {
4041 const DRegister& dreg = dreglist.GetFirstDRegister();
4042 unsigned len = dreglist.GetLength() * 2;
4043 EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4044 (len & 0xff));
4045 AdvanceIT();
4046 return;
4047 }
4048 } else {
4049 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4050 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4051 (((dreglist.GetLength() <= 16) &&
4052 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4053 AllowUnpredictable())) {
4054 const DRegister& dreg = dreglist.GetFirstDRegister();
4055 unsigned len = dreglist.GetLength() * 2;
4056 EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4057 dreg.Encode(22, 12) | (len & 0xff));
4058 return;
4059 }
4060 }
4061 Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4062}
4063
4064void Assembler::fstmiax(Condition cond,
4065 Register rn,
4066 WriteBack write_back,
4067 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004068 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004069 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004070 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004071 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4072 if ((((dreglist.GetLength() <= 16) &&
4073 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4074 AllowUnpredictable())) {
4075 const DRegister& dreg = dreglist.GetFirstDRegister();
4076 unsigned len = dreglist.GetLength() * 2;
4077 EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4078 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4079 (len & 0xff));
4080 AdvanceIT();
4081 return;
4082 }
4083 } else {
4084 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4085 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4086 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4087 AllowUnpredictable())) {
4088 const DRegister& dreg = dreglist.GetFirstDRegister();
4089 unsigned len = dreglist.GetLength() * 2;
4090 EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4091 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4092 (len & 0xff));
4093 return;
4094 }
4095 }
4096 Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4097}
4098
4099void Assembler::hlt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004100 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004101 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004102 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004103 // HLT{<q>} {#}<imm> ; T1
4104 if ((imm <= 63)) {
4105 EmitT32_16(0xba80 | imm);
4106 AdvanceIT();
4107 return;
4108 }
4109 } else {
4110 // HLT{<q>} {#}<imm> ; A1
4111 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4112 EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4113 ((imm & 0xfff0) << 4));
4114 return;
4115 }
4116 }
4117 Delegate(kHlt, &Assembler::hlt, cond, imm);
4118}
4119
4120void Assembler::hvc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004121 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004122 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004123 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004124 // HVC{<q>} {#}<imm16> ; T1
4125 if ((imm <= 65535)) {
4126 EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4127 AdvanceIT();
4128 return;
4129 }
4130 } else {
4131 // HVC{<q>} {#}<imm16> ; A1
4132 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4133 EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4134 ((imm & 0xfff0) << 4));
4135 return;
4136 }
4137 }
4138 Delegate(kHvc, &Assembler::hvc, cond, imm);
4139}
4140
4141void Assembler::isb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004142 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004143 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004144 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004145 // ISB{<c>}{<q>} {<option>} ; T1
4146 EmitT32_32(0xf3bf8f60U | option.GetType());
4147 AdvanceIT();
4148 return;
4149 } else {
4150 // ISB{<c>}{<q>} {<option>} ; A1
4151 if (cond.Is(al)) {
4152 EmitA32(0xf57ff060U | option.GetType());
4153 return;
4154 }
4155 }
4156 Delegate(kIsb, &Assembler::isb, cond, option);
4157}
4158
4159void Assembler::it(Condition cond, uint16_t mask) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004160 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004161 CheckNotIT();
4162 if (mask != 0) {
4163 if ((cond.GetCondition() & 0x1) != 0) {
4164 if ((mask & 0x1) != 0) {
4165 mask ^= 0xE;
4166 } else if ((mask & 0x2) != 0) {
4167 mask ^= 0xC;
4168 } else if ((mask & 0x4) != 0) {
4169 mask ^= 0x8;
4170 }
4171 }
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004172 if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004173 SetIT(cond, mask);
4174 return;
4175 }
4176 DelegateIt(cond, mask);
4177}
4178
4179void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004180 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004181 CheckIT(cond);
4182 if (operand.IsImmediateZero()) {
4183 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004184 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004185 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
4186 if ((operand.GetAddrMode() == Offset) &&
4187 ((!rn.IsPC()) || AllowUnpredictable())) {
4188 EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4189 AdvanceIT();
4190 return;
4191 }
4192 } else {
4193 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
4194 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4195 ((!rn.IsPC()) || AllowUnpredictable())) {
4196 EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4197 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4198 return;
4199 }
4200 }
4201 }
4202 Delegate(kLda, &Assembler::lda, cond, rt, operand);
4203}
4204
4205void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004206 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004207 CheckIT(cond);
4208 if (operand.IsImmediateZero()) {
4209 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004210 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004211 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4212 if ((operand.GetAddrMode() == Offset) &&
4213 ((!rn.IsPC()) || AllowUnpredictable())) {
4214 EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4215 AdvanceIT();
4216 return;
4217 }
4218 } else {
4219 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4220 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4221 ((!rn.IsPC()) || AllowUnpredictable())) {
4222 EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4223 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4224 return;
4225 }
4226 }
4227 }
4228 Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4229}
4230
4231void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004232 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004233 CheckIT(cond);
4234 if (operand.IsImmediateZero()) {
4235 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004236 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004237 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
4238 if ((operand.GetAddrMode() == Offset) &&
4239 ((!rn.IsPC()) || AllowUnpredictable())) {
4240 EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4241 AdvanceIT();
4242 return;
4243 }
4244 } else {
4245 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
4246 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4247 ((!rn.IsPC()) || AllowUnpredictable())) {
4248 EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4249 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4250 return;
4251 }
4252 }
4253 }
4254 Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4255}
4256
4257void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004258 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004259 CheckIT(cond);
4260 if (operand.IsImmediateZero()) {
4261 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004262 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004263 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
4264 if ((operand.GetAddrMode() == Offset) &&
4265 ((!rn.IsPC()) || AllowUnpredictable())) {
4266 EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4267 AdvanceIT();
4268 return;
4269 }
4270 } else {
4271 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
4272 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4273 ((!rn.IsPC()) || AllowUnpredictable())) {
4274 EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4275 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4276 return;
4277 }
4278 }
4279 }
4280 Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4281}
4282
4283void Assembler::ldaexd(Condition cond,
4284 Register rt,
4285 Register rt2,
4286 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004287 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004288 CheckIT(cond);
4289 if (operand.IsImmediateZero()) {
4290 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004291 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004292 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
4293 if ((operand.GetAddrMode() == Offset) &&
4294 ((!rn.IsPC()) || AllowUnpredictable())) {
4295 EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4296 (rn.GetCode() << 16));
4297 AdvanceIT();
4298 return;
4299 }
4300 } else {
4301 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4302 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
4303 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4304 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
4305 AllowUnpredictable())) {
4306 EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4307 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4308 return;
4309 }
4310 }
4311 }
4312 Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4313}
4314
4315void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004316 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004317 CheckIT(cond);
4318 if (operand.IsImmediateZero()) {
4319 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004320 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004321 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4322 if ((operand.GetAddrMode() == Offset) &&
4323 ((!rn.IsPC()) || AllowUnpredictable())) {
4324 EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4325 AdvanceIT();
4326 return;
4327 }
4328 } else {
4329 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4330 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4331 ((!rn.IsPC()) || AllowUnpredictable())) {
4332 EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4333 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4334 return;
4335 }
4336 }
4337 }
4338 Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4339}
4340
4341void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004342 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004343 CheckIT(cond);
4344 if (operand.IsImmediateZero()) {
4345 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004346 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004347 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
4348 if ((operand.GetAddrMode() == Offset) &&
4349 ((!rn.IsPC()) || AllowUnpredictable())) {
4350 EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4351 AdvanceIT();
4352 return;
4353 }
4354 } else {
4355 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
4356 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4357 ((!rn.IsPC()) || AllowUnpredictable())) {
4358 EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4359 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4360 return;
4361 }
4362 }
4363 }
4364 Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4365}
4366
4367void Assembler::ldm(Condition cond,
4368 EncodingSize size,
4369 Register rn,
4370 WriteBack write_back,
4371 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004372 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004373 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004374 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004375 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4376 if (!size.IsWide() && rn.IsLow() &&
4377 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4378 write_back.DoesWriteBack()) &&
4379 ((registers.GetList() & ~0xff) == 0)) {
4380 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4381 GetRegisterListEncoding(registers, 0, 8));
4382 AdvanceIT();
4383 return;
4384 }
4385 // LDM{<c>}{<q>} SP!, <registers> ; T1
4386 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4387 ((registers.GetList() & ~0x80ff) == 0)) {
4388 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4389 GetRegisterListEncoding(registers, 0, 8));
4390 AdvanceIT();
4391 return;
4392 }
4393 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
4394 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
4395 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4396 (write_back.GetWriteBackUint32() << 21) |
4397 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4398 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4399 GetRegisterListEncoding(registers, 0, 13));
4400 AdvanceIT();
4401 return;
4402 }
4403 } else {
4404 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
4405 if (cond.IsNotNever()) {
4406 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4407 (write_back.GetWriteBackUint32() << 21) |
4408 GetRegisterListEncoding(registers, 0, 16));
4409 return;
4410 }
4411 }
4412 Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4413}
4414
4415void Assembler::ldmda(Condition cond,
4416 Register rn,
4417 WriteBack write_back,
4418 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004419 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004420 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004421 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004422 // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4423 if (cond.IsNotNever()) {
4424 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4425 (write_back.GetWriteBackUint32() << 21) |
4426 GetRegisterListEncoding(registers, 0, 16));
4427 return;
4428 }
4429 }
4430 Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4431}
4432
4433void Assembler::ldmdb(Condition cond,
4434 Register rn,
4435 WriteBack write_back,
4436 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004437 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004438 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004439 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004440 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
4441 if (((registers.GetList() & ~0xdfff) == 0)) {
4442 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4443 (write_back.GetWriteBackUint32() << 21) |
4444 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4445 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4446 GetRegisterListEncoding(registers, 0, 13));
4447 AdvanceIT();
4448 return;
4449 }
4450 } else {
4451 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4452 if (cond.IsNotNever()) {
4453 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4454 (write_back.GetWriteBackUint32() << 21) |
4455 GetRegisterListEncoding(registers, 0, 16));
4456 return;
4457 }
4458 }
4459 Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4460}
4461
4462void Assembler::ldmea(Condition cond,
4463 Register rn,
4464 WriteBack write_back,
4465 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004466 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004467 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004468 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004469 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
4470 if (((registers.GetList() & ~0xdfff) == 0)) {
4471 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4472 (write_back.GetWriteBackUint32() << 21) |
4473 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4474 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4475 GetRegisterListEncoding(registers, 0, 13));
4476 AdvanceIT();
4477 return;
4478 }
4479 } else {
4480 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4481 if (cond.IsNotNever()) {
4482 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4483 (write_back.GetWriteBackUint32() << 21) |
4484 GetRegisterListEncoding(registers, 0, 16));
4485 return;
4486 }
4487 }
4488 Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4489}
4490
4491void Assembler::ldmed(Condition cond,
4492 Register rn,
4493 WriteBack write_back,
4494 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004495 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004496 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004497 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004498 // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
4499 if (cond.IsNotNever()) {
4500 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4501 (write_back.GetWriteBackUint32() << 21) |
4502 GetRegisterListEncoding(registers, 0, 16));
4503 return;
4504 }
4505 }
4506 Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4507}
4508
4509void Assembler::ldmfa(Condition cond,
4510 Register rn,
4511 WriteBack write_back,
4512 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004513 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004514 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004515 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004516 // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
4517 if (cond.IsNotNever()) {
4518 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4519 (write_back.GetWriteBackUint32() << 21) |
4520 GetRegisterListEncoding(registers, 0, 16));
4521 return;
4522 }
4523 }
4524 Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4525}
4526
4527void Assembler::ldmfd(Condition cond,
4528 EncodingSize size,
4529 Register rn,
4530 WriteBack write_back,
4531 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004532 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004533 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004534 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004535 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4536 if (!size.IsWide() && rn.IsLow() &&
4537 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4538 write_back.DoesWriteBack()) &&
4539 ((registers.GetList() & ~0xff) == 0)) {
4540 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4541 GetRegisterListEncoding(registers, 0, 8));
4542 AdvanceIT();
4543 return;
4544 }
4545 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
4546 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
4547 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4548 (write_back.GetWriteBackUint32() << 21) |
4549 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4550 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4551 GetRegisterListEncoding(registers, 0, 13));
4552 AdvanceIT();
4553 return;
4554 }
4555 } else {
4556 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
4557 if (cond.IsNotNever()) {
4558 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4559 (write_back.GetWriteBackUint32() << 21) |
4560 GetRegisterListEncoding(registers, 0, 16));
4561 return;
4562 }
4563 }
4564 Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4565}
4566
4567void Assembler::ldmib(Condition cond,
4568 Register rn,
4569 WriteBack write_back,
4570 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004571 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004572 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004573 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004574 // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
4575 if (cond.IsNotNever()) {
4576 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4577 (write_back.GetWriteBackUint32() << 21) |
4578 GetRegisterListEncoding(registers, 0, 16));
4579 return;
4580 }
4581 }
4582 Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4583}
4584
4585void Assembler::ldr(Condition cond,
4586 EncodingSize size,
4587 Register rt,
4588 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004589 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004590 CheckIT(cond);
4591 if (operand.IsImmediate()) {
4592 Register rn = operand.GetBaseRegister();
4593 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004594 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004595 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4596 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4597 (offset <= 124) && ((offset % 4) == 0) &&
4598 (operand.GetAddrMode() == Offset)) {
4599 int32_t offset_ = offset >> 2;
4600 EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
4601 ((offset_ & 0x1f) << 6));
4602 AdvanceIT();
4603 return;
4604 }
4605 // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
4606 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
4607 ((offset % 4) == 0) && rn.Is(sp) &&
4608 (operand.GetAddrMode() == Offset)) {
4609 int32_t offset_ = offset >> 2;
4610 EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
4611 AdvanceIT();
4612 return;
4613 }
4614 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
4615 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
4616 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
4617 EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4618 (offset & 0xfff));
4619 AdvanceIT();
4620 return;
4621 }
4622 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
4623 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
4624 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
4625 EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4626 (-offset & 0xff));
4627 AdvanceIT();
4628 return;
4629 }
4630 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
4631 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4632 (operand.GetAddrMode() == PostIndex) &&
4633 ((rn.GetCode() & 0xf) != 0xf)) {
4634 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4635 uint32_t offset_ = abs(offset);
4636 EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4637 offset_ | (sign << 9));
4638 AdvanceIT();
4639 return;
4640 }
4641 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
4642 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4643 (operand.GetAddrMode() == PreIndex) &&
4644 ((rn.GetCode() & 0xf) != 0xf)) {
4645 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4646 uint32_t offset_ = abs(offset);
4647 EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4648 offset_ | (sign << 9));
4649 AdvanceIT();
4650 return;
4651 }
4652 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
4653 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
4654 rn.Is(pc) && (operand.GetAddrMode() == Offset)) {
4655 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4656 uint32_t offset_ = abs(offset);
4657 EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
4658 AdvanceIT();
4659 return;
4660 }
4661 } else {
4662 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
4663 if ((offset >= -4095) && (offset <= 4095) &&
4664 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4665 ((rn.GetCode() & 0xf) != 0xf)) {
4666 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4667 uint32_t offset_ = abs(offset);
4668 EmitA32(0x05100000U | (cond.GetCondition() << 28) |
4669 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4670 (sign << 23));
4671 return;
4672 }
4673 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
4674 if ((offset >= -4095) && (offset <= 4095) &&
4675 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
4676 ((rn.GetCode() & 0xf) != 0xf)) {
4677 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4678 uint32_t offset_ = abs(offset);
4679 EmitA32(0x04100000U | (cond.GetCondition() << 28) |
4680 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4681 (sign << 23));
4682 return;
4683 }
4684 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
4685 if ((offset >= -4095) && (offset <= 4095) &&
4686 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
4687 ((rn.GetCode() & 0xf) != 0xf)) {
4688 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4689 uint32_t offset_ = abs(offset);
4690 EmitA32(0x05300000U | (cond.GetCondition() << 28) |
4691 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4692 (sign << 23));
4693 return;
4694 }
4695 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
4696 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
4697 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
4698 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4699 uint32_t offset_ = abs(offset);
4700 EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
4701 (rt.GetCode() << 12) | offset_ | (sign << 23));
4702 return;
4703 }
4704 }
4705 }
4706 if (operand.IsPlainRegister()) {
4707 Register rn = operand.GetBaseRegister();
4708 Sign sign = operand.GetSign();
4709 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004710 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004711 // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
4712 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
4713 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
4714 EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
4715 (rm.GetCode() << 6));
4716 AdvanceIT();
4717 return;
4718 }
4719 }
4720 }
4721 if (operand.IsShiftedRegister()) {
4722 Register rn = operand.GetBaseRegister();
4723 Sign sign = operand.GetSign();
4724 Register rm = operand.GetOffsetRegister();
4725 Shift shift = operand.GetShift();
4726 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004727 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004728 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
4729 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
4730 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
4731 EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4732 rm.GetCode() | (amount << 4));
4733 AdvanceIT();
4734 return;
4735 }
4736 } else {
4737 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
4738 if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
4739 cond.IsNotNever()) {
4740 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4741 uint32_t shift_ = TypeEncodingValue(shift);
4742 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4743 EmitA32(0x07100000U | (cond.GetCondition() << 28) |
4744 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4745 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4746 return;
4747 }
4748 // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
4749 if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
4750 cond.IsNotNever()) {
4751 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4752 uint32_t shift_ = TypeEncodingValue(shift);
4753 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4754 EmitA32(0x06100000U | (cond.GetCondition() << 28) |
4755 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4756 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4757 return;
4758 }
4759 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
4760 if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
4761 cond.IsNotNever()) {
4762 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
4763 uint32_t shift_ = TypeEncodingValue(shift);
4764 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
4765 EmitA32(0x07300000U | (cond.GetCondition() << 28) |
4766 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4767 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
4768 return;
4769 }
4770 }
4771 }
4772 Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
4773}
4774
4775void Assembler::ldr(Condition cond,
4776 EncodingSize size,
4777 Register rt,
4778 Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004779 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004780 CheckIT(cond);
4781 Label::Offset offset =
4782 label->IsBound()
4783 ? label->GetLocation() -
4784 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
4785 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004786 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004787 // LDR{<c>}{<q>} <Rt>, <label> ; T1
4788 if (!size.IsWide() && rt.IsLow() &&
4789 ((label->IsBound() && (offset >= 0) && (offset <= 1020) &&
4790 ((offset & 0x3) == 0)) ||
4791 (!label->IsBound() && size.IsNarrow()))) {
4792 static class EmitOp : public Label::LabelEmitOperator {
4793 public:
4794 EmitOp() : Label::LabelEmitOperator(0, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00004795 virtual uint32_t Encode(uint32_t instr,
4796 Label::Offset pc,
4797 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004798 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4799 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
4800 ((offset & 0x3) == 0));
4801 const int32_t target = offset >> 2;
4802 return instr | (target & 0xff);
4803 }
4804 } immop;
4805 EmitT32_16(Link(0x4800 | (rt.GetCode() << 8), label, immop));
4806 AdvanceIT();
4807 return;
4808 }
4809 // LDR{<c>}{<q>} <Rt>, <label> ; T2
4810 if (!size.IsNarrow() &&
4811 ((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
4812 !label->IsBound())) {
4813 static class EmitOp : public Label::LabelEmitOperator {
4814 public:
4815 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00004816 virtual uint32_t Encode(uint32_t instr,
4817 Label::Offset pc,
4818 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004819 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4820 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
4821 uint32_t U = (offset >= 0) && !label->IsMinusZero();
4822 int32_t target = abs(offset) | (U << 12);
4823 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
4824 }
4825 } immop;
4826 EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12), label, immop));
4827 AdvanceIT();
4828 return;
4829 }
4830 } else {
4831 // LDR{<c>}{<q>} <Rt>, <label> ; A1
4832 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
4833 !label->IsBound()) &&
4834 cond.IsNotNever()) {
4835 static class EmitOp : public Label::LabelEmitOperator {
4836 public:
4837 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00004838 virtual uint32_t Encode(uint32_t instr,
4839 Label::Offset pc,
4840 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004841 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
4842 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
4843 uint32_t U = (offset >= 0) && !label->IsMinusZero();
4844 int32_t target = abs(offset) | (U << 12);
4845 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
4846 }
4847 } immop;
4848 EmitA32(
4849 Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
4850 label,
4851 immop));
4852 return;
4853 }
4854 }
4855 Delegate(kLdr, &Assembler::ldr, cond, size, rt, label);
4856}
4857
4858void Assembler::ldrb(Condition cond,
4859 EncodingSize size,
4860 Register rt,
4861 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004863 CheckIT(cond);
4864 if (operand.IsImmediate()) {
4865 Register rn = operand.GetBaseRegister();
4866 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004867 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004868 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4869 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
4870 (offset <= 31) && (operand.GetAddrMode() == Offset)) {
4871 EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
4872 ((offset & 0x1f) << 6));
4873 AdvanceIT();
4874 return;
4875 }
4876 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
4877 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
4878 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
4879 !rt.Is(pc)) {
4880 EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4881 (offset & 0xfff));
4882 AdvanceIT();
4883 return;
4884 }
4885 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
4886 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
4887 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
4888 !rt.Is(pc)) {
4889 EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4890 (-offset & 0xff));
4891 AdvanceIT();
4892 return;
4893 }
4894 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
4895 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4896 (operand.GetAddrMode() == PostIndex) &&
4897 ((rn.GetCode() & 0xf) != 0xf)) {
4898 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4899 uint32_t offset_ = abs(offset);
4900 EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4901 offset_ | (sign << 9));
4902 AdvanceIT();
4903 return;
4904 }
4905 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
4906 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
4907 (operand.GetAddrMode() == PreIndex) &&
4908 ((rn.GetCode() & 0xf) != 0xf)) {
4909 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4910 uint32_t offset_ = abs(offset);
4911 EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4912 offset_ | (sign << 9));
4913 AdvanceIT();
4914 return;
4915 }
4916 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
4917 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
4918 rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
4919 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4920 uint32_t offset_ = abs(offset);
4921 EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
4922 AdvanceIT();
4923 return;
4924 }
4925 } else {
4926 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
4927 if ((offset >= -4095) && (offset <= 4095) &&
4928 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
4929 ((rn.GetCode() & 0xf) != 0xf)) {
4930 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4931 uint32_t offset_ = abs(offset);
4932 EmitA32(0x05500000U | (cond.GetCondition() << 28) |
4933 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4934 (sign << 23));
4935 return;
4936 }
4937 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
4938 if ((offset >= -4095) && (offset <= 4095) &&
4939 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
4940 ((rn.GetCode() & 0xf) != 0xf)) {
4941 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4942 uint32_t offset_ = abs(offset);
4943 EmitA32(0x04500000U | (cond.GetCondition() << 28) |
4944 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4945 (sign << 23));
4946 return;
4947 }
4948 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
4949 if ((offset >= -4095) && (offset <= 4095) &&
4950 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
4951 ((rn.GetCode() & 0xf) != 0xf)) {
4952 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4953 uint32_t offset_ = abs(offset);
4954 EmitA32(0x05700000U | (cond.GetCondition() << 28) |
4955 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
4956 (sign << 23));
4957 return;
4958 }
4959 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
4960 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
4961 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
4962 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
4963 uint32_t offset_ = abs(offset);
4964 EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
4965 (rt.GetCode() << 12) | offset_ | (sign << 23));
4966 return;
4967 }
4968 }
4969 }
4970 if (operand.IsPlainRegister()) {
4971 Register rn = operand.GetBaseRegister();
4972 Sign sign = operand.GetSign();
4973 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004974 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004975 // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
4976 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
4977 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
4978 EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
4979 (rm.GetCode() << 6));
4980 AdvanceIT();
4981 return;
4982 }
4983 }
4984 }
4985 if (operand.IsShiftedRegister()) {
4986 Register rn = operand.GetBaseRegister();
4987 Sign sign = operand.GetSign();
4988 Register rm = operand.GetOffsetRegister();
4989 Shift shift = operand.GetShift();
4990 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004991 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004992 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
4993 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
4994 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
4995 !rt.Is(pc)) {
4996 EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
4997 rm.GetCode() | (amount << 4));
4998 AdvanceIT();
4999 return;
5000 }
5001 } else {
5002 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
5003 if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
5004 cond.IsNotNever()) {
5005 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5006 uint32_t shift_ = TypeEncodingValue(shift);
5007 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5008 EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5009 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5010 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5011 return;
5012 }
5013 // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
5014 if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
5015 cond.IsNotNever()) {
5016 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5017 uint32_t shift_ = TypeEncodingValue(shift);
5018 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5019 EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5020 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5021 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5022 return;
5023 }
5024 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
5025 if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
5026 cond.IsNotNever()) {
5027 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5028 uint32_t shift_ = TypeEncodingValue(shift);
5029 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5030 EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5031 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5032 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5033 return;
5034 }
5035 }
5036 }
5037 Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5038}
5039
5040void Assembler::ldrb(Condition cond, Register rt, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005041 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005042 CheckIT(cond);
5043 Label::Offset offset =
5044 label->IsBound()
5045 ? label->GetLocation() -
5046 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5047 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005048 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005049 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5050 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5051 !label->IsBound()) &&
5052 !rt.Is(pc)) {
5053 static class EmitOp : public Label::LabelEmitOperator {
5054 public:
5055 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005056 virtual uint32_t Encode(uint32_t instr,
5057 Label::Offset pc,
5058 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005059 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5060 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5061 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5062 int32_t target = abs(offset) | (U << 12);
5063 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5064 }
5065 } immop;
5066 EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12), label, immop));
5067 AdvanceIT();
5068 return;
5069 }
5070 } else {
5071 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5072 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5073 !label->IsBound()) &&
5074 cond.IsNotNever()) {
5075 static class EmitOp : public Label::LabelEmitOperator {
5076 public:
5077 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005078 virtual uint32_t Encode(uint32_t instr,
5079 Label::Offset pc,
5080 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005081 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5082 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5083 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5084 int32_t target = abs(offset) | (U << 12);
5085 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5086 }
5087 } immop;
5088 EmitA32(
5089 Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5090 label,
5091 immop));
5092 return;
5093 }
5094 }
5095 Delegate(kLdrb, &Assembler::ldrb, cond, rt, label);
5096}
5097
5098void Assembler::ldrd(Condition cond,
5099 Register rt,
5100 Register rt2,
5101 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005102 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005103 CheckIT(cond);
5104 if (operand.IsImmediate()) {
5105 Register rn = operand.GetBaseRegister();
5106 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005107 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005108 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5109 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5110 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
5111 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5112 uint32_t offset_ = abs(offset) >> 2;
5113 EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5114 (rn.GetCode() << 16) | offset_ | (sign << 23));
5115 AdvanceIT();
5116 return;
5117 }
5118 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5119 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5120 (operand.GetAddrMode() == PostIndex) &&
5121 ((rn.GetCode() & 0xf) != 0xf)) {
5122 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5123 uint32_t offset_ = abs(offset) >> 2;
5124 EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5125 (rn.GetCode() << 16) | offset_ | (sign << 23));
5126 AdvanceIT();
5127 return;
5128 }
5129 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5130 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
5131 (operand.GetAddrMode() == PreIndex) &&
5132 ((rn.GetCode() & 0xf) != 0xf)) {
5133 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5134 uint32_t offset_ = abs(offset) >> 2;
5135 EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5136 (rn.GetCode() << 16) | offset_ | (sign << 23));
5137 AdvanceIT();
5138 return;
5139 }
5140 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5141 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5142 (operand.GetAddrMode() == Offset)) {
5143 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5144 uint32_t offset_ = abs(offset);
5145 EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5146 offset_ | (sign << 23));
5147 AdvanceIT();
5148 return;
5149 }
5150 } else {
5151 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5152 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5153 (offset >= -255) && (offset <= 255) &&
5154 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5155 ((rn.GetCode() & 0xf) != 0xf) &&
5156 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5157 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5158 uint32_t offset_ = abs(offset);
5159 EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5160 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5161 ((offset_ & 0xf0) << 4) | (sign << 23));
5162 return;
5163 }
5164 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5165 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5166 (offset >= -255) && (offset <= 255) &&
5167 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5168 ((rn.GetCode() & 0xf) != 0xf) &&
5169 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5170 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5171 uint32_t offset_ = abs(offset);
5172 EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5173 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5174 ((offset_ & 0xf0) << 4) | (sign << 23));
5175 return;
5176 }
5177 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5178 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5179 (offset >= -255) && (offset <= 255) &&
5180 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5181 ((rn.GetCode() & 0xf) != 0xf) &&
5182 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5183 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5184 uint32_t offset_ = abs(offset);
5185 EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5186 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5187 ((offset_ & 0xf0) << 4) | (sign << 23));
5188 return;
5189 }
5190 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5191 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5192 (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5193 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5194 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5195 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5196 uint32_t offset_ = abs(offset);
5197 EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5198 (rt.GetCode() << 12) | (offset_ & 0xf) |
5199 ((offset_ & 0xf0) << 4) | (sign << 23));
5200 return;
5201 }
5202 }
5203 }
5204 if (operand.IsPlainRegister()) {
5205 Register rn = operand.GetBaseRegister();
5206 Sign sign = operand.GetSign();
5207 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005208 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005209 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5210 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5211 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5212 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5213 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5214 EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5215 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5216 (sign_ << 23));
5217 return;
5218 }
5219 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5220 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5221 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5222 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5223 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5224 EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5225 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5226 (sign_ << 23));
5227 return;
5228 }
5229 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5230 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5231 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5232 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5233 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5234 EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5235 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5236 (sign_ << 23));
5237 return;
5238 }
5239 }
5240 }
5241 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5242}
5243
5244void Assembler::ldrd(Condition cond, Register rt, Register rt2, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005245 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005246 CheckIT(cond);
5247 Label::Offset offset =
5248 label->IsBound()
5249 ? label->GetLocation() -
5250 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5251 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005252 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005253 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5254 if (((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
5255 ((offset & 0x3) == 0)) ||
5256 !label->IsBound())) {
5257 static class EmitOp : public Label::LabelEmitOperator {
5258 public:
5259 EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005260 virtual uint32_t Encode(uint32_t instr,
5261 Label::Offset pc,
5262 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005263 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5264 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5265 ((offset & 0x3) == 0));
5266 int32_t target = offset >> 2;
5267 uint32_t U = (target >= 0) && !label->IsMinusZero();
5268 target = abs(target) | (U << 8);
5269 return instr | (target & 0xff) | ((target & 0x100) << 15);
5270 }
5271 } immop;
5272 EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
5273 label,
5274 immop));
5275 AdvanceIT();
5276 return;
5277 }
5278 } else {
5279 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5280 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5281 ((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5282 !label->IsBound()) &&
5283 cond.IsNotNever() &&
5284 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
5285 static class EmitOp : public Label::LabelEmitOperator {
5286 public:
5287 EmitOp() : Label::LabelEmitOperator(-255, 255) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005288 virtual uint32_t Encode(uint32_t instr,
5289 Label::Offset pc,
5290 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005291 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5292 VIXL_ASSERT((offset >= -255) && (offset <= 255));
5293 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5294 int32_t target = abs(offset) | (U << 8);
5295 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5296 ((target & 0x100) << 15);
5297 }
5298 } immop;
5299 EmitA32(
5300 Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5301 label,
5302 immop));
5303 return;
5304 }
5305 }
5306 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, label);
5307}
5308
5309void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005310 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005311 CheckIT(cond);
5312 if (operand.IsImmediate()) {
5313 Register rn = operand.GetBaseRegister();
5314 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005315 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005316 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5317 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
5318 (operand.GetAddrMode() == Offset)) {
5319 int32_t offset_ = offset >> 2;
5320 EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5321 (offset_ & 0xff));
5322 AdvanceIT();
5323 return;
5324 }
5325 } else {
5326 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
5327 if ((offset == 0) && (operand.GetAddrMode() == Offset) &&
5328 cond.IsNotNever()) {
5329 EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5330 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5331 return;
5332 }
5333 }
5334 }
5335 Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5336}
5337
5338void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005339 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005340 CheckIT(cond);
5341 if (operand.IsImmediateZero()) {
5342 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005343 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005344 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
5345 if ((operand.GetAddrMode() == Offset) &&
5346 ((!rn.IsPC()) || AllowUnpredictable())) {
5347 EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5348 AdvanceIT();
5349 return;
5350 }
5351 } else {
5352 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
5353 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5354 ((!rn.IsPC()) || AllowUnpredictable())) {
5355 EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5356 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5357 return;
5358 }
5359 }
5360 }
5361 Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5362}
5363
5364void Assembler::ldrexd(Condition cond,
5365 Register rt,
5366 Register rt2,
5367 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005369 CheckIT(cond);
5370 if (operand.IsImmediateZero()) {
5371 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005372 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005373 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
5374 if ((operand.GetAddrMode() == Offset) &&
5375 ((!rn.IsPC()) || AllowUnpredictable())) {
5376 EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5377 (rn.GetCode() << 16));
5378 AdvanceIT();
5379 return;
5380 }
5381 } else {
5382 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5383 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5384 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5385 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
5386 AllowUnpredictable())) {
5387 EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5388 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5389 return;
5390 }
5391 }
5392 }
5393 Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5394}
5395
5396void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005397 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005398 CheckIT(cond);
5399 if (operand.IsImmediateZero()) {
5400 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005401 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005402 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
5403 if ((operand.GetAddrMode() == Offset) &&
5404 ((!rn.IsPC()) || AllowUnpredictable())) {
5405 EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5406 AdvanceIT();
5407 return;
5408 }
5409 } else {
5410 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
5411 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5412 ((!rn.IsPC()) || AllowUnpredictable())) {
5413 EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5414 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5415 return;
5416 }
5417 }
5418 }
5419 Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5420}
5421
5422void Assembler::ldrh(Condition cond,
5423 EncodingSize size,
5424 Register rt,
5425 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005426 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005427 CheckIT(cond);
5428 if (operand.IsImmediate()) {
5429 Register rn = operand.GetBaseRegister();
5430 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005431 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005432 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5433 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
5434 (offset <= 62) && ((offset % 2) == 0) &&
5435 (operand.GetAddrMode() == Offset)) {
5436 int32_t offset_ = offset >> 1;
5437 EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5438 ((offset_ & 0x1f) << 6));
5439 AdvanceIT();
5440 return;
5441 }
5442 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5443 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5444 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5445 !rt.Is(pc)) {
5446 EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5447 (offset & 0xfff));
5448 AdvanceIT();
5449 return;
5450 }
5451 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5452 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5453 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5454 !rt.Is(pc)) {
5455 EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5456 (-offset & 0xff));
5457 AdvanceIT();
5458 return;
5459 }
5460 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5461 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5462 (operand.GetAddrMode() == PostIndex) &&
5463 ((rn.GetCode() & 0xf) != 0xf)) {
5464 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5465 uint32_t offset_ = abs(offset);
5466 EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5467 offset_ | (sign << 9));
5468 AdvanceIT();
5469 return;
5470 }
5471 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5472 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5473 (operand.GetAddrMode() == PreIndex) &&
5474 ((rn.GetCode() & 0xf) != 0xf)) {
5475 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5476 uint32_t offset_ = abs(offset);
5477 EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5478 offset_ | (sign << 9));
5479 AdvanceIT();
5480 return;
5481 }
5482 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5483 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5484 rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
5485 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5486 uint32_t offset_ = abs(offset);
5487 EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5488 AdvanceIT();
5489 return;
5490 }
5491 } else {
5492 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
5493 if ((offset >= -255) && (offset <= 255) &&
5494 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5495 ((rn.GetCode() & 0xf) != 0xf)) {
5496 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5497 uint32_t offset_ = abs(offset);
5498 EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
5499 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5500 ((offset_ & 0xf0) << 4) | (sign << 23));
5501 return;
5502 }
5503 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
5504 if ((offset >= -255) && (offset <= 255) &&
5505 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5506 ((rn.GetCode() & 0xf) != 0xf)) {
5507 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5508 uint32_t offset_ = abs(offset);
5509 EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
5510 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5511 ((offset_ & 0xf0) << 4) | (sign << 23));
5512 return;
5513 }
5514 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
5515 if ((offset >= -255) && (offset <= 255) &&
5516 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5517 ((rn.GetCode() & 0xf) != 0xf)) {
5518 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5519 uint32_t offset_ = abs(offset);
5520 EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
5521 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5522 ((offset_ & 0xf0) << 4) | (sign << 23));
5523 return;
5524 }
5525 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5526 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5527 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5528 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5529 uint32_t offset_ = abs(offset);
5530 EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
5531 (rt.GetCode() << 12) | (offset_ & 0xf) |
5532 ((offset_ & 0xf0) << 4) | (sign << 23));
5533 return;
5534 }
5535 }
5536 }
5537 if (operand.IsPlainRegister()) {
5538 Register rn = operand.GetBaseRegister();
5539 Sign sign = operand.GetSign();
5540 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005541 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005542 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5543 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5544 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
5545 EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
5546 (rm.GetCode() << 6));
5547 AdvanceIT();
5548 return;
5549 }
5550 } else {
5551 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5552 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5553 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5554 EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
5555 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5556 (sign_ << 23));
5557 return;
5558 }
5559 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5560 if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
5561 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5562 EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
5563 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5564 (sign_ << 23));
5565 return;
5566 }
5567 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5568 if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
5569 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5570 EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
5571 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5572 (sign_ << 23));
5573 return;
5574 }
5575 }
5576 }
5577 if (operand.IsShiftedRegister()) {
5578 Register rn = operand.GetBaseRegister();
5579 Sign sign = operand.GetSign();
5580 Register rm = operand.GetOffsetRegister();
5581 Shift shift = operand.GetShift();
5582 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005583 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005584 // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5585 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5586 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5587 !rt.Is(pc)) {
5588 EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5589 rm.GetCode() | (amount << 4));
5590 AdvanceIT();
5591 return;
5592 }
5593 }
5594 }
5595 Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
5596}
5597
5598void Assembler::ldrh(Condition cond, Register rt, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005599 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005600 CheckIT(cond);
5601 Label::Offset offset =
5602 label->IsBound()
5603 ? label->GetLocation() -
5604 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5605 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005606 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005607 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
5608 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5609 !label->IsBound()) &&
5610 !rt.Is(pc)) {
5611 static class EmitOp : public Label::LabelEmitOperator {
5612 public:
5613 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005614 virtual uint32_t Encode(uint32_t instr,
5615 Label::Offset pc,
5616 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005617 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5618 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5619 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5620 int32_t target = abs(offset) | (U << 12);
5621 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5622 }
5623 } immop;
5624 EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12), label, immop));
5625 AdvanceIT();
5626 return;
5627 }
5628 } else {
5629 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
5630 if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5631 !label->IsBound()) &&
5632 cond.IsNotNever()) {
5633 static class EmitOp : public Label::LabelEmitOperator {
5634 public:
5635 EmitOp() : Label::LabelEmitOperator(-255, 255) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005636 virtual uint32_t Encode(uint32_t instr,
5637 Label::Offset pc,
5638 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005639 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5640 VIXL_ASSERT((offset >= -255) && (offset <= 255));
5641 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5642 int32_t target = abs(offset) | (U << 8);
5643 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5644 ((target & 0x100) << 15);
5645 }
5646 } immop;
5647 EmitA32(
5648 Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5649 label,
5650 immop));
5651 return;
5652 }
5653 }
5654 Delegate(kLdrh, &Assembler::ldrh, cond, rt, label);
5655}
5656
5657void Assembler::ldrsb(Condition cond,
5658 EncodingSize size,
5659 Register rt,
5660 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005661 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005662 CheckIT(cond);
5663 if (operand.IsImmediate()) {
5664 Register rn = operand.GetBaseRegister();
5665 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005666 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005667 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5668 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5669 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5670 !rt.Is(pc)) {
5671 EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5672 (offset & 0xfff));
5673 AdvanceIT();
5674 return;
5675 }
5676 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
5677 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5678 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5679 !rt.Is(pc)) {
5680 EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5681 (-offset & 0xff));
5682 AdvanceIT();
5683 return;
5684 }
5685 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
5686 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5687 (operand.GetAddrMode() == PostIndex) &&
5688 ((rn.GetCode() & 0xf) != 0xf)) {
5689 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5690 uint32_t offset_ = abs(offset);
5691 EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5692 offset_ | (sign << 9));
5693 AdvanceIT();
5694 return;
5695 }
5696 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
5697 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5698 (operand.GetAddrMode() == PreIndex) &&
5699 ((rn.GetCode() & 0xf) != 0xf)) {
5700 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5701 uint32_t offset_ = abs(offset);
5702 EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5703 offset_ | (sign << 9));
5704 AdvanceIT();
5705 return;
5706 }
5707 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5708 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5709 rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
5710 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5711 uint32_t offset_ = abs(offset);
5712 EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5713 AdvanceIT();
5714 return;
5715 }
5716 } else {
5717 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
5718 if ((offset >= -255) && (offset <= 255) &&
5719 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5720 ((rn.GetCode() & 0xf) != 0xf)) {
5721 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5722 uint32_t offset_ = abs(offset);
5723 EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
5724 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5725 ((offset_ & 0xf0) << 4) | (sign << 23));
5726 return;
5727 }
5728 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
5729 if ((offset >= -255) && (offset <= 255) &&
5730 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5731 ((rn.GetCode() & 0xf) != 0xf)) {
5732 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5733 uint32_t offset_ = abs(offset);
5734 EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
5735 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5736 ((offset_ & 0xf0) << 4) | (sign << 23));
5737 return;
5738 }
5739 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
5740 if ((offset >= -255) && (offset <= 255) &&
5741 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5742 ((rn.GetCode() & 0xf) != 0xf)) {
5743 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5744 uint32_t offset_ = abs(offset);
5745 EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
5746 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5747 ((offset_ & 0xf0) << 4) | (sign << 23));
5748 return;
5749 }
5750 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5751 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5752 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5753 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5754 uint32_t offset_ = abs(offset);
5755 EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
5756 (rt.GetCode() << 12) | (offset_ & 0xf) |
5757 ((offset_ & 0xf0) << 4) | (sign << 23));
5758 return;
5759 }
5760 }
5761 }
5762 if (operand.IsPlainRegister()) {
5763 Register rn = operand.GetBaseRegister();
5764 Sign sign = operand.GetSign();
5765 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005766 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005767 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5768 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5769 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
5770 EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
5771 (rm.GetCode() << 6));
5772 AdvanceIT();
5773 return;
5774 }
5775 } else {
5776 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
5777 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5778 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5779 EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
5780 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5781 (sign_ << 23));
5782 return;
5783 }
5784 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
5785 if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
5786 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5787 EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
5788 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5789 (sign_ << 23));
5790 return;
5791 }
5792 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
5793 if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
5794 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5795 EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
5796 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5797 (sign_ << 23));
5798 return;
5799 }
5800 }
5801 }
5802 if (operand.IsShiftedRegister()) {
5803 Register rn = operand.GetBaseRegister();
5804 Sign sign = operand.GetSign();
5805 Register rm = operand.GetOffsetRegister();
5806 Shift shift = operand.GetShift();
5807 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005808 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005809 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5810 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
5811 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5812 !rt.Is(pc)) {
5813 EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5814 rm.GetCode() | (amount << 4));
5815 AdvanceIT();
5816 return;
5817 }
5818 }
5819 }
5820 Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
5821}
5822
5823void Assembler::ldrsb(Condition cond, Register rt, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005824 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005825 CheckIT(cond);
5826 Label::Offset offset =
5827 label->IsBound()
5828 ? label->GetLocation() -
5829 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5830 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005831 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005832 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
5833 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5834 !label->IsBound()) &&
5835 !rt.Is(pc)) {
5836 static class EmitOp : public Label::LabelEmitOperator {
5837 public:
5838 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005839 virtual uint32_t Encode(uint32_t instr,
5840 Label::Offset pc,
5841 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005842 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5843 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
5844 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5845 int32_t target = abs(offset) | (U << 12);
5846 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5847 }
5848 } immop;
5849 EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12), label, immop));
5850 AdvanceIT();
5851 return;
5852 }
5853 } else {
5854 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
5855 if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
5856 !label->IsBound()) &&
5857 cond.IsNotNever()) {
5858 static class EmitOp : public Label::LabelEmitOperator {
5859 public:
5860 EmitOp() : Label::LabelEmitOperator(-255, 255) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005861 virtual uint32_t Encode(uint32_t instr,
5862 Label::Offset pc,
5863 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005864 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
5865 VIXL_ASSERT((offset >= -255) && (offset <= 255));
5866 uint32_t U = (offset >= 0) && !label->IsMinusZero();
5867 int32_t target = abs(offset) | (U << 8);
5868 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5869 ((target & 0x100) << 15);
5870 }
5871 } immop;
5872 EmitA32(
5873 Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
5874 label,
5875 immop));
5876 return;
5877 }
5878 }
5879 Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, label);
5880}
5881
5882void Assembler::ldrsh(Condition cond,
5883 EncodingSize size,
5884 Register rt,
5885 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005886 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005887 CheckIT(cond);
5888 if (operand.IsImmediate()) {
5889 Register rn = operand.GetBaseRegister();
5890 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005891 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005892 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5893 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
5894 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5895 !rt.Is(pc)) {
5896 EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5897 (offset & 0xfff));
5898 AdvanceIT();
5899 return;
5900 }
5901 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
5902 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
5903 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
5904 !rt.Is(pc)) {
5905 EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5906 (-offset & 0xff));
5907 AdvanceIT();
5908 return;
5909 }
5910 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
5911 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5912 (operand.GetAddrMode() == PostIndex) &&
5913 ((rn.GetCode() & 0xf) != 0xf)) {
5914 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5915 uint32_t offset_ = abs(offset);
5916 EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5917 offset_ | (sign << 9));
5918 AdvanceIT();
5919 return;
5920 }
5921 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
5922 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
5923 (operand.GetAddrMode() == PreIndex) &&
5924 ((rn.GetCode() & 0xf) != 0xf)) {
5925 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5926 uint32_t offset_ = abs(offset);
5927 EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5928 offset_ | (sign << 9));
5929 AdvanceIT();
5930 return;
5931 }
5932 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5933 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
5934 rn.Is(pc) && (operand.GetAddrMode() == Offset) && !rt.Is(pc)) {
5935 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5936 uint32_t offset_ = abs(offset);
5937 EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5938 AdvanceIT();
5939 return;
5940 }
5941 } else {
5942 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
5943 if ((offset >= -255) && (offset <= 255) &&
5944 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
5945 ((rn.GetCode() & 0xf) != 0xf)) {
5946 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5947 uint32_t offset_ = abs(offset);
5948 EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
5949 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5950 ((offset_ & 0xf0) << 4) | (sign << 23));
5951 return;
5952 }
5953 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
5954 if ((offset >= -255) && (offset <= 255) &&
5955 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
5956 ((rn.GetCode() & 0xf) != 0xf)) {
5957 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5958 uint32_t offset_ = abs(offset);
5959 EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
5960 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5961 ((offset_ & 0xf0) << 4) | (sign << 23));
5962 return;
5963 }
5964 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
5965 if ((offset >= -255) && (offset <= 255) &&
5966 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
5967 ((rn.GetCode() & 0xf) != 0xf)) {
5968 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5969 uint32_t offset_ = abs(offset);
5970 EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
5971 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5972 ((offset_ & 0xf0) << 4) | (sign << 23));
5973 return;
5974 }
5975 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5976 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
5977 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
5978 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5979 uint32_t offset_ = abs(offset);
5980 EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
5981 (rt.GetCode() << 12) | (offset_ & 0xf) |
5982 ((offset_ & 0xf0) << 4) | (sign << 23));
5983 return;
5984 }
5985 }
5986 }
5987 if (operand.IsPlainRegister()) {
5988 Register rn = operand.GetBaseRegister();
5989 Sign sign = operand.GetSign();
5990 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005991 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005992 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5993 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
5994 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
5995 EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
5996 (rm.GetCode() << 6));
5997 AdvanceIT();
5998 return;
5999 }
6000 } else {
6001 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
6002 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
6003 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6004 EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6005 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6006 (sign_ << 23));
6007 return;
6008 }
6009 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
6010 if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
6011 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6012 EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6013 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6014 (sign_ << 23));
6015 return;
6016 }
6017 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
6018 if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
6019 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6020 EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6021 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6022 (sign_ << 23));
6023 return;
6024 }
6025 }
6026 }
6027 if (operand.IsShiftedRegister()) {
6028 Register rn = operand.GetBaseRegister();
6029 Sign sign = operand.GetSign();
6030 Register rm = operand.GetOffsetRegister();
6031 Shift shift = operand.GetShift();
6032 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006033 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006034 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6035 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
6036 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf) &&
6037 !rt.Is(pc)) {
6038 EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6039 rm.GetCode() | (amount << 4));
6040 AdvanceIT();
6041 return;
6042 }
6043 }
6044 }
6045 Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6046}
6047
6048void Assembler::ldrsh(Condition cond, Register rt, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006049 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006050 CheckIT(cond);
6051 Label::Offset offset =
6052 label->IsBound()
6053 ? label->GetLocation() -
6054 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6055 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006056 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006057 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6058 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6059 !label->IsBound()) &&
6060 !rt.Is(pc)) {
6061 static class EmitOp : public Label::LabelEmitOperator {
6062 public:
6063 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006064 virtual uint32_t Encode(uint32_t instr,
6065 Label::Offset pc,
6066 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006067 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
6068 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
6069 uint32_t U = (offset >= 0) && !label->IsMinusZero();
6070 int32_t target = abs(offset) | (U << 12);
6071 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6072 }
6073 } immop;
6074 EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12), label, immop));
6075 AdvanceIT();
6076 return;
6077 }
6078 } else {
6079 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6080 if (((label->IsBound() && (offset >= -255) && (offset <= 255)) ||
6081 !label->IsBound()) &&
6082 cond.IsNotNever()) {
6083 static class EmitOp : public Label::LabelEmitOperator {
6084 public:
6085 EmitOp() : Label::LabelEmitOperator(-255, 255) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006086 virtual uint32_t Encode(uint32_t instr,
6087 Label::Offset pc,
6088 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006089 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
6090 VIXL_ASSERT((offset >= -255) && (offset <= 255));
6091 uint32_t U = (offset >= 0) && !label->IsMinusZero();
6092 int32_t target = abs(offset) | (U << 8);
6093 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6094 ((target & 0x100) << 15);
6095 }
6096 } immop;
6097 EmitA32(
6098 Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
6099 label,
6100 immop));
6101 return;
6102 }
6103 }
6104 Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, label);
6105}
6106
6107void Assembler::lsl(Condition cond,
6108 EncodingSize size,
6109 Register rd,
6110 Register rm,
6111 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006112 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006113 CheckIT(cond);
6114 if (operand.IsImmediate()) {
6115 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006116 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006117 // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6118 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6119 (imm >= 1) && (imm <= 31)) {
6120 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6121 AdvanceIT();
6122 return;
6123 }
6124 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6125 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
6126 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6127 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6128 AdvanceIT();
6129 return;
6130 }
6131 } else {
6132 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6133 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6134 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6135 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6136 return;
6137 }
6138 }
6139 }
6140 if (operand.IsPlainRegister()) {
6141 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006142 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006143 // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6144 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6145 rs.IsLow()) {
6146 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6147 AdvanceIT();
6148 return;
6149 }
6150 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6151 if (!size.IsNarrow()) {
6152 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6153 rs.GetCode());
6154 AdvanceIT();
6155 return;
6156 }
6157 } else {
6158 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6159 if (cond.IsNotNever()) {
6160 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6161 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6162 return;
6163 }
6164 }
6165 }
6166 Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6167}
6168
6169void Assembler::lsls(Condition cond,
6170 EncodingSize size,
6171 Register rd,
6172 Register rm,
6173 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006174 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006175 CheckIT(cond);
6176 if (operand.IsImmediate()) {
6177 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006178 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006179 // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6180 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6181 (imm >= 1) && (imm <= 31)) {
6182 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6183 AdvanceIT();
6184 return;
6185 }
6186 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6187 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
6188 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6189 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6190 AdvanceIT();
6191 return;
6192 }
6193 } else {
6194 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6195 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6196 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6197 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6198 return;
6199 }
6200 }
6201 }
6202 if (operand.IsPlainRegister()) {
6203 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006204 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006205 // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6206 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6207 rs.IsLow()) {
6208 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6209 AdvanceIT();
6210 return;
6211 }
6212 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6213 if (!size.IsNarrow()) {
6214 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6215 rs.GetCode());
6216 AdvanceIT();
6217 return;
6218 }
6219 } else {
6220 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6221 if (cond.IsNotNever()) {
6222 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6223 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6224 return;
6225 }
6226 }
6227 }
6228 Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6229}
6230
6231void Assembler::lsr(Condition cond,
6232 EncodingSize size,
6233 Register rd,
6234 Register rm,
6235 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006236 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006237 CheckIT(cond);
6238 if (operand.IsImmediate()) {
6239 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006240 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006241 // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6242 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6243 (imm >= 1) && (imm <= 32)) {
6244 uint32_t amount_ = imm % 32;
6245 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6246 (amount_ << 6));
6247 AdvanceIT();
6248 return;
6249 }
6250 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6251 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
6252 uint32_t amount_ = imm % 32;
6253 EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6254 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6255 AdvanceIT();
6256 return;
6257 }
6258 } else {
6259 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6260 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6261 uint32_t amount_ = imm % 32;
6262 EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6263 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6264 return;
6265 }
6266 }
6267 }
6268 if (operand.IsPlainRegister()) {
6269 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006270 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006271 // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6272 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6273 rs.IsLow()) {
6274 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6275 AdvanceIT();
6276 return;
6277 }
6278 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6279 if (!size.IsNarrow()) {
6280 EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6281 rs.GetCode());
6282 AdvanceIT();
6283 return;
6284 }
6285 } else {
6286 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6287 if (cond.IsNotNever()) {
6288 EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6289 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6290 return;
6291 }
6292 }
6293 }
6294 Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6295}
6296
6297void Assembler::lsrs(Condition cond,
6298 EncodingSize size,
6299 Register rd,
6300 Register rm,
6301 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006302 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006303 CheckIT(cond);
6304 if (operand.IsImmediate()) {
6305 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006306 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006307 // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6308 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6309 (imm >= 1) && (imm <= 32)) {
6310 uint32_t amount_ = imm % 32;
6311 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6312 (amount_ << 6));
6313 AdvanceIT();
6314 return;
6315 }
6316 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
6317 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) {
6318 uint32_t amount_ = imm % 32;
6319 EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6320 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6321 AdvanceIT();
6322 return;
6323 }
6324 } else {
6325 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6326 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6327 uint32_t amount_ = imm % 32;
6328 EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6329 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6330 return;
6331 }
6332 }
6333 }
6334 if (operand.IsPlainRegister()) {
6335 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006336 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006337 // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6338 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6339 rs.IsLow()) {
6340 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6341 AdvanceIT();
6342 return;
6343 }
6344 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
6345 if (!size.IsNarrow()) {
6346 EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6347 rs.GetCode());
6348 AdvanceIT();
6349 return;
6350 }
6351 } else {
6352 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
6353 if (cond.IsNotNever()) {
6354 EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6355 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6356 return;
6357 }
6358 }
6359 }
6360 Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6361}
6362
6363void Assembler::mla(
6364 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006365 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006366 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006367 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006368 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6369 if (!ra.Is(pc)) {
6370 EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6371 rm.GetCode() | (ra.GetCode() << 12));
6372 AdvanceIT();
6373 return;
6374 }
6375 } else {
6376 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6377 if (cond.IsNotNever()) {
6378 EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6379 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6380 return;
6381 }
6382 }
6383 Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
6384}
6385
6386void Assembler::mlas(
6387 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006388 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006389 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006390 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006391 // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6392 if (cond.IsNotNever()) {
6393 EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6394 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6395 return;
6396 }
6397 }
6398 Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
6399}
6400
6401void Assembler::mls(
6402 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006403 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006404 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006405 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006406 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
6407 EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6408 rm.GetCode() | (ra.GetCode() << 12));
6409 AdvanceIT();
6410 return;
6411 } else {
6412 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
6413 if (cond.IsNotNever()) {
6414 EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6415 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6416 return;
6417 }
6418 }
6419 Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
6420}
6421
6422void Assembler::mov(Condition cond,
6423 EncodingSize size,
6424 Register rd,
6425 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006426 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006427 CheckIT(cond);
6428 if (operand.IsImmediateShiftedRegister()) {
6429 Register rm = operand.GetBaseRegister();
6430 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006431 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006432 // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
6433 if (!size.IsWide()) {
6434 EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
6435 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
6436 AdvanceIT();
6437 return;
6438 }
6439 }
6440 }
6441 Shift shift = operand.GetShift();
6442 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006443 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006444 // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6445 if (InITBlock() && !size.IsWide() && rd.IsLow() &&
6446 shift.IsValidAmount(amount) && rm.IsLow() &&
6447 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
6448 uint32_t amount_ = amount % 32;
6449 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
6450 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
6451 AdvanceIT();
6452 return;
6453 }
6454 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
6455 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6456 uint32_t amount_ = amount % 32;
6457 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6458 (operand.GetTypeEncodingValue() << 4) |
6459 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6460 AdvanceIT();
6461 return;
6462 }
6463 } else {
6464 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6465 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6466 uint32_t amount_ = amount % 32;
6467 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6468 (rd.GetCode() << 12) | rm.GetCode() |
6469 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6470 return;
6471 }
6472 }
6473 }
6474 if (operand.IsRegisterShiftedRegister()) {
6475 Register rm = operand.GetBaseRegister();
6476 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006477 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006478 // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
6479 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6480 shift.IsASR() && operand.GetShiftRegister().IsLow()) {
6481 EmitT32_16(0x4100 | rd.GetCode() |
6482 (operand.GetShiftRegister().GetCode() << 3));
6483 AdvanceIT();
6484 return;
6485 }
6486 // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
6487 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6488 shift.IsLSL() && operand.GetShiftRegister().IsLow()) {
6489 EmitT32_16(0x4080 | rd.GetCode() |
6490 (operand.GetShiftRegister().GetCode() << 3));
6491 AdvanceIT();
6492 return;
6493 }
6494 // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
6495 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6496 shift.IsLSR() && operand.GetShiftRegister().IsLow()) {
6497 EmitT32_16(0x40c0 | rd.GetCode() |
6498 (operand.GetShiftRegister().GetCode() << 3));
6499 AdvanceIT();
6500 return;
6501 }
6502 // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
6503 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6504 shift.IsROR() && operand.GetShiftRegister().IsLow()) {
6505 EmitT32_16(0x41c0 | rd.GetCode() |
6506 (operand.GetShiftRegister().GetCode() << 3));
6507 AdvanceIT();
6508 return;
6509 }
6510 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
6511 if (!size.IsNarrow()) {
6512 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6513 (shift.GetType() << 21) |
6514 operand.GetShiftRegister().GetCode());
6515 AdvanceIT();
6516 return;
6517 }
6518 } else {
6519 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6520 if (cond.IsNotNever()) {
6521 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6522 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6523 (operand.GetShiftRegister().GetCode() << 8));
6524 return;
6525 }
6526 }
6527 }
6528 if (operand.IsImmediate()) {
6529 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006530 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006531 ImmediateT32 immediate_t32(imm);
6532 // MOV<c>{<q>} <Rd>, #<imm8> ; T1
6533 if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
6534 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
6535 AdvanceIT();
6536 return;
6537 }
6538 // MOV{<c>}{<q>} <Rd>, #<const> ; T2
6539 if (!size.IsNarrow() && immediate_t32.IsValid()) {
6540 EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
6541 (immediate_t32.GetEncodingValue() & 0xff) |
6542 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6543 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6544 AdvanceIT();
6545 return;
6546 }
6547 // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
6548 if (!size.IsNarrow() && (imm <= 65535)) {
6549 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
6550 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6551 ((imm & 0xf000) << 4));
6552 AdvanceIT();
6553 return;
6554 }
6555 } else {
6556 ImmediateA32 immediate_a32(imm);
6557 // MOV{<c>}{<q>} <Rd>, #<const> ; A1
6558 if (immediate_a32.IsValid() && cond.IsNotNever()) {
6559 EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
6560 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6561 return;
6562 }
6563 // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
6564 if ((imm <= 65535) && cond.IsNotNever()) {
6565 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
6566 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6567 return;
6568 }
6569 }
6570 }
6571 Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
6572}
6573
6574void Assembler::movs(Condition cond,
6575 EncodingSize size,
6576 Register rd,
6577 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006578 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006579 CheckIT(cond);
6580 if (operand.IsImmediateShiftedRegister()) {
6581 Register rm = operand.GetBaseRegister();
6582 Shift shift = operand.GetShift();
6583 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006584 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006585 // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6586 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
6587 shift.IsValidAmount(amount) && rm.IsLow() &&
6588 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
6589 uint32_t amount_ = amount % 32;
6590 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
6591 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
6592 AdvanceIT();
6593 return;
6594 }
6595 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
6596 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6597 uint32_t amount_ = amount % 32;
6598 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6599 (operand.GetTypeEncodingValue() << 4) |
6600 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6601 AdvanceIT();
6602 return;
6603 }
6604 } else {
6605 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6606 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6607 uint32_t amount_ = amount % 32;
6608 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6609 (rd.GetCode() << 12) | rm.GetCode() |
6610 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6611 return;
6612 }
6613 }
6614 }
6615 if (operand.IsRegisterShiftedRegister()) {
6616 Register rm = operand.GetBaseRegister();
6617 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006618 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006619 // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
6620 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6621 shift.IsASR() && operand.GetShiftRegister().IsLow()) {
6622 EmitT32_16(0x4100 | rd.GetCode() |
6623 (operand.GetShiftRegister().GetCode() << 3));
6624 AdvanceIT();
6625 return;
6626 }
6627 // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
6628 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6629 shift.IsLSL() && operand.GetShiftRegister().IsLow()) {
6630 EmitT32_16(0x4080 | rd.GetCode() |
6631 (operand.GetShiftRegister().GetCode() << 3));
6632 AdvanceIT();
6633 return;
6634 }
6635 // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
6636 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6637 shift.IsLSR() && operand.GetShiftRegister().IsLow()) {
6638 EmitT32_16(0x40c0 | rd.GetCode() |
6639 (operand.GetShiftRegister().GetCode() << 3));
6640 AdvanceIT();
6641 return;
6642 }
6643 // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
6644 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6645 shift.IsROR() && operand.GetShiftRegister().IsLow()) {
6646 EmitT32_16(0x41c0 | rd.GetCode() |
6647 (operand.GetShiftRegister().GetCode() << 3));
6648 AdvanceIT();
6649 return;
6650 }
6651 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
6652 if (!size.IsNarrow()) {
6653 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6654 (shift.GetType() << 21) |
6655 operand.GetShiftRegister().GetCode());
6656 AdvanceIT();
6657 return;
6658 }
6659 } else {
6660 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6661 if (cond.IsNotNever()) {
6662 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6663 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6664 (operand.GetShiftRegister().GetCode() << 8));
6665 return;
6666 }
6667 }
6668 }
6669 if (operand.IsImmediate()) {
6670 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006671 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006672 ImmediateT32 immediate_t32(imm);
6673 // MOVS{<q>} <Rd>, #<imm8> ; T1
6674 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
6675 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
6676 AdvanceIT();
6677 return;
6678 }
6679 // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
6680 if (!size.IsNarrow() && immediate_t32.IsValid()) {
6681 EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
6682 (immediate_t32.GetEncodingValue() & 0xff) |
6683 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6684 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6685 AdvanceIT();
6686 return;
6687 }
6688 } else {
6689 ImmediateA32 immediate_a32(imm);
6690 // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
6691 if (immediate_a32.IsValid() && cond.IsNotNever()) {
6692 EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
6693 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6694 return;
6695 }
6696 }
6697 }
6698 Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
6699}
6700
6701void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006702 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006703 CheckIT(cond);
6704 if (operand.IsImmediate()) {
6705 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006706 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006707 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
6708 if ((imm <= 65535)) {
6709 EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
6710 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6711 ((imm & 0xf000) << 4));
6712 AdvanceIT();
6713 return;
6714 }
6715 } else {
6716 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
6717 if ((imm <= 65535) && cond.IsNotNever()) {
6718 EmitA32(0x03400000U | (cond.GetCondition() << 28) |
6719 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6720 return;
6721 }
6722 }
6723 }
6724 Delegate(kMovt, &Assembler::movt, cond, rd, operand);
6725}
6726
6727void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006728 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006729 CheckIT(cond);
6730 if (operand.IsImmediate()) {
6731 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006732 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006733 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
6734 if ((imm <= 65535)) {
6735 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
6736 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
6737 ((imm & 0xf000) << 4));
6738 AdvanceIT();
6739 return;
6740 }
6741 } else {
6742 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
6743 if ((imm <= 65535) && cond.IsNotNever()) {
6744 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
6745 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
6746 return;
6747 }
6748 }
6749 }
6750 Delegate(kMovw, &Assembler::movw, cond, rd, operand);
6751}
6752
6753void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006754 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006755 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006756 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006757 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
6758 EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
6759 AdvanceIT();
6760 return;
6761 } else {
6762 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
6763 if (cond.IsNotNever()) {
6764 EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
6765 (spec_reg.GetReg() << 22));
6766 return;
6767 }
6768 }
6769 Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
6770}
6771
6772void Assembler::msr(Condition cond,
6773 MaskedSpecialRegister spec_reg,
6774 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006775 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006776 CheckIT(cond);
6777 if (operand.IsImmediate()) {
6778 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006779 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006780 ImmediateA32 immediate_a32(imm);
6781 // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
6782 if (immediate_a32.IsValid() && cond.IsNotNever()) {
6783 EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
6784 ((spec_reg.GetReg() & 0xf) << 16) |
6785 ((spec_reg.GetReg() & 0x10) << 18) |
6786 immediate_a32.GetEncodingValue());
6787 return;
6788 }
6789 }
6790 }
6791 if (operand.IsPlainRegister()) {
6792 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006793 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006794 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
6795 EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
6796 ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
6797 AdvanceIT();
6798 return;
6799 } else {
6800 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
6801 if (cond.IsNotNever()) {
6802 EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
6803 ((spec_reg.GetReg() & 0xf) << 16) |
6804 ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
6805 return;
6806 }
6807 }
6808 }
6809 Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
6810}
6811
6812void Assembler::mul(
6813 Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006814 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006815 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006816 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006817 // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
6818 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
6819 rm.IsLow()) {
6820 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
6821 AdvanceIT();
6822 return;
6823 }
6824 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
6825 if (!size.IsNarrow()) {
6826 EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6827 rm.GetCode());
6828 AdvanceIT();
6829 return;
6830 }
6831 } else {
6832 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
6833 if (cond.IsNotNever()) {
6834 EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6835 rn.GetCode() | (rm.GetCode() << 8));
6836 return;
6837 }
6838 }
6839 Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
6840}
6841
6842void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006843 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006844 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006845 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006846 // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
6847 if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
6848 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
6849 AdvanceIT();
6850 return;
6851 }
6852 } else {
6853 // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
6854 if (cond.IsNotNever()) {
6855 EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6856 rn.GetCode() | (rm.GetCode() << 8));
6857 return;
6858 }
6859 }
6860 Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
6861}
6862
6863void Assembler::mvn(Condition cond,
6864 EncodingSize size,
6865 Register rd,
6866 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006867 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006868 CheckIT(cond);
6869 if (operand.IsImmediate()) {
6870 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006871 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006872 ImmediateT32 immediate_t32(imm);
6873 // MVN{<c>}{<q>} <Rd>, #<const> ; T1
6874 if (!size.IsNarrow() && immediate_t32.IsValid()) {
6875 EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
6876 (immediate_t32.GetEncodingValue() & 0xff) |
6877 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6878 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6879 AdvanceIT();
6880 return;
6881 }
6882 } else {
6883 ImmediateA32 immediate_a32(imm);
6884 // MVN{<c>}{<q>} <Rd>, #<const> ; A1
6885 if (immediate_a32.IsValid() && cond.IsNotNever()) {
6886 EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
6887 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6888 return;
6889 }
6890 }
6891 }
6892 if (operand.IsImmediateShiftedRegister()) {
6893 Register rm = operand.GetBaseRegister();
6894 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006896 // MVN<c>{<q>} <Rd>, <Rm> ; T1
6897 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
6898 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
6899 AdvanceIT();
6900 return;
6901 }
6902 }
6903 }
6904 Shift shift = operand.GetShift();
6905 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006906 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006907 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6908 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6909 uint32_t amount_ = amount % 32;
6910 EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6911 (operand.GetTypeEncodingValue() << 4) |
6912 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6913 AdvanceIT();
6914 return;
6915 }
6916 } else {
6917 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6918 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6919 uint32_t amount_ = amount % 32;
6920 EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
6921 (rd.GetCode() << 12) | rm.GetCode() |
6922 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
6923 return;
6924 }
6925 }
6926 }
6927 if (operand.IsRegisterShiftedRegister()) {
6928 Register rm = operand.GetBaseRegister();
6929 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006930 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006931 // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
6932 if (cond.IsNotNever()) {
6933 EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
6934 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
6935 (operand.GetShiftRegister().GetCode() << 8));
6936 return;
6937 }
6938 }
6939 }
6940 Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
6941}
6942
6943void Assembler::mvns(Condition cond,
6944 EncodingSize size,
6945 Register rd,
6946 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006947 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006948 CheckIT(cond);
6949 if (operand.IsImmediate()) {
6950 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006951 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006952 ImmediateT32 immediate_t32(imm);
6953 // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
6954 if (!size.IsNarrow() && immediate_t32.IsValid()) {
6955 EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
6956 (immediate_t32.GetEncodingValue() & 0xff) |
6957 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
6958 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
6959 AdvanceIT();
6960 return;
6961 }
6962 } else {
6963 ImmediateA32 immediate_a32(imm);
6964 // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
6965 if (immediate_a32.IsValid() && cond.IsNotNever()) {
6966 EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
6967 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
6968 return;
6969 }
6970 }
6971 }
6972 if (operand.IsImmediateShiftedRegister()) {
6973 Register rm = operand.GetBaseRegister();
6974 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006975 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006976 // MVNS{<q>} <Rd>, <Rm> ; T1
6977 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
6978 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
6979 AdvanceIT();
6980 return;
6981 }
6982 }
6983 }
6984 Shift shift = operand.GetShift();
6985 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006986 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006987 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
6988 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
6989 uint32_t amount_ = amount % 32;
6990 EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6991 (operand.GetTypeEncodingValue() << 4) |
6992 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6993 AdvanceIT();
6994 return;
6995 }
6996 } else {
6997 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
6998 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
6999 uint32_t amount_ = amount % 32;
7000 EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7001 (rd.GetCode() << 12) | rm.GetCode() |
7002 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7003 return;
7004 }
7005 }
7006 }
7007 if (operand.IsRegisterShiftedRegister()) {
7008 Register rm = operand.GetBaseRegister();
7009 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007010 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007011 // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
7012 if (cond.IsNotNever()) {
7013 EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7014 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
7015 (operand.GetShiftRegister().GetCode() << 8));
7016 return;
7017 }
7018 }
7019 }
7020 Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7021}
7022
7023void Assembler::nop(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007024 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007025 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007026 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007027 // NOP{<c>}{<q>} ; T1
7028 if (!size.IsWide()) {
7029 EmitT32_16(0xbf00);
7030 AdvanceIT();
7031 return;
7032 }
7033 // NOP{<c>}.W ; T2
7034 if (!size.IsNarrow()) {
7035 EmitT32_32(0xf3af8000U);
7036 AdvanceIT();
7037 return;
7038 }
7039 } else {
7040 // NOP{<c>}{<q>} ; A1
7041 if (cond.IsNotNever()) {
7042 EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7043 return;
7044 }
7045 }
7046 Delegate(kNop, &Assembler::nop, cond, size);
7047}
7048
7049void Assembler::orn(Condition cond,
7050 Register rd,
7051 Register rn,
7052 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007053 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007054 CheckIT(cond);
7055 if (operand.IsImmediate()) {
7056 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007057 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007058 ImmediateT32 immediate_t32(imm);
7059 // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7060 if (immediate_t32.IsValid() && !rn.Is(pc)) {
7061 EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7062 (immediate_t32.GetEncodingValue() & 0xff) |
7063 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7064 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7065 AdvanceIT();
7066 return;
7067 }
7068 }
7069 }
7070 if (operand.IsImmediateShiftedRegister()) {
7071 Register rm = operand.GetBaseRegister();
7072 Shift shift = operand.GetShift();
7073 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007074 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007075 // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7076 if (shift.IsValidAmount(amount) && !rn.Is(pc)) {
7077 uint32_t amount_ = amount % 32;
7078 EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7079 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7080 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7081 AdvanceIT();
7082 return;
7083 }
7084 }
7085 }
7086 Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7087}
7088
7089void Assembler::orns(Condition cond,
7090 Register rd,
7091 Register rn,
7092 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007093 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007094 CheckIT(cond);
7095 if (operand.IsImmediate()) {
7096 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007097 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007098 ImmediateT32 immediate_t32(imm);
7099 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7100 if (immediate_t32.IsValid() && !rn.Is(pc)) {
7101 EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7102 (immediate_t32.GetEncodingValue() & 0xff) |
7103 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7104 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7105 AdvanceIT();
7106 return;
7107 }
7108 }
7109 }
7110 if (operand.IsImmediateShiftedRegister()) {
7111 Register rm = operand.GetBaseRegister();
7112 Shift shift = operand.GetShift();
7113 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007114 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007115 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
7116 if (shift.IsValidAmount(amount) && !rn.Is(pc)) {
7117 uint32_t amount_ = amount % 32;
7118 EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7119 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7120 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7121 AdvanceIT();
7122 return;
7123 }
7124 }
7125 }
7126 Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7127}
7128
7129void Assembler::orr(Condition cond,
7130 EncodingSize size,
7131 Register rd,
7132 Register rn,
7133 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007134 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007135 CheckIT(cond);
7136 if (operand.IsImmediate()) {
7137 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007138 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007139 ImmediateT32 immediate_t32(imm);
7140 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7141 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc)) {
7142 EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7143 (immediate_t32.GetEncodingValue() & 0xff) |
7144 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7145 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7146 AdvanceIT();
7147 return;
7148 }
7149 } else {
7150 ImmediateA32 immediate_a32(imm);
7151 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7152 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7153 EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7154 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7155 immediate_a32.GetEncodingValue());
7156 return;
7157 }
7158 }
7159 }
7160 if (operand.IsImmediateShiftedRegister()) {
7161 Register rm = operand.GetBaseRegister();
7162 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007163 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007164 // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7165 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7166 rm.IsLow()) {
7167 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7168 AdvanceIT();
7169 return;
7170 }
7171 }
7172 }
7173 Shift shift = operand.GetShift();
7174 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007175 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007176 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7177 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc)) {
7178 uint32_t amount_ = amount % 32;
7179 EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7180 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7181 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7182 AdvanceIT();
7183 return;
7184 }
7185 } else {
7186 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7187 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7188 uint32_t amount_ = amount % 32;
7189 EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7190 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7191 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7192 return;
7193 }
7194 }
7195 }
7196 if (operand.IsRegisterShiftedRegister()) {
7197 Register rm = operand.GetBaseRegister();
7198 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007199 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007200 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7201 if (cond.IsNotNever()) {
7202 EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7203 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7204 (shift.GetType() << 5) |
7205 (operand.GetShiftRegister().GetCode() << 8));
7206 return;
7207 }
7208 }
7209 }
7210 Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7211}
7212
7213void Assembler::orrs(Condition cond,
7214 EncodingSize size,
7215 Register rd,
7216 Register rn,
7217 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007218 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007219 CheckIT(cond);
7220 if (operand.IsImmediate()) {
7221 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007222 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007223 ImmediateT32 immediate_t32(imm);
7224 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
7225 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc)) {
7226 EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7227 (immediate_t32.GetEncodingValue() & 0xff) |
7228 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7229 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7230 AdvanceIT();
7231 return;
7232 }
7233 } else {
7234 ImmediateA32 immediate_a32(imm);
7235 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7236 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7237 EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7238 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7239 immediate_a32.GetEncodingValue());
7240 return;
7241 }
7242 }
7243 }
7244 if (operand.IsImmediateShiftedRegister()) {
7245 Register rm = operand.GetBaseRegister();
7246 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007247 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007248 // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7249 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7250 rm.IsLow()) {
7251 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7252 AdvanceIT();
7253 return;
7254 }
7255 }
7256 }
7257 Shift shift = operand.GetShift();
7258 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007259 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007260 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
7261 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc)) {
7262 uint32_t amount_ = amount % 32;
7263 EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7264 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7265 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7266 AdvanceIT();
7267 return;
7268 }
7269 } else {
7270 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7271 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7272 uint32_t amount_ = amount % 32;
7273 EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7274 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7275 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7276 return;
7277 }
7278 }
7279 }
7280 if (operand.IsRegisterShiftedRegister()) {
7281 Register rm = operand.GetBaseRegister();
7282 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007283 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007284 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
7285 if (cond.IsNotNever()) {
7286 EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7287 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7288 (shift.GetType() << 5) |
7289 (operand.GetShiftRegister().GetCode() << 8));
7290 return;
7291 }
7292 }
7293 }
7294 Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7295}
7296
7297void Assembler::pkhbt(Condition cond,
7298 Register rd,
7299 Register rn,
7300 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007301 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007302 CheckIT(cond);
7303 if (operand.IsImmediateShiftedRegister()) {
7304 Register rm = operand.GetBaseRegister();
7305 Shift shift = operand.GetShift();
7306 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007307 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007308 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
7309 if (shift.IsLSL() && shift.IsValidAmount(amount)) {
7310 EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7311 rm.GetCode() | ((amount & 0x3) << 6) |
7312 ((amount & 0x1c) << 10));
7313 AdvanceIT();
7314 return;
7315 }
7316 } else {
7317 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
7318 if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever()) {
7319 EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7320 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7321 (amount << 7));
7322 return;
7323 }
7324 }
7325 }
7326 Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7327}
7328
7329void Assembler::pkhtb(Condition cond,
7330 Register rd,
7331 Register rn,
7332 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007333 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007334 CheckIT(cond);
7335 if (operand.IsImmediateShiftedRegister()) {
7336 Register rm = operand.GetBaseRegister();
7337 Shift shift = operand.GetShift();
7338 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007339 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007340 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
7341 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount)) {
7342 uint32_t amount_ = amount % 32;
7343 EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7344 rm.GetCode() | ((amount_ & 0x3) << 6) |
7345 ((amount_ & 0x1c) << 10));
7346 AdvanceIT();
7347 return;
7348 }
7349 } else {
7350 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
7351 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7352 cond.IsNotNever()) {
7353 uint32_t amount_ = amount % 32;
7354 EmitA32(0x06800050U | (cond.GetCondition() << 28) |
7355 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7356 (amount_ << 7));
7357 return;
7358 }
7359 }
7360 }
7361 Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
7362}
7363
7364void Assembler::pld(Condition cond, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007365 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007366 CheckIT(cond);
7367 Label::Offset offset =
7368 label->IsBound()
7369 ? label->GetLocation() -
7370 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
7371 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007372 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007373 // PLD{<c>}{<q>} <label> ; T1
7374 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7375 !label->IsBound())) {
7376 static class EmitOp : public Label::LabelEmitOperator {
7377 public:
7378 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00007379 virtual uint32_t Encode(uint32_t instr,
7380 Label::Offset pc,
7381 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007382 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7383 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7384 uint32_t U = (offset >= 0) && !label->IsMinusZero();
7385 int32_t target = abs(offset) | (U << 12);
7386 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7387 }
7388 } immop;
7389 EmitT32_32(Link(0xf81ff000U, label, immop));
7390 AdvanceIT();
7391 return;
7392 }
7393 } else {
7394 // PLD{<c>}{<q>} <label> ; A1
7395 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7396 !label->IsBound())) {
7397 if (cond.Is(al)) {
7398 static class EmitOp : public Label::LabelEmitOperator {
7399 public:
7400 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00007401 virtual uint32_t Encode(uint32_t instr,
7402 Label::Offset pc,
7403 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007404 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7405 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7406 uint32_t U = (offset >= 0) && !label->IsMinusZero();
7407 int32_t target = abs(offset) | (U << 12);
7408 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7409 }
7410 } immop;
7411 EmitA32(Link(0xf55ff000U, label, immop));
7412 return;
7413 }
7414 }
7415 }
7416 Delegate(kPld, &Assembler::pld, cond, label);
7417}
7418
7419void Assembler::pld(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007420 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007421 CheckIT(cond);
7422 if (operand.IsImmediate()) {
7423 Register rn = operand.GetBaseRegister();
7424 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007425 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007426 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
7427 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7428 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7429 uint32_t offset_ = abs(offset);
7430 EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
7431 AdvanceIT();
7432 return;
7433 }
7434 } else {
7435 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
7436 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7437 if (cond.Is(al)) {
7438 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7439 uint32_t offset_ = abs(offset);
7440 EmitA32(0xf55ff000U | offset_ | (sign << 23));
7441 return;
7442 }
7443 }
7444 }
7445 }
7446 if (operand.IsImmediate()) {
7447 Register rn = operand.GetBaseRegister();
7448 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007449 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007450 // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7451 if ((offset >= 0) && (offset <= 4095) && ((rn.GetCode() & 0xf) != 0xf)) {
7452 EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7453 AdvanceIT();
7454 return;
7455 }
7456 // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7457 if ((-offset >= 0) && (-offset <= 255) && ((rn.GetCode() & 0xf) != 0xf)) {
7458 EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7459 AdvanceIT();
7460 return;
7461 }
7462 } else {
7463 // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
7464 if ((offset >= -4095) && (offset <= 4095) &&
7465 ((rn.GetCode() & 0xf) != 0xf)) {
7466 if (cond.Is(al)) {
7467 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7468 uint32_t offset_ = abs(offset);
7469 EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7470 return;
7471 }
7472 }
7473 }
7474 }
7475 if (operand.IsShiftedRegister()) {
7476 Register rn = operand.GetBaseRegister();
7477 Sign sign = operand.GetSign();
7478 Register rm = operand.GetOffsetRegister();
7479 Shift shift = operand.GetShift();
7480 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007481 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007482 // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7483 if (sign.IsPlus() && shift.IsLSL() && (operand.GetAddrMode() == Offset) &&
7484 ((rn.GetCode() & 0xf) != 0xf)) {
7485 EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
7486 (amount << 4));
7487 AdvanceIT();
7488 return;
7489 }
7490 } else {
7491 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7492 if (!shift.IsRRX() && shift.IsValidAmount(amount) &&
7493 (operand.GetAddrMode() == Offset)) {
7494 if (cond.Is(al)) {
7495 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7496 uint32_t amount_ = amount % 32;
7497 EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
7498 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7499 return;
7500 }
7501 }
7502 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7503 if (shift.IsRRX() && (operand.GetAddrMode() == Offset)) {
7504 if (cond.Is(al)) {
7505 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7506 EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
7507 (sign_ << 23));
7508 return;
7509 }
7510 }
7511 }
7512 }
7513 Delegate(kPld, &Assembler::pld, cond, operand);
7514}
7515
7516void Assembler::pldw(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007517 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007518 CheckIT(cond);
7519 if (operand.IsImmediate()) {
7520 Register rn = operand.GetBaseRegister();
7521 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007522 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007523 // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7524 if ((offset >= 0) && (offset <= 4095) && ((rn.GetCode() & 0xf) != 0xf)) {
7525 EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7526 AdvanceIT();
7527 return;
7528 }
7529 // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7530 if ((-offset >= 0) && (-offset <= 255) && ((rn.GetCode() & 0xf) != 0xf)) {
7531 EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7532 AdvanceIT();
7533 return;
7534 }
7535 } else {
7536 // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
7537 if ((offset >= -4095) && (offset <= 4095) &&
7538 ((rn.GetCode() & 0xf) != 0xf)) {
7539 if (cond.Is(al)) {
7540 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7541 uint32_t offset_ = abs(offset);
7542 EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7543 return;
7544 }
7545 }
7546 }
7547 }
7548 if (operand.IsShiftedRegister()) {
7549 Register rn = operand.GetBaseRegister();
7550 Sign sign = operand.GetSign();
7551 Register rm = operand.GetOffsetRegister();
7552 Shift shift = operand.GetShift();
7553 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007554 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007555 // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7556 if (sign.IsPlus() && shift.IsLSL() && (operand.GetAddrMode() == Offset) &&
7557 ((rn.GetCode() & 0xf) != 0xf)) {
7558 EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
7559 (amount << 4));
7560 AdvanceIT();
7561 return;
7562 }
7563 } else {
7564 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7565 if (!shift.IsRRX() && shift.IsValidAmount(amount) &&
7566 (operand.GetAddrMode() == Offset)) {
7567 if (cond.Is(al)) {
7568 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7569 uint32_t amount_ = amount % 32;
7570 EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
7571 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7572 return;
7573 }
7574 }
7575 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7576 if (shift.IsRRX() && (operand.GetAddrMode() == Offset)) {
7577 if (cond.Is(al)) {
7578 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7579 EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
7580 (sign_ << 23));
7581 return;
7582 }
7583 }
7584 }
7585 }
7586 Delegate(kPldw, &Assembler::pldw, cond, operand);
7587}
7588
7589void Assembler::pli(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007590 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007591 CheckIT(cond);
7592 if (operand.IsImmediate()) {
7593 Register rn = operand.GetBaseRegister();
7594 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007595 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007596 // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
7597 if ((offset >= 0) && (offset <= 4095) && ((rn.GetCode() & 0xf) != 0xf)) {
7598 EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
7599 AdvanceIT();
7600 return;
7601 }
7602 // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
7603 if ((-offset >= 0) && (-offset <= 255) && ((rn.GetCode() & 0xf) != 0xf)) {
7604 EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
7605 AdvanceIT();
7606 return;
7607 }
7608 } else {
7609 // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
7610 if ((offset >= -4095) && (offset <= 4095) &&
7611 ((rn.GetCode() & 0xf) != 0xf)) {
7612 if (cond.Is(al)) {
7613 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7614 uint32_t offset_ = abs(offset);
7615 EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
7616 return;
7617 }
7618 }
7619 }
7620 }
7621 if (operand.IsImmediate()) {
7622 Register rn = operand.GetBaseRegister();
7623 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007624 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007625 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
7626 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7627 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7628 uint32_t offset_ = abs(offset);
7629 EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
7630 AdvanceIT();
7631 return;
7632 }
7633 } else {
7634 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
7635 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc)) {
7636 if (cond.Is(al)) {
7637 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
7638 uint32_t offset_ = abs(offset);
7639 EmitA32(0xf45ff000U | offset_ | (sign << 23));
7640 return;
7641 }
7642 }
7643 }
7644 }
7645 if (operand.IsShiftedRegister()) {
7646 Register rn = operand.GetBaseRegister();
7647 Sign sign = operand.GetSign();
7648 Register rm = operand.GetOffsetRegister();
7649 Shift shift = operand.GetShift();
7650 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007652 // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
7653 if (sign.IsPlus() && shift.IsLSL() && (operand.GetAddrMode() == Offset) &&
7654 ((rn.GetCode() & 0xf) != 0xf)) {
7655 EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
7656 (amount << 4));
7657 AdvanceIT();
7658 return;
7659 }
7660 } else {
7661 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
7662 if (shift.IsRRX() && (operand.GetAddrMode() == Offset)) {
7663 if (cond.Is(al)) {
7664 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7665 EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
7666 (sign_ << 23));
7667 return;
7668 }
7669 }
7670 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
7671 if (!shift.IsRRX() && shift.IsValidAmount(amount) &&
7672 (operand.GetAddrMode() == Offset)) {
7673 if (cond.Is(al)) {
7674 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
7675 uint32_t amount_ = amount % 32;
7676 EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
7677 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
7678 return;
7679 }
7680 }
7681 }
7682 }
7683 Delegate(kPli, &Assembler::pli, cond, operand);
7684}
7685
7686void Assembler::pli(Condition cond, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007687 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007688 CheckIT(cond);
7689 Label::Offset offset =
7690 label->IsBound()
7691 ? label->GetLocation() -
7692 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
7693 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007694 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007695 // PLI{<c>}{<q>} <label> ; T3
7696 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7697 !label->IsBound())) {
7698 static class EmitOp : public Label::LabelEmitOperator {
7699 public:
7700 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00007701 virtual uint32_t Encode(uint32_t instr,
7702 Label::Offset pc,
7703 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007704 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7705 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7706 uint32_t U = (offset >= 0) && !label->IsMinusZero();
7707 int32_t target = abs(offset) | (U << 12);
7708 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7709 }
7710 } immop;
7711 EmitT32_32(Link(0xf91ff000U, label, immop));
7712 AdvanceIT();
7713 return;
7714 }
7715 } else {
7716 // PLI{<c>}{<q>} <label> ; A1
7717 if (((label->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
7718 !label->IsBound())) {
7719 if (cond.Is(al)) {
7720 static class EmitOp : public Label::LabelEmitOperator {
7721 public:
7722 EmitOp() : Label::LabelEmitOperator(-4095, 4095) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00007723 virtual uint32_t Encode(uint32_t instr,
7724 Label::Offset pc,
7725 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007726 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
7727 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
7728 uint32_t U = (offset >= 0) && !label->IsMinusZero();
7729 int32_t target = abs(offset) | (U << 12);
7730 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
7731 }
7732 } immop;
7733 EmitA32(Link(0xf45ff000U, label, immop));
7734 return;
7735 }
7736 }
7737 }
7738 Delegate(kPli, &Assembler::pli, cond, label);
7739}
7740
7741void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007742 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007743 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007744 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007745 // POP{<c>}{<q>} <registers> ; T1
7746 if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
7747 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
7748 GetRegisterListEncoding(registers, 0, 8));
7749 AdvanceIT();
7750 return;
7751 }
7752 // POP{<c>}{<q>} <registers> ; T2
7753 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
7754 EmitT32_32(0xe8bd0000U |
7755 (GetRegisterListEncoding(registers, 15, 1) << 15) |
7756 (GetRegisterListEncoding(registers, 14, 1) << 14) |
7757 GetRegisterListEncoding(registers, 0, 13));
7758 AdvanceIT();
7759 return;
7760 }
7761 } else {
7762 // POP{<c>}{<q>} <registers> ; A1
7763 if (cond.IsNotNever()) {
7764 EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
7765 GetRegisterListEncoding(registers, 0, 16));
7766 return;
7767 }
7768 }
7769 Delegate(kPop, &Assembler::pop, cond, size, registers);
7770}
7771
7772void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007773 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007774 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007775 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007776 // POP{<c>}{<q>} <single_register_list> ; T4
7777 if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) {
7778 EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
7779 AdvanceIT();
7780 return;
7781 }
7782 } else {
7783 // POP{<c>}{<q>} <single_register_list> ; A1
7784 if (cond.IsNotNever()) {
7785 EmitA32(0x049d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
7786 return;
7787 }
7788 }
7789 Delegate(kPop, &Assembler::pop, cond, size, rt);
7790}
7791
7792void Assembler::push(Condition cond,
7793 EncodingSize size,
7794 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007795 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007796 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007797 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007798 // PUSH{<c>}{<q>} <registers> ; T1
7799 if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
7800 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
7801 GetRegisterListEncoding(registers, 0, 8));
7802 AdvanceIT();
7803 return;
7804 }
7805 // PUSH{<c>}{<q>} <registers> ; T1
7806 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
7807 EmitT32_32(0xe92d0000U |
7808 (GetRegisterListEncoding(registers, 14, 1) << 14) |
7809 GetRegisterListEncoding(registers, 0, 13));
7810 AdvanceIT();
7811 return;
7812 }
7813 } else {
7814 // PUSH{<c>}{<q>} <registers> ; A1
7815 if (cond.IsNotNever()) {
7816 EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
7817 GetRegisterListEncoding(registers, 0, 16));
7818 return;
7819 }
7820 }
7821 Delegate(kPush, &Assembler::push, cond, size, registers);
7822}
7823
7824void Assembler::push(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007825 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007826 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007827 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007828 // PUSH{<c>}{<q>} <single_register_list> ; T4
7829 if (!size.IsNarrow()) {
7830 EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
7831 AdvanceIT();
7832 return;
7833 }
7834 } else {
7835 // PUSH{<c>}{<q>} <single_register_list> ; A1
7836 if (cond.IsNotNever() && ((!rt.IsPC()) || AllowUnpredictable())) {
7837 EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
7838 return;
7839 }
7840 }
7841 Delegate(kPush, &Assembler::push, cond, size, rt);
7842}
7843
7844void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007845 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007846 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007847 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007848 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7849 EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
7850 (rn.GetCode() << 16));
7851 AdvanceIT();
7852 return;
7853 } else {
7854 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7855 if (cond.IsNotNever()) {
7856 EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7857 rm.GetCode() | (rn.GetCode() << 16));
7858 return;
7859 }
7860 }
7861 Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
7862}
7863
7864void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007865 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007866 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007867 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007868 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7869 EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7870 rm.GetCode());
7871 AdvanceIT();
7872 return;
7873 } else {
7874 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7875 if (cond.IsNotNever()) {
7876 EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7877 (rn.GetCode() << 16) | rm.GetCode());
7878 return;
7879 }
7880 }
7881 Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
7882}
7883
7884void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007885 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007886 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007887 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007888 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7889 EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7890 rm.GetCode());
7891 AdvanceIT();
7892 return;
7893 } else {
7894 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7895 if (cond.IsNotNever()) {
7896 EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7897 (rn.GetCode() << 16) | rm.GetCode());
7898 return;
7899 }
7900 }
7901 Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
7902}
7903
7904void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007905 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007906 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007907 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007908 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7909 EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7910 rm.GetCode());
7911 AdvanceIT();
7912 return;
7913 } else {
7914 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7915 if (cond.IsNotNever()) {
7916 EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7917 (rn.GetCode() << 16) | rm.GetCode());
7918 return;
7919 }
7920 }
7921 Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
7922}
7923
7924void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007925 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007926 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007927 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007928 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7929 EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
7930 (rn.GetCode() << 16));
7931 AdvanceIT();
7932 return;
7933 } else {
7934 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7935 if (cond.IsNotNever()) {
7936 EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7937 rm.GetCode() | (rn.GetCode() << 16));
7938 return;
7939 }
7940 }
7941 Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
7942}
7943
7944void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007946 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007947 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007948 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7949 EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
7950 (rn.GetCode() << 16));
7951 AdvanceIT();
7952 return;
7953 } else {
7954 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7955 if (cond.IsNotNever()) {
7956 EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7957 rm.GetCode() | (rn.GetCode() << 16));
7958 return;
7959 }
7960 }
7961 Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
7962}
7963
7964void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007965 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007966 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007968 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
7969 EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7970 rm.GetCode());
7971 AdvanceIT();
7972 return;
7973 } else {
7974 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
7975 if (cond.IsNotNever()) {
7976 EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7977 (rn.GetCode() << 16) | rm.GetCode());
7978 return;
7979 }
7980 }
7981 Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
7982}
7983
7984void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007985 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007986 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007987 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007988 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
7989 EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
7990 (rn.GetCode() << 16));
7991 AdvanceIT();
7992 return;
7993 } else {
7994 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
7995 if (cond.IsNotNever()) {
7996 EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7997 rm.GetCode() | (rn.GetCode() << 16));
7998 return;
7999 }
8000 }
8001 Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8002}
8003
8004void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008005 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008006 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008007 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008008 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8009 EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8010 rm.GetCode());
8011 AdvanceIT();
8012 return;
8013 } else {
8014 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8015 if (cond.IsNotNever()) {
8016 EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8017 (rn.GetCode() << 16) | rm.GetCode());
8018 return;
8019 }
8020 }
8021 Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8022}
8023
8024void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008025 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008026 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008027 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008028 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8029 EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8030 rm.GetCode());
8031 AdvanceIT();
8032 return;
8033 } else {
8034 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8035 if (cond.IsNotNever()) {
8036 EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8037 (rn.GetCode() << 16) | rm.GetCode());
8038 return;
8039 }
8040 }
8041 Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8042}
8043
8044void Assembler::rbit(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008045 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008046 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008047 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008048 // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
8049 EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8050 (rm.GetCode() << 16));
8051 AdvanceIT();
8052 return;
8053 } else {
8054 // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
8055 if (cond.IsNotNever()) {
8056 EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8057 rm.GetCode());
8058 return;
8059 }
8060 }
8061 Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8062}
8063
8064void Assembler::rev(Condition cond,
8065 EncodingSize size,
8066 Register rd,
8067 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008068 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008069 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008070 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008071 // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8072 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8073 EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8074 AdvanceIT();
8075 return;
8076 }
8077 // REV{<c>}{<q>} <Rd>, <Rm> ; T2
8078 if (!size.IsNarrow()) {
8079 EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8080 (rm.GetCode() << 16));
8081 AdvanceIT();
8082 return;
8083 }
8084 } else {
8085 // REV{<c>}{<q>} <Rd>, <Rm> ; A1
8086 if (cond.IsNotNever()) {
8087 EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8088 rm.GetCode());
8089 return;
8090 }
8091 }
8092 Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8093}
8094
8095void Assembler::rev16(Condition cond,
8096 EncodingSize size,
8097 Register rd,
8098 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008099 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008100 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008101 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008102 // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8103 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8104 EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8105 AdvanceIT();
8106 return;
8107 }
8108 // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
8109 if (!size.IsNarrow()) {
8110 EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8111 (rm.GetCode() << 16));
8112 AdvanceIT();
8113 return;
8114 }
8115 } else {
8116 // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
8117 if (cond.IsNotNever()) {
8118 EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8119 rm.GetCode());
8120 return;
8121 }
8122 }
8123 Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8124}
8125
8126void Assembler::revsh(Condition cond,
8127 EncodingSize size,
8128 Register rd,
8129 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008130 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008131 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008132 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008133 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8134 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8135 EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8136 AdvanceIT();
8137 return;
8138 }
8139 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
8140 if (!size.IsNarrow()) {
8141 EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8142 (rm.GetCode() << 16));
8143 AdvanceIT();
8144 return;
8145 }
8146 } else {
8147 // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
8148 if (cond.IsNotNever()) {
8149 EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8150 rm.GetCode());
8151 return;
8152 }
8153 }
8154 Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8155}
8156
8157void Assembler::ror(Condition cond,
8158 EncodingSize size,
8159 Register rd,
8160 Register rm,
8161 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008162 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008163 CheckIT(cond);
8164 if (operand.IsImmediate()) {
8165 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008166 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008167 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8168 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
8169 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8170 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8171 AdvanceIT();
8172 return;
8173 }
8174 } else {
8175 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8176 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8177 EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8178 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8179 return;
8180 }
8181 }
8182 }
8183 if (operand.IsPlainRegister()) {
8184 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008185 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008186 // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8187 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8188 rs.IsLow()) {
8189 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8190 AdvanceIT();
8191 return;
8192 }
8193 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8194 if (!size.IsNarrow()) {
8195 EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8196 rs.GetCode());
8197 AdvanceIT();
8198 return;
8199 }
8200 } else {
8201 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8202 if (cond.IsNotNever()) {
8203 EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
8204 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8205 return;
8206 }
8207 }
8208 }
8209 Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
8210}
8211
8212void Assembler::rors(Condition cond,
8213 EncodingSize size,
8214 Register rd,
8215 Register rm,
8216 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008217 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008218 CheckIT(cond);
8219 if (operand.IsImmediate()) {
8220 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008221 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008222 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
8223 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) {
8224 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8225 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8226 AdvanceIT();
8227 return;
8228 }
8229 } else {
8230 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8231 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8232 EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
8233 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8234 return;
8235 }
8236 }
8237 }
8238 if (operand.IsPlainRegister()) {
8239 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008240 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008241 // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8242 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8243 rs.IsLow()) {
8244 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8245 AdvanceIT();
8246 return;
8247 }
8248 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
8249 if (!size.IsNarrow()) {
8250 EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8251 rs.GetCode());
8252 AdvanceIT();
8253 return;
8254 }
8255 } else {
8256 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
8257 if (cond.IsNotNever()) {
8258 EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
8259 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8260 return;
8261 }
8262 }
8263 }
8264 Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
8265}
8266
8267void Assembler::rrx(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008268 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008269 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008270 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008271 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
8272 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
8273 AdvanceIT();
8274 return;
8275 } else {
8276 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
8277 if (cond.IsNotNever()) {
8278 EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8279 rm.GetCode());
8280 return;
8281 }
8282 }
8283 Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
8284}
8285
8286void Assembler::rrxs(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008287 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008288 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008289 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008290 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
8291 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
8292 AdvanceIT();
8293 return;
8294 } else {
8295 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
8296 if (cond.IsNotNever()) {
8297 EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8298 rm.GetCode());
8299 return;
8300 }
8301 }
8302 Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
8303}
8304
8305void Assembler::rsb(Condition cond,
8306 EncodingSize size,
8307 Register rd,
8308 Register rn,
8309 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008310 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008311 CheckIT(cond);
8312 if (operand.IsImmediate()) {
8313 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008314 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008315 ImmediateT32 immediate_t32(imm);
8316 // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
8317 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
8318 (imm == 0)) {
8319 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
8320 AdvanceIT();
8321 return;
8322 }
8323 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
8324 if (!size.IsNarrow() && immediate_t32.IsValid()) {
8325 EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8326 (immediate_t32.GetEncodingValue() & 0xff) |
8327 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8328 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8329 AdvanceIT();
8330 return;
8331 }
8332 } else {
8333 ImmediateA32 immediate_a32(imm);
8334 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8335 if (immediate_a32.IsValid() && cond.IsNotNever()) {
8336 EmitA32(0x02600000U | (cond.GetCondition() << 28) |
8337 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8338 immediate_a32.GetEncodingValue());
8339 return;
8340 }
8341 }
8342 }
8343 if (operand.IsImmediateShiftedRegister()) {
8344 Register rm = operand.GetBaseRegister();
8345 Shift shift = operand.GetShift();
8346 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008347 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008348 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
8349 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8350 uint32_t amount_ = amount % 32;
8351 EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8352 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8353 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8354 AdvanceIT();
8355 return;
8356 }
8357 } else {
8358 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8359 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8360 uint32_t amount_ = amount % 32;
8361 EmitA32(0x00600000U | (cond.GetCondition() << 28) |
8362 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8363 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8364 return;
8365 }
8366 }
8367 }
8368 if (operand.IsRegisterShiftedRegister()) {
8369 Register rm = operand.GetBaseRegister();
8370 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008371 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008372 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8373 if (cond.IsNotNever()) {
8374 EmitA32(0x00600010U | (cond.GetCondition() << 28) |
8375 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8376 (shift.GetType() << 5) |
8377 (operand.GetShiftRegister().GetCode() << 8));
8378 return;
8379 }
8380 }
8381 }
8382 Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
8383}
8384
8385void Assembler::rsbs(Condition cond,
8386 EncodingSize size,
8387 Register rd,
8388 Register rn,
8389 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008390 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008391 CheckIT(cond);
8392 if (operand.IsImmediate()) {
8393 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008394 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008395 ImmediateT32 immediate_t32(imm);
8396 // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
8397 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
8398 (imm == 0)) {
8399 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
8400 AdvanceIT();
8401 return;
8402 }
8403 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
8404 if (!size.IsNarrow() && immediate_t32.IsValid()) {
8405 EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8406 (immediate_t32.GetEncodingValue() & 0xff) |
8407 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8408 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8409 AdvanceIT();
8410 return;
8411 }
8412 } else {
8413 ImmediateA32 immediate_a32(imm);
8414 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8415 if (immediate_a32.IsValid() && cond.IsNotNever()) {
8416 EmitA32(0x02700000U | (cond.GetCondition() << 28) |
8417 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8418 immediate_a32.GetEncodingValue());
8419 return;
8420 }
8421 }
8422 }
8423 if (operand.IsImmediateShiftedRegister()) {
8424 Register rm = operand.GetBaseRegister();
8425 Shift shift = operand.GetShift();
8426 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008427 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008428 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
8429 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8430 uint32_t amount_ = amount % 32;
8431 EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8432 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8433 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8434 AdvanceIT();
8435 return;
8436 }
8437 } else {
8438 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8439 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8440 uint32_t amount_ = amount % 32;
8441 EmitA32(0x00700000U | (cond.GetCondition() << 28) |
8442 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8443 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8444 return;
8445 }
8446 }
8447 }
8448 if (operand.IsRegisterShiftedRegister()) {
8449 Register rm = operand.GetBaseRegister();
8450 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008451 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008452 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8453 if (cond.IsNotNever()) {
8454 EmitA32(0x00700010U | (cond.GetCondition() << 28) |
8455 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8456 (shift.GetType() << 5) |
8457 (operand.GetShiftRegister().GetCode() << 8));
8458 return;
8459 }
8460 }
8461 }
8462 Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
8463}
8464
8465void Assembler::rsc(Condition cond,
8466 Register rd,
8467 Register rn,
8468 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008469 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008470 CheckIT(cond);
8471 if (operand.IsImmediate()) {
8472 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008473 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008474 ImmediateA32 immediate_a32(imm);
8475 // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8476 if (immediate_a32.IsValid() && cond.IsNotNever()) {
8477 EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
8478 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8479 immediate_a32.GetEncodingValue());
8480 return;
8481 }
8482 }
8483 }
8484 if (operand.IsImmediateShiftedRegister()) {
8485 Register rm = operand.GetBaseRegister();
8486 Shift shift = operand.GetShift();
8487 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008488 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008489 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8490 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8491 uint32_t amount_ = amount % 32;
8492 EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
8493 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8494 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8495 return;
8496 }
8497 }
8498 }
8499 if (operand.IsRegisterShiftedRegister()) {
8500 Register rm = operand.GetBaseRegister();
8501 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008502 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008503 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8504 if (cond.IsNotNever()) {
8505 EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
8506 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8507 (shift.GetType() << 5) |
8508 (operand.GetShiftRegister().GetCode() << 8));
8509 return;
8510 }
8511 }
8512 }
8513 Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
8514}
8515
8516void Assembler::rscs(Condition cond,
8517 Register rd,
8518 Register rn,
8519 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008520 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008521 CheckIT(cond);
8522 if (operand.IsImmediate()) {
8523 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008524 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008525 ImmediateA32 immediate_a32(imm);
8526 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8527 if (immediate_a32.IsValid() && cond.IsNotNever()) {
8528 EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
8529 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8530 immediate_a32.GetEncodingValue());
8531 return;
8532 }
8533 }
8534 }
8535 if (operand.IsImmediateShiftedRegister()) {
8536 Register rm = operand.GetBaseRegister();
8537 Shift shift = operand.GetShift();
8538 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008539 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008540 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8541 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8542 uint32_t amount_ = amount % 32;
8543 EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
8544 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8545 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8546 return;
8547 }
8548 }
8549 }
8550 if (operand.IsRegisterShiftedRegister()) {
8551 Register rm = operand.GetBaseRegister();
8552 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008553 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008554 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8555 if (cond.IsNotNever()) {
8556 EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
8557 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8558 (shift.GetType() << 5) |
8559 (operand.GetShiftRegister().GetCode() << 8));
8560 return;
8561 }
8562 }
8563 }
8564 Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
8565}
8566
8567void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008568 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008569 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008570 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008571 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8572 EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8573 rm.GetCode());
8574 AdvanceIT();
8575 return;
8576 } else {
8577 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8578 if (cond.IsNotNever()) {
8579 EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8580 (rn.GetCode() << 16) | rm.GetCode());
8581 return;
8582 }
8583 }
8584 Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
8585}
8586
8587void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008588 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008589 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008590 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008591 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8592 EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8593 rm.GetCode());
8594 AdvanceIT();
8595 return;
8596 } else {
8597 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8598 if (cond.IsNotNever()) {
8599 EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8600 (rn.GetCode() << 16) | rm.GetCode());
8601 return;
8602 }
8603 }
8604 Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
8605}
8606
8607void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008608 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008609 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008610 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008611 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8612 EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8613 rm.GetCode());
8614 AdvanceIT();
8615 return;
8616 } else {
8617 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8618 if (cond.IsNotNever()) {
8619 EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8620 (rn.GetCode() << 16) | rm.GetCode());
8621 return;
8622 }
8623 }
8624 Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
8625}
8626
8627void Assembler::sbc(Condition cond,
8628 EncodingSize size,
8629 Register rd,
8630 Register rn,
8631 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008632 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008633 CheckIT(cond);
8634 if (operand.IsImmediate()) {
8635 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008636 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008637 ImmediateT32 immediate_t32(imm);
8638 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
8639 if (!size.IsNarrow() && immediate_t32.IsValid()) {
8640 EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8641 (immediate_t32.GetEncodingValue() & 0xff) |
8642 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8643 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8644 AdvanceIT();
8645 return;
8646 }
8647 } else {
8648 ImmediateA32 immediate_a32(imm);
8649 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8650 if (immediate_a32.IsValid() && cond.IsNotNever()) {
8651 EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
8652 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8653 immediate_a32.GetEncodingValue());
8654 return;
8655 }
8656 }
8657 }
8658 if (operand.IsImmediateShiftedRegister()) {
8659 Register rm = operand.GetBaseRegister();
8660 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008661 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008662 // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
8663 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
8664 rm.IsLow()) {
8665 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
8666 AdvanceIT();
8667 return;
8668 }
8669 }
8670 }
8671 Shift shift = operand.GetShift();
8672 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008673 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008674 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
8675 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8676 uint32_t amount_ = amount % 32;
8677 EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8678 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8679 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8680 AdvanceIT();
8681 return;
8682 }
8683 } else {
8684 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8685 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8686 uint32_t amount_ = amount % 32;
8687 EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
8688 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8689 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8690 return;
8691 }
8692 }
8693 }
8694 if (operand.IsRegisterShiftedRegister()) {
8695 Register rm = operand.GetBaseRegister();
8696 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008697 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008698 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8699 if (cond.IsNotNever()) {
8700 EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
8701 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8702 (shift.GetType() << 5) |
8703 (operand.GetShiftRegister().GetCode() << 8));
8704 return;
8705 }
8706 }
8707 }
8708 Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
8709}
8710
8711void Assembler::sbcs(Condition cond,
8712 EncodingSize size,
8713 Register rd,
8714 Register rn,
8715 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008716 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008717 CheckIT(cond);
8718 if (operand.IsImmediate()) {
8719 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008720 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008721 ImmediateT32 immediate_t32(imm);
8722 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
8723 if (!size.IsNarrow() && immediate_t32.IsValid()) {
8724 EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8725 (immediate_t32.GetEncodingValue() & 0xff) |
8726 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
8727 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
8728 AdvanceIT();
8729 return;
8730 }
8731 } else {
8732 ImmediateA32 immediate_a32(imm);
8733 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
8734 if (immediate_a32.IsValid() && cond.IsNotNever()) {
8735 EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
8736 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
8737 immediate_a32.GetEncodingValue());
8738 return;
8739 }
8740 }
8741 }
8742 if (operand.IsImmediateShiftedRegister()) {
8743 Register rm = operand.GetBaseRegister();
8744 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008745 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008746 // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
8747 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
8748 rm.IsLow()) {
8749 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
8750 AdvanceIT();
8751 return;
8752 }
8753 }
8754 }
8755 Shift shift = operand.GetShift();
8756 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008757 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008758 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
8759 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
8760 uint32_t amount_ = amount % 32;
8761 EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8762 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
8763 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
8764 AdvanceIT();
8765 return;
8766 }
8767 } else {
8768 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
8769 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
8770 uint32_t amount_ = amount % 32;
8771 EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
8772 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8773 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
8774 return;
8775 }
8776 }
8777 }
8778 if (operand.IsRegisterShiftedRegister()) {
8779 Register rm = operand.GetBaseRegister();
8780 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008781 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008782 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
8783 if (cond.IsNotNever()) {
8784 EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
8785 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8786 (shift.GetType() << 5) |
8787 (operand.GetShiftRegister().GetCode() << 8));
8788 return;
8789 }
8790 }
8791 }
8792 Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
8793}
8794
8795void Assembler::sbfx(Condition cond,
8796 Register rd,
8797 Register rn,
8798 uint32_t lsb,
8799 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008800 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008801 CheckIT(cond);
8802 if (operand.IsImmediate()) {
8803 uint32_t width = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008804 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008805 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
8806 if ((lsb <= 31) &&
8807 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
8808 uint32_t widthm1 = width - 1;
8809 EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8810 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
8811 AdvanceIT();
8812 return;
8813 }
8814 } else {
8815 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
8816 if ((lsb <= 31) && cond.IsNotNever() &&
8817 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
8818 uint32_t widthm1 = width - 1;
8819 EmitA32(0x07a00050U | (cond.GetCondition() << 28) |
8820 (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) |
8821 (widthm1 << 16));
8822 return;
8823 }
8824 }
8825 }
8826 Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, operand);
8827}
8828
8829void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008830 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008831 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008833 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8834 EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8835 rm.GetCode());
8836 AdvanceIT();
8837 return;
8838 } else {
8839 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8840 if (cond.IsNotNever()) {
8841 EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
8842 rn.GetCode() | (rm.GetCode() << 8));
8843 return;
8844 }
8845 }
8846 Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
8847}
8848
8849void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008850 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008851 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008852 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008853 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8854 EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8855 rm.GetCode());
8856 AdvanceIT();
8857 return;
8858 } else {
8859 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8860 if (cond.IsNotNever()) {
8861 EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8862 (rn.GetCode() << 16) | rm.GetCode());
8863 return;
8864 }
8865 }
8866 Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
8867}
8868
8869void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008870 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008871 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008872 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008873 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8874 EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8875 rm.GetCode());
8876 AdvanceIT();
8877 return;
8878 } else {
8879 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8880 if (cond.IsNotNever()) {
8881 EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8882 (rn.GetCode() << 16) | rm.GetCode());
8883 return;
8884 }
8885 }
8886 Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
8887}
8888
8889void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008890 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008891 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008892 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008893 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8894 EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8895 rm.GetCode());
8896 AdvanceIT();
8897 return;
8898 } else {
8899 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8900 if (cond.IsNotNever()) {
8901 EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8902 (rn.GetCode() << 16) | rm.GetCode());
8903 return;
8904 }
8905 }
8906 Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
8907}
8908
8909void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008910 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008911 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008912 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008913 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8914 EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8915 rm.GetCode());
8916 AdvanceIT();
8917 return;
8918 } else {
8919 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8920 if (cond.IsNotNever()) {
8921 EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8922 (rn.GetCode() << 16) | rm.GetCode());
8923 return;
8924 }
8925 }
8926 Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
8927}
8928
8929void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008930 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008931 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008932 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008933 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8934 EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8935 rm.GetCode());
8936 AdvanceIT();
8937 return;
8938 } else {
8939 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8940 if (cond.IsNotNever()) {
8941 EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8942 (rn.GetCode() << 16) | rm.GetCode());
8943 return;
8944 }
8945 }
8946 Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
8947}
8948
8949void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008950 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008951 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008952 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008953 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8954 EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8955 rm.GetCode());
8956 AdvanceIT();
8957 return;
8958 } else {
8959 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8960 if (cond.IsNotNever()) {
8961 EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8962 (rn.GetCode() << 16) | rm.GetCode());
8963 return;
8964 }
8965 }
8966 Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
8967}
8968
8969void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008970 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008971 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008972 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008973 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
8974 EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8975 rm.GetCode());
8976 AdvanceIT();
8977 return;
8978 } else {
8979 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
8980 if (cond.IsNotNever()) {
8981 EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8982 (rn.GetCode() << 16) | rm.GetCode());
8983 return;
8984 }
8985 }
8986 Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
8987}
8988
8989void Assembler::smlabb(
8990 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008991 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008992 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008993 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008994 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
8995 if (!ra.Is(pc)) {
8996 EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8997 rm.GetCode() | (ra.GetCode() << 12));
8998 AdvanceIT();
8999 return;
9000 }
9001 } else {
9002 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9003 if (cond.IsNotNever()) {
9004 EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9005 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9006 return;
9007 }
9008 }
9009 Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9010}
9011
9012void Assembler::smlabt(
9013 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009014 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009015 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009016 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009017 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9018 if (!ra.Is(pc)) {
9019 EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9020 rm.GetCode() | (ra.GetCode() << 12));
9021 AdvanceIT();
9022 return;
9023 }
9024 } else {
9025 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9026 if (cond.IsNotNever()) {
9027 EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9028 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9029 return;
9030 }
9031 }
9032 Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9033}
9034
9035void Assembler::smlad(
9036 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009037 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009038 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009039 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009040 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9041 if (!ra.Is(pc)) {
9042 EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9043 rm.GetCode() | (ra.GetCode() << 12));
9044 AdvanceIT();
9045 return;
9046 }
9047 } else {
9048 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9049 if (cond.IsNotNever() && !ra.Is(pc)) {
9050 EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9051 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9052 return;
9053 }
9054 }
9055 Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9056}
9057
9058void Assembler::smladx(
9059 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009060 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009061 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009062 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009063 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9064 if (!ra.Is(pc)) {
9065 EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9066 rm.GetCode() | (ra.GetCode() << 12));
9067 AdvanceIT();
9068 return;
9069 }
9070 } else {
9071 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9072 if (cond.IsNotNever() && !ra.Is(pc)) {
9073 EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9074 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9075 return;
9076 }
9077 }
9078 Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9079}
9080
9081void Assembler::smlal(
9082 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009083 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009084 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009085 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009086 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9087 EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9088 (rn.GetCode() << 16) | rm.GetCode());
9089 AdvanceIT();
9090 return;
9091 } else {
9092 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9093 if (cond.IsNotNever()) {
9094 EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9095 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9096 (rm.GetCode() << 8));
9097 return;
9098 }
9099 }
9100 Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9101}
9102
9103void Assembler::smlalbb(
9104 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009105 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009106 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009107 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009108 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9109 EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9110 (rn.GetCode() << 16) | rm.GetCode());
9111 AdvanceIT();
9112 return;
9113 } else {
9114 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9115 if (cond.IsNotNever()) {
9116 EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9117 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9118 (rm.GetCode() << 8));
9119 return;
9120 }
9121 }
9122 Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9123}
9124
9125void Assembler::smlalbt(
9126 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009127 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009128 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009129 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009130 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9131 EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9132 (rn.GetCode() << 16) | rm.GetCode());
9133 AdvanceIT();
9134 return;
9135 } else {
9136 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9137 if (cond.IsNotNever()) {
9138 EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
9139 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9140 (rm.GetCode() << 8));
9141 return;
9142 }
9143 }
9144 Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
9145}
9146
9147void Assembler::smlald(
9148 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009149 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009150 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009151 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009152 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9153 EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9154 (rn.GetCode() << 16) | rm.GetCode());
9155 AdvanceIT();
9156 return;
9157 } else {
9158 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9159 if (cond.IsNotNever()) {
9160 EmitA32(0x07400010U | (cond.GetCondition() << 28) |
9161 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9162 (rm.GetCode() << 8));
9163 return;
9164 }
9165 }
9166 Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
9167}
9168
9169void Assembler::smlaldx(
9170 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009171 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009172 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009173 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009174 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9175 EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9176 (rn.GetCode() << 16) | rm.GetCode());
9177 AdvanceIT();
9178 return;
9179 } else {
9180 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9181 if (cond.IsNotNever()) {
9182 EmitA32(0x07400030U | (cond.GetCondition() << 28) |
9183 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9184 (rm.GetCode() << 8));
9185 return;
9186 }
9187 }
9188 Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
9189}
9190
9191void Assembler::smlals(
9192 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009193 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009194 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009195 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009196 // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9197 if (cond.IsNotNever()) {
9198 EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
9199 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9200 (rm.GetCode() << 8));
9201 return;
9202 }
9203 }
9204 Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
9205}
9206
9207void Assembler::smlaltb(
9208 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009209 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009210 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009211 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009212 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9213 EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9214 (rn.GetCode() << 16) | rm.GetCode());
9215 AdvanceIT();
9216 return;
9217 } else {
9218 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9219 if (cond.IsNotNever()) {
9220 EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
9221 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9222 (rm.GetCode() << 8));
9223 return;
9224 }
9225 }
9226 Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
9227}
9228
9229void Assembler::smlaltt(
9230 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009231 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009232 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009233 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009234 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9235 EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9236 (rn.GetCode() << 16) | rm.GetCode());
9237 AdvanceIT();
9238 return;
9239 } else {
9240 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9241 if (cond.IsNotNever()) {
9242 EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
9243 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9244 (rm.GetCode() << 8));
9245 return;
9246 }
9247 }
9248 Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
9249}
9250
9251void Assembler::smlatb(
9252 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009253 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009254 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009255 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009256 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9257 if (!ra.Is(pc)) {
9258 EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9259 rm.GetCode() | (ra.GetCode() << 12));
9260 AdvanceIT();
9261 return;
9262 }
9263 } else {
9264 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9265 if (cond.IsNotNever()) {
9266 EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9267 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9268 return;
9269 }
9270 }
9271 Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
9272}
9273
9274void Assembler::smlatt(
9275 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009276 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009277 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009278 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009279 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9280 if (!ra.Is(pc)) {
9281 EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9282 rm.GetCode() | (ra.GetCode() << 12));
9283 AdvanceIT();
9284 return;
9285 }
9286 } else {
9287 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9288 if (cond.IsNotNever()) {
9289 EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9290 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9291 return;
9292 }
9293 }
9294 Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
9295}
9296
9297void Assembler::smlawb(
9298 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009299 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009300 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009301 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009302 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9303 if (!ra.Is(pc)) {
9304 EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9305 rm.GetCode() | (ra.GetCode() << 12));
9306 AdvanceIT();
9307 return;
9308 }
9309 } else {
9310 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9311 if (cond.IsNotNever()) {
9312 EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9313 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9314 return;
9315 }
9316 }
9317 Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
9318}
9319
9320void Assembler::smlawt(
9321 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009322 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009323 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009324 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009325 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9326 if (!ra.Is(pc)) {
9327 EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9328 rm.GetCode() | (ra.GetCode() << 12));
9329 AdvanceIT();
9330 return;
9331 }
9332 } else {
9333 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9334 if (cond.IsNotNever()) {
9335 EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9336 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9337 return;
9338 }
9339 }
9340 Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
9341}
9342
9343void Assembler::smlsd(
9344 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009345 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009346 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009347 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009348 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9349 if (!ra.Is(pc)) {
9350 EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9351 rm.GetCode() | (ra.GetCode() << 12));
9352 AdvanceIT();
9353 return;
9354 }
9355 } else {
9356 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9357 if (cond.IsNotNever() && !ra.Is(pc)) {
9358 EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9359 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9360 return;
9361 }
9362 }
9363 Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
9364}
9365
9366void Assembler::smlsdx(
9367 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009369 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009370 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009371 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9372 if (!ra.Is(pc)) {
9373 EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9374 rm.GetCode() | (ra.GetCode() << 12));
9375 AdvanceIT();
9376 return;
9377 }
9378 } else {
9379 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9380 if (cond.IsNotNever() && !ra.Is(pc)) {
9381 EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9382 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9383 return;
9384 }
9385 }
9386 Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
9387}
9388
9389void Assembler::smlsld(
9390 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009391 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009392 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009393 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009394 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9395 EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9396 (rn.GetCode() << 16) | rm.GetCode());
9397 AdvanceIT();
9398 return;
9399 } else {
9400 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9401 if (cond.IsNotNever()) {
9402 EmitA32(0x07400050U | (cond.GetCondition() << 28) |
9403 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9404 (rm.GetCode() << 8));
9405 return;
9406 }
9407 }
9408 Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
9409}
9410
9411void Assembler::smlsldx(
9412 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009413 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009414 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009415 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009416 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9417 EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9418 (rn.GetCode() << 16) | rm.GetCode());
9419 AdvanceIT();
9420 return;
9421 } else {
9422 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9423 if (cond.IsNotNever()) {
9424 EmitA32(0x07400070U | (cond.GetCondition() << 28) |
9425 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9426 (rm.GetCode() << 8));
9427 return;
9428 }
9429 }
9430 Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
9431}
9432
9433void Assembler::smmla(
9434 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009435 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009436 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009437 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009438 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9439 if (!ra.Is(pc)) {
9440 EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9441 rm.GetCode() | (ra.GetCode() << 12));
9442 AdvanceIT();
9443 return;
9444 }
9445 } else {
9446 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9447 if (cond.IsNotNever() && !ra.Is(pc)) {
9448 EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9449 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9450 return;
9451 }
9452 }
9453 Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
9454}
9455
9456void Assembler::smmlar(
9457 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009458 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009459 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009460 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009461 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9462 if (!ra.Is(pc)) {
9463 EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9464 rm.GetCode() | (ra.GetCode() << 12));
9465 AdvanceIT();
9466 return;
9467 }
9468 } else {
9469 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9470 if (cond.IsNotNever() && !ra.Is(pc)) {
9471 EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9472 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9473 return;
9474 }
9475 }
9476 Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
9477}
9478
9479void Assembler::smmls(
9480 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009481 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009482 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009483 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009484 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9485 EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9486 rm.GetCode() | (ra.GetCode() << 12));
9487 AdvanceIT();
9488 return;
9489 } else {
9490 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9491 if (cond.IsNotNever()) {
9492 EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9493 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9494 return;
9495 }
9496 }
9497 Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
9498}
9499
9500void Assembler::smmlsr(
9501 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009502 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009503 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009504 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009505 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
9506 EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9507 rm.GetCode() | (ra.GetCode() << 12));
9508 AdvanceIT();
9509 return;
9510 } else {
9511 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
9512 if (cond.IsNotNever()) {
9513 EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9514 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9515 return;
9516 }
9517 }
9518 Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
9519}
9520
9521void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009522 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009523 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009524 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009525 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9526 EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9527 rm.GetCode());
9528 AdvanceIT();
9529 return;
9530 } else {
9531 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9532 if (cond.IsNotNever()) {
9533 EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9534 rn.GetCode() | (rm.GetCode() << 8));
9535 return;
9536 }
9537 }
9538 Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
9539}
9540
9541void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009542 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009543 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009544 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009545 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9546 EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9547 rm.GetCode());
9548 AdvanceIT();
9549 return;
9550 } else {
9551 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9552 if (cond.IsNotNever()) {
9553 EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9554 rn.GetCode() | (rm.GetCode() << 8));
9555 return;
9556 }
9557 }
9558 Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
9559}
9560
9561void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009562 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009563 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009564 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009565 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9566 EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9567 rm.GetCode());
9568 AdvanceIT();
9569 return;
9570 } else {
9571 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9572 if (cond.IsNotNever()) {
9573 EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9574 rn.GetCode() | (rm.GetCode() << 8));
9575 return;
9576 }
9577 }
9578 Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
9579}
9580
9581void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009582 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009583 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009584 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009585 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9586 EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9587 rm.GetCode());
9588 AdvanceIT();
9589 return;
9590 } else {
9591 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9592 if (cond.IsNotNever()) {
9593 EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9594 rn.GetCode() | (rm.GetCode() << 8));
9595 return;
9596 }
9597 }
9598 Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
9599}
9600
9601void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009602 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009603 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009604 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009605 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9606 EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9607 rm.GetCode());
9608 AdvanceIT();
9609 return;
9610 } else {
9611 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9612 if (cond.IsNotNever()) {
9613 EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9614 rn.GetCode() | (rm.GetCode() << 8));
9615 return;
9616 }
9617 }
9618 Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
9619}
9620
9621void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009622 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009623 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009624 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009625 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9626 EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9627 rm.GetCode());
9628 AdvanceIT();
9629 return;
9630 } else {
9631 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9632 if (cond.IsNotNever()) {
9633 EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9634 rn.GetCode() | (rm.GetCode() << 8));
9635 return;
9636 }
9637 }
9638 Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
9639}
9640
9641void Assembler::smull(
9642 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009643 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009644 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009645 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009646 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
9647 EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9648 (rn.GetCode() << 16) | rm.GetCode());
9649 AdvanceIT();
9650 return;
9651 } else {
9652 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9653 if (cond.IsNotNever()) {
9654 EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
9655 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9656 (rm.GetCode() << 8));
9657 return;
9658 }
9659 }
9660 Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
9661}
9662
9663void Assembler::smulls(
9664 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009665 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009666 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009667 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009668 // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
9669 if (cond.IsNotNever()) {
9670 EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
9671 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9672 (rm.GetCode() << 8));
9673 return;
9674 }
9675 }
9676 Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
9677}
9678
9679void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009680 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009681 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009682 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009683 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9684 EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9685 rm.GetCode());
9686 AdvanceIT();
9687 return;
9688 } else {
9689 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9690 if (cond.IsNotNever()) {
9691 EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9692 rn.GetCode() | (rm.GetCode() << 8));
9693 return;
9694 }
9695 }
9696 Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
9697}
9698
9699void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009700 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009701 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009702 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009703 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9704 EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9705 rm.GetCode());
9706 AdvanceIT();
9707 return;
9708 } else {
9709 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9710 if (cond.IsNotNever()) {
9711 EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9712 rn.GetCode() | (rm.GetCode() << 8));
9713 return;
9714 }
9715 }
9716 Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
9717}
9718
9719void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009721 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009722 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009723 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9724 EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9725 rm.GetCode());
9726 AdvanceIT();
9727 return;
9728 } else {
9729 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9730 if (cond.IsNotNever()) {
9731 EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9732 rn.GetCode() | (rm.GetCode() << 8));
9733 return;
9734 }
9735 }
9736 Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
9737}
9738
9739void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009740 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009741 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009743 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9744 EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9745 rm.GetCode());
9746 AdvanceIT();
9747 return;
9748 } else {
9749 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9750 if (cond.IsNotNever()) {
9751 EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9752 rn.GetCode() | (rm.GetCode() << 8));
9753 return;
9754 }
9755 }
9756 Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
9757}
9758
9759void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009760 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009761 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009762 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009763 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9764 EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9765 rm.GetCode());
9766 AdvanceIT();
9767 return;
9768 } else {
9769 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9770 if (cond.IsNotNever()) {
9771 EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9772 rn.GetCode() | (rm.GetCode() << 8));
9773 return;
9774 }
9775 }
9776 Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
9777}
9778
9779void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009780 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009781 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009783 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9784 EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9785 rm.GetCode());
9786 AdvanceIT();
9787 return;
9788 } else {
9789 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9790 if (cond.IsNotNever()) {
9791 EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9792 rn.GetCode() | (rm.GetCode() << 8));
9793 return;
9794 }
9795 }
9796 Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
9797}
9798
9799void Assembler::ssat(Condition cond,
9800 Register rd,
9801 uint32_t imm,
9802 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009803 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009804 CheckIT(cond);
9805 if (operand.IsImmediateShiftedRegister()) {
9806 Register rn = operand.GetBaseRegister();
9807 Shift shift = operand.GetShift();
9808 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009809 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009810 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
9811 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
9812 (amount <= 31)) {
9813 uint32_t imm_ = imm - 1;
9814 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
9815 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
9816 ((amount & 0x1c) << 10));
9817 AdvanceIT();
9818 return;
9819 }
9820 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
9821 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31)) {
9822 uint32_t imm_ = imm - 1;
9823 EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
9824 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
9825 ((amount & 0x1c) << 10));
9826 AdvanceIT();
9827 return;
9828 }
9829 } else {
9830 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
9831 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
9832 (amount <= 32) && cond.IsNotNever()) {
9833 uint32_t imm_ = imm - 1;
9834 uint32_t amount_ = amount % 32;
9835 EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
9836 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
9837 (amount_ << 7));
9838 return;
9839 }
9840 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
9841 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
9842 cond.IsNotNever()) {
9843 uint32_t imm_ = imm - 1;
9844 EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
9845 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
9846 (amount << 7));
9847 return;
9848 }
9849 }
9850 }
9851 Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
9852}
9853
9854void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009855 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009856 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009857 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009858 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
9859 if ((imm >= 1) && (imm <= 16)) {
9860 uint32_t imm_ = imm - 1;
9861 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
9862 (rn.GetCode() << 16));
9863 AdvanceIT();
9864 return;
9865 }
9866 } else {
9867 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
9868 if ((imm >= 1) && (imm <= 16) && cond.IsNotNever()) {
9869 uint32_t imm_ = imm - 1;
9870 EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9871 (imm_ << 16) | rn.GetCode());
9872 return;
9873 }
9874 }
9875 Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
9876}
9877
9878void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009879 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009880 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009881 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009882 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9883 EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9884 rm.GetCode());
9885 AdvanceIT();
9886 return;
9887 } else {
9888 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9889 if (cond.IsNotNever()) {
9890 EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9891 (rn.GetCode() << 16) | rm.GetCode());
9892 return;
9893 }
9894 }
9895 Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
9896}
9897
9898void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009899 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009900 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009901 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009902 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9903 EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9904 rm.GetCode());
9905 AdvanceIT();
9906 return;
9907 } else {
9908 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9909 if (cond.IsNotNever()) {
9910 EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9911 (rn.GetCode() << 16) | rm.GetCode());
9912 return;
9913 }
9914 }
9915 Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
9916}
9917
9918void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009919 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009920 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009921 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009922 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
9923 EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9924 rm.GetCode());
9925 AdvanceIT();
9926 return;
9927 } else {
9928 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
9929 if (cond.IsNotNever()) {
9930 EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9931 (rn.GetCode() << 16) | rm.GetCode());
9932 return;
9933 }
9934 }
9935 Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
9936}
9937
9938void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009939 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009940 CheckIT(cond);
9941 if (operand.IsImmediateZero()) {
9942 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009944 // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
9945 if ((operand.GetAddrMode() == Offset) &&
9946 ((!rn.IsPC()) || AllowUnpredictable())) {
9947 EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
9948 AdvanceIT();
9949 return;
9950 }
9951 } else {
9952 // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
9953 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
9954 ((!rn.IsPC()) || AllowUnpredictable())) {
9955 EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
9956 (rn.GetCode() << 16));
9957 return;
9958 }
9959 }
9960 }
9961 Delegate(kStl, &Assembler::stl, cond, rt, operand);
9962}
9963
9964void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009965 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009966 CheckIT(cond);
9967 if (operand.IsImmediateZero()) {
9968 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009969 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009970 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
9971 if ((operand.GetAddrMode() == Offset) &&
9972 ((!rn.IsPC()) || AllowUnpredictable())) {
9973 EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
9974 AdvanceIT();
9975 return;
9976 }
9977 } else {
9978 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
9979 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
9980 ((!rn.IsPC()) || AllowUnpredictable())) {
9981 EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
9982 (rn.GetCode() << 16));
9983 return;
9984 }
9985 }
9986 }
9987 Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
9988}
9989
9990void Assembler::stlex(Condition cond,
9991 Register rd,
9992 Register rt,
9993 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009994 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009995 CheckIT(cond);
9996 if (operand.IsImmediateZero()) {
9997 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009998 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009999 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10000 if ((operand.GetAddrMode() == Offset) &&
10001 ((!rn.IsPC()) || AllowUnpredictable())) {
10002 EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
10003 (rn.GetCode() << 16));
10004 AdvanceIT();
10005 return;
10006 }
10007 } else {
10008 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10009 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10010 ((!rn.IsPC()) || AllowUnpredictable())) {
10011 EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
10012 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10013 return;
10014 }
10015 }
10016 }
10017 Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
10018}
10019
10020void Assembler::stlexb(Condition cond,
10021 Register rd,
10022 Register rt,
10023 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010024 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010025 CheckIT(cond);
10026 if (operand.IsImmediateZero()) {
10027 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010028 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010029 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10030 if ((operand.GetAddrMode() == Offset) &&
10031 ((!rn.IsPC()) || AllowUnpredictable())) {
10032 EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
10033 (rn.GetCode() << 16));
10034 AdvanceIT();
10035 return;
10036 }
10037 } else {
10038 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10039 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10040 ((!rn.IsPC()) || AllowUnpredictable())) {
10041 EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
10042 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10043 return;
10044 }
10045 }
10046 }
10047 Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
10048}
10049
10050void Assembler::stlexd(Condition cond,
10051 Register rd,
10052 Register rt,
10053 Register rt2,
10054 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010055 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010056 CheckIT(cond);
10057 if (operand.IsImmediateZero()) {
10058 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010059 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010060 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
10061 if ((operand.GetAddrMode() == Offset) &&
10062 ((!rn.IsPC()) || AllowUnpredictable())) {
10063 EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
10064 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
10065 AdvanceIT();
10066 return;
10067 }
10068 } else {
10069 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
10070 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10071 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10072 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
10073 AllowUnpredictable())) {
10074 EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
10075 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10076 return;
10077 }
10078 }
10079 }
10080 Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
10081}
10082
10083void Assembler::stlexh(Condition cond,
10084 Register rd,
10085 Register rt,
10086 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010087 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010088 CheckIT(cond);
10089 if (operand.IsImmediateZero()) {
10090 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010091 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010092 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10093 if ((operand.GetAddrMode() == Offset) &&
10094 ((!rn.IsPC()) || AllowUnpredictable())) {
10095 EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
10096 (rn.GetCode() << 16));
10097 AdvanceIT();
10098 return;
10099 }
10100 } else {
10101 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10102 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10103 ((!rn.IsPC()) || AllowUnpredictable())) {
10104 EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
10105 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10106 return;
10107 }
10108 }
10109 }
10110 Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
10111}
10112
10113void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010114 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010115 CheckIT(cond);
10116 if (operand.IsImmediateZero()) {
10117 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010118 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010119 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
10120 if ((operand.GetAddrMode() == Offset) &&
10121 ((!rn.IsPC()) || AllowUnpredictable())) {
10122 EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10123 AdvanceIT();
10124 return;
10125 }
10126 } else {
10127 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
10128 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10129 ((!rn.IsPC()) || AllowUnpredictable())) {
10130 EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10131 (rn.GetCode() << 16));
10132 return;
10133 }
10134 }
10135 }
10136 Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
10137}
10138
10139void Assembler::stm(Condition cond,
10140 EncodingSize size,
10141 Register rn,
10142 WriteBack write_back,
10143 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010144 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010145 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010146 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010147 // STM{<c>}{<q>} <Rn>!, <registers> ; T1
10148 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
10149 ((registers.GetList() & ~0xff) == 0)) {
10150 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
10151 GetRegisterListEncoding(registers, 0, 8));
10152 AdvanceIT();
10153 return;
10154 }
10155 // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
10156 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10157 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10158 (write_back.GetWriteBackUint32() << 21) |
10159 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10160 GetRegisterListEncoding(registers, 0, 13));
10161 AdvanceIT();
10162 return;
10163 }
10164 } else {
10165 // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
10166 if (cond.IsNotNever()) {
10167 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10168 (write_back.GetWriteBackUint32() << 21) |
10169 GetRegisterListEncoding(registers, 0, 16));
10170 return;
10171 }
10172 }
10173 Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
10174}
10175
10176void Assembler::stmda(Condition cond,
10177 Register rn,
10178 WriteBack write_back,
10179 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010180 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010181 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010182 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010183 // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10184 if (cond.IsNotNever()) {
10185 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10186 (write_back.GetWriteBackUint32() << 21) |
10187 GetRegisterListEncoding(registers, 0, 16));
10188 return;
10189 }
10190 }
10191 Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
10192}
10193
10194void Assembler::stmdb(Condition cond,
10195 EncodingSize size,
10196 Register rn,
10197 WriteBack write_back,
10198 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010199 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010200 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010201 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010202 // STMDB{<c>}{<q>} SP!, <registers> ; T1
10203 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
10204 ((registers.GetList() & ~0x40ff) == 0)) {
10205 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
10206 GetRegisterListEncoding(registers, 0, 8));
10207 AdvanceIT();
10208 return;
10209 }
10210 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
10211 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10212 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
10213 (write_back.GetWriteBackUint32() << 21) |
10214 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10215 GetRegisterListEncoding(registers, 0, 13));
10216 AdvanceIT();
10217 return;
10218 }
10219 } else {
10220 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
10221 if (cond.IsNotNever()) {
10222 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10223 (write_back.GetWriteBackUint32() << 21) |
10224 GetRegisterListEncoding(registers, 0, 16));
10225 return;
10226 }
10227 }
10228 Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
10229}
10230
10231void Assembler::stmea(Condition cond,
10232 EncodingSize size,
10233 Register rn,
10234 WriteBack write_back,
10235 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010236 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010237 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010238 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010239 // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
10240 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
10241 ((registers.GetList() & ~0xff) == 0)) {
10242 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
10243 GetRegisterListEncoding(registers, 0, 8));
10244 AdvanceIT();
10245 return;
10246 }
10247 // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
10248 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10249 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10250 (write_back.GetWriteBackUint32() << 21) |
10251 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10252 GetRegisterListEncoding(registers, 0, 13));
10253 AdvanceIT();
10254 return;
10255 }
10256 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
10257 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
10258 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
10259 (write_back.GetWriteBackUint32() << 21) |
10260 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10261 GetRegisterListEncoding(registers, 0, 13));
10262 AdvanceIT();
10263 return;
10264 }
10265 } else {
10266 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10267 if (cond.IsNotNever()) {
10268 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10269 (write_back.GetWriteBackUint32() << 21) |
10270 GetRegisterListEncoding(registers, 0, 16));
10271 return;
10272 }
10273 }
10274 Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
10275}
10276
10277void Assembler::stmed(Condition cond,
10278 Register rn,
10279 WriteBack write_back,
10280 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010281 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010282 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010283 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010284 // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
10285 if (cond.IsNotNever()) {
10286 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10287 (write_back.GetWriteBackUint32() << 21) |
10288 GetRegisterListEncoding(registers, 0, 16));
10289 return;
10290 }
10291 }
10292 Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
10293}
10294
10295void Assembler::stmfa(Condition cond,
10296 Register rn,
10297 WriteBack write_back,
10298 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010299 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010300 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010301 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010302 // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
10303 if (cond.IsNotNever()) {
10304 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10305 (write_back.GetWriteBackUint32() << 21) |
10306 GetRegisterListEncoding(registers, 0, 16));
10307 return;
10308 }
10309 }
10310 Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
10311}
10312
10313void Assembler::stmfd(Condition cond,
10314 Register rn,
10315 WriteBack write_back,
10316 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010317 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010318 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010320 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
10321 if (((registers.GetList() & ~0x5fff) == 0)) {
10322 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
10323 (write_back.GetWriteBackUint32() << 21) |
10324 (GetRegisterListEncoding(registers, 14, 1) << 14) |
10325 GetRegisterListEncoding(registers, 0, 13));
10326 AdvanceIT();
10327 return;
10328 }
10329 } else {
10330 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
10331 if (cond.IsNotNever()) {
10332 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10333 (write_back.GetWriteBackUint32() << 21) |
10334 GetRegisterListEncoding(registers, 0, 16));
10335 return;
10336 }
10337 }
10338 Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
10339}
10340
10341void Assembler::stmib(Condition cond,
10342 Register rn,
10343 WriteBack write_back,
10344 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010345 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010346 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010347 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010348 // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
10349 if (cond.IsNotNever()) {
10350 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
10351 (write_back.GetWriteBackUint32() << 21) |
10352 GetRegisterListEncoding(registers, 0, 16));
10353 return;
10354 }
10355 }
10356 Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
10357}
10358
10359void Assembler::str(Condition cond,
10360 EncodingSize size,
10361 Register rt,
10362 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010363 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010364 CheckIT(cond);
10365 if (operand.IsImmediate()) {
10366 Register rn = operand.GetBaseRegister();
10367 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010368 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010369 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10370 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10371 (offset <= 124) && ((offset % 4) == 0) &&
10372 (operand.GetAddrMode() == Offset)) {
10373 int32_t offset_ = offset >> 2;
10374 EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
10375 ((offset_ & 0x1f) << 6));
10376 AdvanceIT();
10377 return;
10378 }
10379 // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
10380 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
10381 ((offset % 4) == 0) && rn.Is(sp) &&
10382 (operand.GetAddrMode() == Offset)) {
10383 int32_t offset_ = offset >> 2;
10384 EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
10385 AdvanceIT();
10386 return;
10387 }
10388 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
10389 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10390 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10391 EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10392 (offset & 0xfff));
10393 AdvanceIT();
10394 return;
10395 }
10396 // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
10397 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10398 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10399 EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10400 (-offset & 0xff));
10401 AdvanceIT();
10402 return;
10403 }
10404 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
10405 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10406 (operand.GetAddrMode() == PostIndex) &&
10407 ((rn.GetCode() & 0xf) != 0xf)) {
10408 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10409 uint32_t offset_ = abs(offset);
10410 EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10411 offset_ | (sign << 9));
10412 AdvanceIT();
10413 return;
10414 }
10415 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
10416 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10417 (operand.GetAddrMode() == PreIndex) &&
10418 ((rn.GetCode() & 0xf) != 0xf)) {
10419 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10420 uint32_t offset_ = abs(offset);
10421 EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10422 offset_ | (sign << 9));
10423 AdvanceIT();
10424 return;
10425 }
10426 } else {
10427 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10428 if ((offset >= -4095) && (offset <= 4095) &&
10429 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
10430 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10431 uint32_t offset_ = abs(offset);
10432 EmitA32(0x05000000U | (cond.GetCondition() << 28) |
10433 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10434 (sign << 23));
10435 return;
10436 }
10437 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10438 if ((offset >= -4095) && (offset <= 4095) &&
10439 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
10440 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10441 uint32_t offset_ = abs(offset);
10442 EmitA32(0x04000000U | (cond.GetCondition() << 28) |
10443 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10444 (sign << 23));
10445 return;
10446 }
10447 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10448 if ((offset >= -4095) && (offset <= 4095) &&
10449 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
10450 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10451 uint32_t offset_ = abs(offset);
10452 EmitA32(0x05200000U | (cond.GetCondition() << 28) |
10453 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10454 (sign << 23));
10455 return;
10456 }
10457 }
10458 }
10459 if (operand.IsPlainRegister()) {
10460 Register rn = operand.GetBaseRegister();
10461 Sign sign = operand.GetSign();
10462 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010463 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010464 // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
10465 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
10466 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
10467 EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
10468 (rm.GetCode() << 6));
10469 AdvanceIT();
10470 return;
10471 }
10472 }
10473 }
10474 if (operand.IsShiftedRegister()) {
10475 Register rn = operand.GetBaseRegister();
10476 Sign sign = operand.GetSign();
10477 Register rm = operand.GetOffsetRegister();
10478 Shift shift = operand.GetShift();
10479 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010480 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010481 // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
10482 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
10483 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10484 EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10485 rm.GetCode() | (amount << 4));
10486 AdvanceIT();
10487 return;
10488 }
10489 } else {
10490 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
10491 if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
10492 cond.IsNotNever()) {
10493 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10494 uint32_t shift_ = TypeEncodingValue(shift);
10495 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10496 EmitA32(0x07000000U | (cond.GetCondition() << 28) |
10497 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10498 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10499 return;
10500 }
10501 // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
10502 if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
10503 cond.IsNotNever()) {
10504 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10505 uint32_t shift_ = TypeEncodingValue(shift);
10506 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10507 EmitA32(0x06000000U | (cond.GetCondition() << 28) |
10508 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10509 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10510 return;
10511 }
10512 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
10513 if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
10514 cond.IsNotNever()) {
10515 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10516 uint32_t shift_ = TypeEncodingValue(shift);
10517 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10518 EmitA32(0x07200000U | (cond.GetCondition() << 28) |
10519 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10520 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10521 return;
10522 }
10523 }
10524 }
10525 Delegate(kStr, &Assembler::str, cond, size, rt, operand);
10526}
10527
10528void Assembler::strb(Condition cond,
10529 EncodingSize size,
10530 Register rt,
10531 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010532 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010533 CheckIT(cond);
10534 if (operand.IsImmediate()) {
10535 Register rn = operand.GetBaseRegister();
10536 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010537 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010538 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10539 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10540 (offset <= 31) && (operand.GetAddrMode() == Offset)) {
10541 EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
10542 ((offset & 0x1f) << 6));
10543 AdvanceIT();
10544 return;
10545 }
10546 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
10547 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10548 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10549 EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10550 (offset & 0xfff));
10551 AdvanceIT();
10552 return;
10553 }
10554 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
10555 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10556 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10557 EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10558 (-offset & 0xff));
10559 AdvanceIT();
10560 return;
10561 }
10562 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
10563 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10564 (operand.GetAddrMode() == PostIndex) &&
10565 ((rn.GetCode() & 0xf) != 0xf)) {
10566 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10567 uint32_t offset_ = abs(offset);
10568 EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10569 offset_ | (sign << 9));
10570 AdvanceIT();
10571 return;
10572 }
10573 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
10574 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10575 (operand.GetAddrMode() == PreIndex) &&
10576 ((rn.GetCode() & 0xf) != 0xf)) {
10577 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10578 uint32_t offset_ = abs(offset);
10579 EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10580 offset_ | (sign << 9));
10581 AdvanceIT();
10582 return;
10583 }
10584 } else {
10585 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10586 if ((offset >= -4095) && (offset <= 4095) &&
10587 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
10588 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10589 uint32_t offset_ = abs(offset);
10590 EmitA32(0x05400000U | (cond.GetCondition() << 28) |
10591 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10592 (sign << 23));
10593 return;
10594 }
10595 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
10596 if ((offset >= -4095) && (offset <= 4095) &&
10597 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
10598 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10599 uint32_t offset_ = abs(offset);
10600 EmitA32(0x04400000U | (cond.GetCondition() << 28) |
10601 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10602 (sign << 23));
10603 return;
10604 }
10605 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
10606 if ((offset >= -4095) && (offset <= 4095) &&
10607 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
10608 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10609 uint32_t offset_ = abs(offset);
10610 EmitA32(0x05600000U | (cond.GetCondition() << 28) |
10611 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
10612 (sign << 23));
10613 return;
10614 }
10615 }
10616 }
10617 if (operand.IsPlainRegister()) {
10618 Register rn = operand.GetBaseRegister();
10619 Sign sign = operand.GetSign();
10620 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010621 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010622 // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
10623 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
10624 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
10625 EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
10626 (rm.GetCode() << 6));
10627 AdvanceIT();
10628 return;
10629 }
10630 }
10631 }
10632 if (operand.IsShiftedRegister()) {
10633 Register rn = operand.GetBaseRegister();
10634 Sign sign = operand.GetSign();
10635 Register rm = operand.GetOffsetRegister();
10636 Shift shift = operand.GetShift();
10637 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010638 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010639 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
10640 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
10641 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10642 EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10643 rm.GetCode() | (amount << 4));
10644 AdvanceIT();
10645 return;
10646 }
10647 } else {
10648 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
10649 if (operand.IsShiftValid() && (operand.GetAddrMode() == Offset) &&
10650 cond.IsNotNever()) {
10651 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10652 uint32_t shift_ = TypeEncodingValue(shift);
10653 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10654 EmitA32(0x07400000U | (cond.GetCondition() << 28) |
10655 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10656 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10657 return;
10658 }
10659 // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
10660 if (operand.IsShiftValid() && (operand.GetAddrMode() == PostIndex) &&
10661 cond.IsNotNever()) {
10662 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10663 uint32_t shift_ = TypeEncodingValue(shift);
10664 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10665 EmitA32(0x06400000U | (cond.GetCondition() << 28) |
10666 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10667 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10668 return;
10669 }
10670 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
10671 if (operand.IsShiftValid() && (operand.GetAddrMode() == PreIndex) &&
10672 cond.IsNotNever()) {
10673 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10674 uint32_t shift_ = TypeEncodingValue(shift);
10675 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
10676 EmitA32(0x07600000U | (cond.GetCondition() << 28) |
10677 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10678 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
10679 return;
10680 }
10681 }
10682 }
10683 Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
10684}
10685
10686void Assembler::strd(Condition cond,
10687 Register rt,
10688 Register rt2,
10689 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010690 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010691 CheckIT(cond);
10692 if (operand.IsImmediate()) {
10693 Register rn = operand.GetBaseRegister();
10694 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010695 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010696 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
10697 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10698 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10699 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10700 uint32_t offset_ = abs(offset) >> 2;
10701 EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10702 (rn.GetCode() << 16) | offset_ | (sign << 23));
10703 AdvanceIT();
10704 return;
10705 }
10706 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
10707 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10708 (operand.GetAddrMode() == PostIndex) &&
10709 ((rn.GetCode() & 0xf) != 0xf)) {
10710 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10711 uint32_t offset_ = abs(offset) >> 2;
10712 EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10713 (rn.GetCode() << 16) | offset_ | (sign << 23));
10714 AdvanceIT();
10715 return;
10716 }
10717 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
10718 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
10719 (operand.GetAddrMode() == PreIndex) &&
10720 ((rn.GetCode() & 0xf) != 0xf)) {
10721 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10722 uint32_t offset_ = abs(offset) >> 2;
10723 EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
10724 (rn.GetCode() << 16) | offset_ | (sign << 23));
10725 AdvanceIT();
10726 return;
10727 }
10728 } else {
10729 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
10730 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10731 (offset >= -255) && (offset <= 255) &&
10732 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10733 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10734 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10735 uint32_t offset_ = abs(offset);
10736 EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
10737 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10738 ((offset_ & 0xf0) << 4) | (sign << 23));
10739 return;
10740 }
10741 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
10742 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10743 (offset >= -255) && (offset <= 255) &&
10744 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
10745 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10746 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10747 uint32_t offset_ = abs(offset);
10748 EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
10749 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10750 ((offset_ & 0xf0) << 4) | (sign << 23));
10751 return;
10752 }
10753 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
10754 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10755 (offset >= -255) && (offset <= 255) &&
10756 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
10757 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10758 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10759 uint32_t offset_ = abs(offset);
10760 EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
10761 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10762 ((offset_ & 0xf0) << 4) | (sign << 23));
10763 return;
10764 }
10765 }
10766 }
10767 if (operand.IsPlainRegister()) {
10768 Register rn = operand.GetBaseRegister();
10769 Sign sign = operand.GetSign();
10770 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010771 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010772 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
10773 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10774 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10775 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10776 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10777 EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
10778 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10779 (sign_ << 23));
10780 return;
10781 }
10782 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
10783 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10784 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever() &&
10785 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10786 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10787 EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
10788 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10789 (sign_ << 23));
10790 return;
10791 }
10792 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
10793 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10794 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever() &&
10795 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0)) || AllowUnpredictable())) {
10796 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
10797 EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
10798 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
10799 (sign_ << 23));
10800 return;
10801 }
10802 }
10803 }
10804 Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
10805}
10806
10807void Assembler::strex(Condition cond,
10808 Register rd,
10809 Register rt,
10810 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010811 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010812 CheckIT(cond);
10813 if (operand.IsImmediate()) {
10814 Register rn = operand.GetBaseRegister();
10815 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010816 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010817 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
10818 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
10819 (operand.GetAddrMode() == Offset)) {
10820 int32_t offset_ = offset >> 2;
10821 EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
10822 (rn.GetCode() << 16) | (offset_ & 0xff));
10823 AdvanceIT();
10824 return;
10825 }
10826 } else {
10827 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
10828 if ((offset == 0) && (operand.GetAddrMode() == Offset) &&
10829 cond.IsNotNever()) {
10830 EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
10831 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10832 return;
10833 }
10834 }
10835 }
10836 Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
10837}
10838
10839void Assembler::strexb(Condition cond,
10840 Register rd,
10841 Register rt,
10842 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010843 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010844 CheckIT(cond);
10845 if (operand.IsImmediateZero()) {
10846 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010847 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010848 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10849 if ((operand.GetAddrMode() == Offset) &&
10850 ((!rn.IsPC()) || AllowUnpredictable())) {
10851 EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
10852 (rn.GetCode() << 16));
10853 AdvanceIT();
10854 return;
10855 }
10856 } else {
10857 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10858 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10859 ((!rn.IsPC()) || AllowUnpredictable())) {
10860 EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
10861 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10862 return;
10863 }
10864 }
10865 }
10866 Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
10867}
10868
10869void Assembler::strexd(Condition cond,
10870 Register rd,
10871 Register rt,
10872 Register rt2,
10873 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010874 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010875 CheckIT(cond);
10876 if (operand.IsImmediateZero()) {
10877 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010878 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010879 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
10880 if ((operand.GetAddrMode() == Offset) &&
10881 ((!rn.IsPC()) || AllowUnpredictable())) {
10882 EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
10883 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
10884 AdvanceIT();
10885 return;
10886 }
10887 } else {
10888 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
10889 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
10890 (operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10891 ((!rt.IsLR() && ((rt.GetCode() & 1) == 0) && !rn.IsPC()) ||
10892 AllowUnpredictable())) {
10893 EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
10894 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10895 return;
10896 }
10897 }
10898 }
10899 Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
10900}
10901
10902void Assembler::strexh(Condition cond,
10903 Register rd,
10904 Register rt,
10905 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010906 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010907 CheckIT(cond);
10908 if (operand.IsImmediateZero()) {
10909 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010910 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010911 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
10912 if ((operand.GetAddrMode() == Offset) &&
10913 ((!rn.IsPC()) || AllowUnpredictable())) {
10914 EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
10915 (rn.GetCode() << 16));
10916 AdvanceIT();
10917 return;
10918 }
10919 } else {
10920 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
10921 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever() &&
10922 ((!rn.IsPC()) || AllowUnpredictable())) {
10923 EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
10924 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10925 return;
10926 }
10927 }
10928 }
10929 Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
10930}
10931
10932void Assembler::strh(Condition cond,
10933 EncodingSize size,
10934 Register rt,
10935 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010936 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010937 CheckIT(cond);
10938 if (operand.IsImmediate()) {
10939 Register rn = operand.GetBaseRegister();
10940 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010941 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010942 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
10943 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
10944 (offset <= 62) && ((offset % 2) == 0) &&
10945 (operand.GetAddrMode() == Offset)) {
10946 int32_t offset_ = offset >> 1;
10947 EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
10948 ((offset_ & 0x1f) << 6));
10949 AdvanceIT();
10950 return;
10951 }
10952 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
10953 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
10954 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10955 EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10956 (offset & 0xfff));
10957 AdvanceIT();
10958 return;
10959 }
10960 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
10961 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
10962 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
10963 EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10964 (-offset & 0xff));
10965 AdvanceIT();
10966 return;
10967 }
10968 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
10969 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10970 (operand.GetAddrMode() == PostIndex) &&
10971 ((rn.GetCode() & 0xf) != 0xf)) {
10972 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10973 uint32_t offset_ = abs(offset);
10974 EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10975 offset_ | (sign << 9));
10976 AdvanceIT();
10977 return;
10978 }
10979 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
10980 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
10981 (operand.GetAddrMode() == PreIndex) &&
10982 ((rn.GetCode() & 0xf) != 0xf)) {
10983 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10984 uint32_t offset_ = abs(offset);
10985 EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
10986 offset_ | (sign << 9));
10987 AdvanceIT();
10988 return;
10989 }
10990 } else {
10991 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
10992 if ((offset >= -255) && (offset <= 255) &&
10993 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
10994 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
10995 uint32_t offset_ = abs(offset);
10996 EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
10997 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
10998 ((offset_ & 0xf0) << 4) | (sign << 23));
10999 return;
11000 }
11001 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
11002 if ((offset >= -255) && (offset <= 255) &&
11003 (operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
11004 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11005 uint32_t offset_ = abs(offset);
11006 EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
11007 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11008 ((offset_ & 0xf0) << 4) | (sign << 23));
11009 return;
11010 }
11011 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
11012 if ((offset >= -255) && (offset <= 255) &&
11013 (operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
11014 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11015 uint32_t offset_ = abs(offset);
11016 EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
11017 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11018 ((offset_ & 0xf0) << 4) | (sign << 23));
11019 return;
11020 }
11021 }
11022 }
11023 if (operand.IsPlainRegister()) {
11024 Register rn = operand.GetBaseRegister();
11025 Sign sign = operand.GetSign();
11026 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011027 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011028 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11029 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
11030 sign.IsPlus() && (operand.GetAddrMode() == Offset)) {
11031 EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
11032 (rm.GetCode() << 6));
11033 AdvanceIT();
11034 return;
11035 }
11036 } else {
11037 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
11038 if ((operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
11039 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11040 EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
11041 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11042 (sign_ << 23));
11043 return;
11044 }
11045 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
11046 if ((operand.GetAddrMode() == PostIndex) && cond.IsNotNever()) {
11047 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11048 EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
11049 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11050 (sign_ << 23));
11051 return;
11052 }
11053 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
11054 if ((operand.GetAddrMode() == PreIndex) && cond.IsNotNever()) {
11055 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11056 EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
11057 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11058 (sign_ << 23));
11059 return;
11060 }
11061 }
11062 }
11063 if (operand.IsShiftedRegister()) {
11064 Register rn = operand.GetBaseRegister();
11065 Sign sign = operand.GetSign();
11066 Register rm = operand.GetOffsetRegister();
11067 Shift shift = operand.GetShift();
11068 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011069 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011070 // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11071 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
11072 (operand.GetAddrMode() == Offset) && ((rn.GetCode() & 0xf) != 0xf)) {
11073 EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11074 rm.GetCode() | (amount << 4));
11075 AdvanceIT();
11076 return;
11077 }
11078 }
11079 }
11080 Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
11081}
11082
11083void Assembler::sub(Condition cond,
11084 EncodingSize size,
11085 Register rd,
11086 Register rn,
11087 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011088 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011089 CheckIT(cond);
11090 if (operand.IsImmediate()) {
11091 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011092 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011093 ImmediateT32 immediate_t32(imm);
11094 // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
11095 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11096 (imm <= 7)) {
11097 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
11098 AdvanceIT();
11099 return;
11100 }
11101 // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
11102 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
11103 (imm <= 255)) {
11104 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11105 AdvanceIT();
11106 return;
11107 }
11108 // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
11109 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
11110 ((imm % 4) == 0)) {
11111 uint32_t imm_ = imm >> 2;
11112 EmitT32_16(0xb080 | imm_);
11113 AdvanceIT();
11114 return;
11115 }
11116 // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
11117 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) {
11118 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11119 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11120 AdvanceIT();
11121 return;
11122 }
11123 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
11124 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp)) {
11125 EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11126 (immediate_t32.GetEncodingValue() & 0xff) |
11127 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11128 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11129 AdvanceIT();
11130 return;
11131 }
11132 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
11133 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
11134 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11135 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11136 AdvanceIT();
11137 return;
11138 }
11139 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
11140 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid()) {
11141 EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
11142 (immediate_t32.GetEncodingValue() & 0xff) |
11143 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11144 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11145 AdvanceIT();
11146 return;
11147 }
11148 // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
11149 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095)) {
11150 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11151 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11152 AdvanceIT();
11153 return;
11154 }
11155 } else {
11156 ImmediateA32 immediate_a32(imm);
11157 // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
11158 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
11159 EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
11160 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11161 return;
11162 }
11163 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
11164 if (immediate_a32.IsValid() && cond.IsNotNever() &&
11165 ((rn.GetCode() & 0xd) != 0xd)) {
11166 EmitA32(0x02400000U | (cond.GetCondition() << 28) |
11167 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
11168 immediate_a32.GetEncodingValue());
11169 return;
11170 }
11171 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
11172 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
11173 EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
11174 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11175 return;
11176 }
11177 }
11178 }
11179 if (operand.IsImmediateShiftedRegister()) {
11180 Register rm = operand.GetBaseRegister();
11181 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011182 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011183 // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
11184 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11185 rm.IsLow()) {
11186 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
11187 (rm.GetCode() << 6));
11188 AdvanceIT();
11189 return;
11190 }
11191 // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
11192 if (rn.Is(sp)) {
11193 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
11194 AdvanceIT();
11195 return;
11196 }
11197 }
11198 }
11199 Shift shift = operand.GetShift();
11200 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011201 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011202 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
11203 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp)) {
11204 uint32_t amount_ = amount % 32;
11205 EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11206 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
11207 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11208 AdvanceIT();
11209 return;
11210 }
11211 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
11212 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount)) {
11213 uint32_t amount_ = amount % 32;
11214 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
11215 (operand.GetTypeEncodingValue() << 4) |
11216 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11217 AdvanceIT();
11218 return;
11219 }
11220 } else {
11221 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
11222 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
11223 uint32_t amount_ = amount % 32;
11224 EmitA32(0x00400000U | (cond.GetCondition() << 28) |
11225 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11226 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11227 return;
11228 }
11229 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
11230 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
11231 uint32_t amount_ = amount % 32;
11232 EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
11233 (rd.GetCode() << 12) | rm.GetCode() |
11234 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11235 return;
11236 }
11237 }
11238 }
11239 if (operand.IsRegisterShiftedRegister()) {
11240 Register rm = operand.GetBaseRegister();
11241 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011242 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011243 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
11244 if (cond.IsNotNever()) {
11245 EmitA32(0x00400010U | (cond.GetCondition() << 28) |
11246 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11247 (shift.GetType() << 5) |
11248 (operand.GetShiftRegister().GetCode() << 8));
11249 return;
11250 }
11251 }
11252 }
11253 Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
11254}
11255
11256void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011257 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011258 CheckIT(cond);
11259 if (operand.IsImmediate()) {
11260 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011261 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011262 // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
11263 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
11264 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11265 AdvanceIT();
11266 return;
11267 }
11268 }
11269 }
11270 Delegate(kSub, &Assembler::sub, cond, rd, operand);
11271}
11272
11273void Assembler::subs(Condition cond,
11274 EncodingSize size,
11275 Register rd,
11276 Register rn,
11277 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011278 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011279 CheckIT(cond);
11280 if (operand.IsImmediate()) {
11281 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011282 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011283 ImmediateT32 immediate_t32(imm);
11284 // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
11285 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11286 (imm <= 7)) {
11287 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
11288 AdvanceIT();
11289 return;
11290 }
11291 // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
11292 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
11293 (imm <= 255)) {
11294 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11295 AdvanceIT();
11296 return;
11297 }
11298 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
11299 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
11300 !rd.Is(pc)) {
11301 EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11302 (immediate_t32.GetEncodingValue() & 0xff) |
11303 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11304 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11305 AdvanceIT();
11306 return;
11307 }
11308 // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
11309 if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255)) {
11310 EmitT32_32(0xf3de8f00U | imm);
11311 AdvanceIT();
11312 return;
11313 }
11314 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
11315 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
11316 !rd.Is(pc)) {
11317 EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
11318 (immediate_t32.GetEncodingValue() & 0xff) |
11319 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11320 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11321 AdvanceIT();
11322 return;
11323 }
11324 } else {
11325 ImmediateA32 immediate_a32(imm);
11326 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
11327 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
11328 EmitA32(0x02500000U | (cond.GetCondition() << 28) |
11329 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
11330 immediate_a32.GetEncodingValue());
11331 return;
11332 }
11333 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
11334 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
11335 EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
11336 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
11337 return;
11338 }
11339 }
11340 }
11341 if (operand.IsImmediateShiftedRegister()) {
11342 Register rm = operand.GetBaseRegister();
11343 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011344 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011345 // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11346 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
11347 rm.IsLow()) {
11348 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
11349 (rm.GetCode() << 6));
11350 AdvanceIT();
11351 return;
11352 }
11353 }
11354 }
11355 Shift shift = operand.GetShift();
11356 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011357 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011358 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
11359 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
11360 !rd.Is(pc)) {
11361 uint32_t amount_ = amount % 32;
11362 EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11363 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
11364 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11365 AdvanceIT();
11366 return;
11367 }
11368 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
11369 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
11370 !rd.Is(pc)) {
11371 uint32_t amount_ = amount % 32;
11372 EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
11373 (operand.GetTypeEncodingValue() << 4) |
11374 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11375 AdvanceIT();
11376 return;
11377 }
11378 } else {
11379 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
11380 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
11381 uint32_t amount_ = amount % 32;
11382 EmitA32(0x00500000U | (cond.GetCondition() << 28) |
11383 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11384 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11385 return;
11386 }
11387 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
11388 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
11389 uint32_t amount_ = amount % 32;
11390 EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
11391 (rd.GetCode() << 12) | rm.GetCode() |
11392 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11393 return;
11394 }
11395 }
11396 }
11397 if (operand.IsRegisterShiftedRegister()) {
11398 Register rm = operand.GetBaseRegister();
11399 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011400 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011401 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
11402 if (cond.IsNotNever()) {
11403 EmitA32(0x00500010U | (cond.GetCondition() << 28) |
11404 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11405 (shift.GetType() << 5) |
11406 (operand.GetShiftRegister().GetCode() << 8));
11407 return;
11408 }
11409 }
11410 }
11411 Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
11412}
11413
11414void Assembler::subs(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011415 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011416 CheckIT(al);
11417 if (operand.IsImmediate()) {
11418 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011419 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011420 // SUBS{<q>} <Rdn>, #<imm8> ; T2
11421 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
11422 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
11423 AdvanceIT();
11424 return;
11425 }
11426 }
11427 }
11428 Delegate(kSubs, &Assembler::subs, rd, operand);
11429}
11430
11431void Assembler::subw(Condition cond,
11432 Register rd,
11433 Register rn,
11434 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011435 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011436 CheckIT(cond);
11437 if (operand.IsImmediate()) {
11438 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011439 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011440 // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
11441 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
11442 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11443 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11444 AdvanceIT();
11445 return;
11446 }
11447 // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
11448 if (rn.Is(sp) && (imm <= 4095)) {
11449 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
11450 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
11451 AdvanceIT();
11452 return;
11453 }
11454 }
11455 }
11456 Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
11457}
11458
11459void Assembler::svc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011460 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011461 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011462 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011463 // SVC{<c>}{<q>} {#}<imm> ; T1
11464 if ((imm <= 255)) {
11465 EmitT32_16(0xdf00 | imm);
11466 AdvanceIT();
11467 return;
11468 }
11469 } else {
11470 // SVC{<c>}{<q>} {#}<imm> ; A1
11471 if ((imm <= 16777215) && cond.IsNotNever()) {
11472 EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
11473 return;
11474 }
11475 }
11476 Delegate(kSvc, &Assembler::svc, cond, imm);
11477}
11478
11479void Assembler::sxtab(Condition cond,
11480 Register rd,
11481 Register rn,
11482 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011483 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011484 CheckIT(cond);
11485 if (operand.IsImmediateShiftedRegister()) {
11486 Register rm = operand.GetBaseRegister();
11487 Shift shift = operand.GetShift();
11488 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011489 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011490 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11491 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11492 ((amount % 8) == 0) && !rn.Is(pc)) {
11493 uint32_t amount_ = amount / 8;
11494 EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11495 rm.GetCode() | (amount_ << 4));
11496 AdvanceIT();
11497 return;
11498 }
11499 } else {
11500 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11501 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11502 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11503 uint32_t amount_ = amount / 8;
11504 EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
11505 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11506 (amount_ << 10));
11507 return;
11508 }
11509 }
11510 }
11511 Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
11512}
11513
11514void Assembler::sxtab16(Condition cond,
11515 Register rd,
11516 Register rn,
11517 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011518 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011519 CheckIT(cond);
11520 if (operand.IsImmediateShiftedRegister()) {
11521 Register rm = operand.GetBaseRegister();
11522 Shift shift = operand.GetShift();
11523 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011524 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011525 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11526 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11527 ((amount % 8) == 0) && !rn.Is(pc)) {
11528 uint32_t amount_ = amount / 8;
11529 EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11530 rm.GetCode() | (amount_ << 4));
11531 AdvanceIT();
11532 return;
11533 }
11534 } else {
11535 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11536 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11537 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11538 uint32_t amount_ = amount / 8;
11539 EmitA32(0x06800070U | (cond.GetCondition() << 28) |
11540 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11541 (amount_ << 10));
11542 return;
11543 }
11544 }
11545 }
11546 Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
11547}
11548
11549void Assembler::sxtah(Condition cond,
11550 Register rd,
11551 Register rn,
11552 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011553 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011554 CheckIT(cond);
11555 if (operand.IsImmediateShiftedRegister()) {
11556 Register rm = operand.GetBaseRegister();
11557 Shift shift = operand.GetShift();
11558 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011559 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011560 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
11561 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11562 ((amount % 8) == 0) && !rn.Is(pc)) {
11563 uint32_t amount_ = amount / 8;
11564 EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11565 rm.GetCode() | (amount_ << 4));
11566 AdvanceIT();
11567 return;
11568 }
11569 } else {
11570 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
11571 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11572 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
11573 uint32_t amount_ = amount / 8;
11574 EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
11575 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11576 (amount_ << 10));
11577 return;
11578 }
11579 }
11580 }
11581 Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
11582}
11583
11584void Assembler::sxtb(Condition cond,
11585 EncodingSize size,
11586 Register rd,
11587 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011588 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011589 CheckIT(cond);
11590 if (operand.IsImmediateShiftedRegister()) {
11591 Register rm = operand.GetBaseRegister();
11592 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011593 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011594 // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
11595 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
11596 EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
11597 AdvanceIT();
11598 return;
11599 }
11600 }
11601 }
11602 Shift shift = operand.GetShift();
11603 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011604 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011605 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
11606 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
11607 (amount <= 24) && ((amount % 8) == 0)) {
11608 uint32_t amount_ = amount / 8;
11609 EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11610 (amount_ << 4));
11611 AdvanceIT();
11612 return;
11613 }
11614 } else {
11615 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11616 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11617 ((amount % 8) == 0) && cond.IsNotNever()) {
11618 uint32_t amount_ = amount / 8;
11619 EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
11620 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11621 return;
11622 }
11623 }
11624 }
11625 Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
11626}
11627
11628void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011629 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011630 CheckIT(cond);
11631 if (operand.IsImmediateShiftedRegister()) {
11632 Register rm = operand.GetBaseRegister();
11633 Shift shift = operand.GetShift();
11634 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011635 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011636 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
11637 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11638 ((amount % 8) == 0)) {
11639 uint32_t amount_ = amount / 8;
11640 EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11641 (amount_ << 4));
11642 AdvanceIT();
11643 return;
11644 }
11645 } else {
11646 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11647 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11648 ((amount % 8) == 0) && cond.IsNotNever()) {
11649 uint32_t amount_ = amount / 8;
11650 EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
11651 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11652 return;
11653 }
11654 }
11655 }
11656 Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
11657}
11658
11659void Assembler::sxth(Condition cond,
11660 EncodingSize size,
11661 Register rd,
11662 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011663 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011664 CheckIT(cond);
11665 if (operand.IsImmediateShiftedRegister()) {
11666 Register rm = operand.GetBaseRegister();
11667 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011668 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011669 // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
11670 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
11671 EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
11672 AdvanceIT();
11673 return;
11674 }
11675 }
11676 }
11677 Shift shift = operand.GetShift();
11678 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011679 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011680 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
11681 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
11682 (amount <= 24) && ((amount % 8) == 0)) {
11683 uint32_t amount_ = amount / 8;
11684 EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
11685 (amount_ << 4));
11686 AdvanceIT();
11687 return;
11688 }
11689 } else {
11690 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
11691 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
11692 ((amount % 8) == 0) && cond.IsNotNever()) {
11693 uint32_t amount_ = amount / 8;
11694 EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
11695 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
11696 return;
11697 }
11698 }
11699 }
11700 Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
11701}
11702
11703void Assembler::tbb(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011704 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011705 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011706 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011707 // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
11708 if (OutsideITBlockAndAlOrLast(cond) &&
11709 ((!rm.IsPC()) || AllowUnpredictable())) {
11710 EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
11711 AdvanceIT();
11712 return;
11713 }
11714 }
11715 Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
11716}
11717
11718void Assembler::tbh(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011719 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011720 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011721 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011722 // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
11723 if (OutsideITBlockAndAlOrLast(cond) &&
11724 ((!rm.IsPC()) || AllowUnpredictable())) {
11725 EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
11726 AdvanceIT();
11727 return;
11728 }
11729 }
11730 Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
11731}
11732
11733void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011734 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011735 CheckIT(cond);
11736 if (operand.IsImmediate()) {
11737 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011738 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011739 ImmediateT32 immediate_t32(imm);
11740 // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
11741 if (immediate_t32.IsValid()) {
11742 EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
11743 (immediate_t32.GetEncodingValue() & 0xff) |
11744 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11745 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11746 AdvanceIT();
11747 return;
11748 }
11749 } else {
11750 ImmediateA32 immediate_a32(imm);
11751 // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
11752 if (immediate_a32.IsValid() && cond.IsNotNever()) {
11753 EmitA32(0x03300000U | (cond.GetCondition() << 28) |
11754 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
11755 return;
11756 }
11757 }
11758 }
11759 if (operand.IsImmediateShiftedRegister()) {
11760 Register rm = operand.GetBaseRegister();
11761 Shift shift = operand.GetShift();
11762 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011763 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011764 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
11765 if (shift.IsValidAmount(amount)) {
11766 uint32_t amount_ = amount % 32;
11767 EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
11768 (operand.GetTypeEncodingValue() << 4) |
11769 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11770 AdvanceIT();
11771 return;
11772 }
11773 } else {
11774 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
11775 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
11776 uint32_t amount_ = amount % 32;
11777 EmitA32(0x01300000U | (cond.GetCondition() << 28) |
11778 (rn.GetCode() << 16) | rm.GetCode() |
11779 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11780 return;
11781 }
11782 }
11783 }
11784 if (operand.IsRegisterShiftedRegister()) {
11785 Register rm = operand.GetBaseRegister();
11786 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011787 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011788 // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
11789 if (cond.IsNotNever()) {
11790 EmitA32(0x01300010U | (cond.GetCondition() << 28) |
11791 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
11792 (operand.GetShiftRegister().GetCode() << 8));
11793 return;
11794 }
11795 }
11796 }
11797 Delegate(kTeq, &Assembler::teq, cond, rn, operand);
11798}
11799
11800void Assembler::tst(Condition cond,
11801 EncodingSize size,
11802 Register rn,
11803 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011804 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011805 CheckIT(cond);
11806 if (operand.IsImmediate()) {
11807 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011808 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011809 ImmediateT32 immediate_t32(imm);
11810 // TST{<c>}{<q>} <Rn>, #<const> ; T1
11811 if (!size.IsNarrow() && immediate_t32.IsValid()) {
11812 EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
11813 (immediate_t32.GetEncodingValue() & 0xff) |
11814 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
11815 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
11816 AdvanceIT();
11817 return;
11818 }
11819 } else {
11820 ImmediateA32 immediate_a32(imm);
11821 // TST{<c>}{<q>} <Rn>, #<const> ; A1
11822 if (immediate_a32.IsValid() && cond.IsNotNever()) {
11823 EmitA32(0x03100000U | (cond.GetCondition() << 28) |
11824 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
11825 return;
11826 }
11827 }
11828 }
11829 if (operand.IsImmediateShiftedRegister()) {
11830 Register rm = operand.GetBaseRegister();
11831 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011833 // TST{<c>}{<q>} <Rn>, <Rm> ; T1
11834 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
11835 EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
11836 AdvanceIT();
11837 return;
11838 }
11839 }
11840 }
11841 Shift shift = operand.GetShift();
11842 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011844 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
11845 if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
11846 uint32_t amount_ = amount % 32;
11847 EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
11848 (operand.GetTypeEncodingValue() << 4) |
11849 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
11850 AdvanceIT();
11851 return;
11852 }
11853 } else {
11854 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
11855 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
11856 uint32_t amount_ = amount % 32;
11857 EmitA32(0x01100000U | (cond.GetCondition() << 28) |
11858 (rn.GetCode() << 16) | rm.GetCode() |
11859 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
11860 return;
11861 }
11862 }
11863 }
11864 if (operand.IsRegisterShiftedRegister()) {
11865 Register rm = operand.GetBaseRegister();
11866 Shift shift = operand.GetShift();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011867 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011868 // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
11869 if (cond.IsNotNever()) {
11870 EmitA32(0x01100010U | (cond.GetCondition() << 28) |
11871 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
11872 (operand.GetShiftRegister().GetCode() << 8));
11873 return;
11874 }
11875 }
11876 }
11877 Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
11878}
11879
11880void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011881 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011882 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011883 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011884 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11885 EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11886 rm.GetCode());
11887 AdvanceIT();
11888 return;
11889 } else {
11890 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11891 if (cond.IsNotNever()) {
11892 EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11893 (rn.GetCode() << 16) | rm.GetCode());
11894 return;
11895 }
11896 }
11897 Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
11898}
11899
11900void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011901 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011902 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011903 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011904 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11905 EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11906 rm.GetCode());
11907 AdvanceIT();
11908 return;
11909 } else {
11910 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11911 if (cond.IsNotNever()) {
11912 EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11913 (rn.GetCode() << 16) | rm.GetCode());
11914 return;
11915 }
11916 }
11917 Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
11918}
11919
11920void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011921 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011922 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011923 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011924 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
11925 EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11926 rm.GetCode());
11927 AdvanceIT();
11928 return;
11929 } else {
11930 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
11931 if (cond.IsNotNever()) {
11932 EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
11933 (rn.GetCode() << 16) | rm.GetCode());
11934 return;
11935 }
11936 }
11937 Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
11938}
11939
11940void Assembler::ubfx(Condition cond,
11941 Register rd,
11942 Register rn,
11943 uint32_t lsb,
11944 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011946 CheckIT(cond);
11947 if (operand.IsImmediate()) {
11948 uint32_t width = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011949 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011950 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
11951 if ((lsb <= 31) &&
11952 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
11953 uint32_t widthm1 = width - 1;
11954 EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
11955 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
11956 AdvanceIT();
11957 return;
11958 }
11959 } else {
11960 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
11961 if ((lsb <= 31) && cond.IsNotNever() &&
11962 (((width >= 1) && (width <= 32 - lsb)) || AllowUnpredictable())) {
11963 uint32_t widthm1 = width - 1;
11964 EmitA32(0x07e00050U | (cond.GetCondition() << 28) |
11965 (rd.GetCode() << 12) | rn.GetCode() | (lsb << 7) |
11966 (widthm1 << 16));
11967 return;
11968 }
11969 }
11970 }
11971 Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, operand);
11972}
11973
11974void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011975 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011976 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011977 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011978 // UDF{<c>}{<q>} {#}<imm> ; T1
11979 if (!size.IsWide() && (imm <= 255)) {
11980 if (cond.Is(al) || AllowStronglyDiscouraged()) {
11981 EmitT32_16(0xde00 | imm);
11982 AdvanceIT();
11983 return;
11984 }
11985 }
11986 // UDF{<c>}{<q>} {#}<imm> ; T2
11987 if (!size.IsNarrow() && (imm <= 65535)) {
11988 if (cond.Is(al) || AllowStronglyDiscouraged()) {
11989 EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
11990 AdvanceIT();
11991 return;
11992 }
11993 }
11994 } else {
11995 // UDF{<c>}{<q>} {#}<imm> ; A1
11996 if ((imm <= 65535)) {
11997 if (cond.Is(al) || AllowStronglyDiscouraged()) {
11998 EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
11999 return;
12000 }
12001 }
12002 }
12003 Delegate(kUdf, &Assembler::udf, cond, size, imm);
12004}
12005
12006void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012007 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012008 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012009 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012010 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12011 EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12012 rm.GetCode());
12013 AdvanceIT();
12014 return;
12015 } else {
12016 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12017 if (cond.IsNotNever()) {
12018 EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12019 rn.GetCode() | (rm.GetCode() << 8));
12020 return;
12021 }
12022 }
12023 Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
12024}
12025
12026void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012027 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012028 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012029 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012030 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12031 EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12032 rm.GetCode());
12033 AdvanceIT();
12034 return;
12035 } else {
12036 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12037 if (cond.IsNotNever()) {
12038 EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12039 (rn.GetCode() << 16) | rm.GetCode());
12040 return;
12041 }
12042 }
12043 Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
12044}
12045
12046void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012047 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012048 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012049 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012050 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12051 EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12052 rm.GetCode());
12053 AdvanceIT();
12054 return;
12055 } else {
12056 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12057 if (cond.IsNotNever()) {
12058 EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12059 (rn.GetCode() << 16) | rm.GetCode());
12060 return;
12061 }
12062 }
12063 Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
12064}
12065
12066void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012067 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012068 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012069 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012070 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12071 EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12072 rm.GetCode());
12073 AdvanceIT();
12074 return;
12075 } else {
12076 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12077 if (cond.IsNotNever()) {
12078 EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12079 (rn.GetCode() << 16) | rm.GetCode());
12080 return;
12081 }
12082 }
12083 Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
12084}
12085
12086void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012087 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012088 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012089 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012090 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12091 EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12092 rm.GetCode());
12093 AdvanceIT();
12094 return;
12095 } else {
12096 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12097 if (cond.IsNotNever()) {
12098 EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12099 (rn.GetCode() << 16) | rm.GetCode());
12100 return;
12101 }
12102 }
12103 Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
12104}
12105
12106void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012107 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012108 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012109 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012110 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12111 EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12112 rm.GetCode());
12113 AdvanceIT();
12114 return;
12115 } else {
12116 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12117 if (cond.IsNotNever()) {
12118 EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12119 (rn.GetCode() << 16) | rm.GetCode());
12120 return;
12121 }
12122 }
12123 Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
12124}
12125
12126void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012127 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012128 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012129 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012130 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12131 EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12132 rm.GetCode());
12133 AdvanceIT();
12134 return;
12135 } else {
12136 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12137 if (cond.IsNotNever()) {
12138 EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12139 (rn.GetCode() << 16) | rm.GetCode());
12140 return;
12141 }
12142 }
12143 Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
12144}
12145
12146void Assembler::umaal(
12147 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012148 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012149 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012150 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012151 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12152 EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12153 (rn.GetCode() << 16) | rm.GetCode());
12154 AdvanceIT();
12155 return;
12156 } else {
12157 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12158 if (cond.IsNotNever()) {
12159 EmitA32(0x00400090U | (cond.GetCondition() << 28) |
12160 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12161 (rm.GetCode() << 8));
12162 return;
12163 }
12164 }
12165 Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
12166}
12167
12168void Assembler::umlal(
12169 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012170 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012171 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012172 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012173 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12174 EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12175 (rn.GetCode() << 16) | rm.GetCode());
12176 AdvanceIT();
12177 return;
12178 } else {
12179 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12180 if (cond.IsNotNever()) {
12181 EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
12182 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12183 (rm.GetCode() << 8));
12184 return;
12185 }
12186 }
12187 Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
12188}
12189
12190void Assembler::umlals(
12191 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012192 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012193 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012194 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012195 // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12196 if (cond.IsNotNever()) {
12197 EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
12198 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12199 (rm.GetCode() << 8));
12200 return;
12201 }
12202 }
12203 Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
12204}
12205
12206void Assembler::umull(
12207 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012208 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012209 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012210 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012211 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
12212 EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
12213 (rn.GetCode() << 16) | rm.GetCode());
12214 AdvanceIT();
12215 return;
12216 } else {
12217 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12218 if (cond.IsNotNever()) {
12219 EmitA32(0x00800090U | (cond.GetCondition() << 28) |
12220 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12221 (rm.GetCode() << 8));
12222 return;
12223 }
12224 }
12225 Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
12226}
12227
12228void Assembler::umulls(
12229 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012230 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012231 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012232 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012233 // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
12234 if (cond.IsNotNever()) {
12235 EmitA32(0x00900090U | (cond.GetCondition() << 28) |
12236 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
12237 (rm.GetCode() << 8));
12238 return;
12239 }
12240 }
12241 Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
12242}
12243
12244void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012245 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012246 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012247 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012248 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12249 EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12250 rm.GetCode());
12251 AdvanceIT();
12252 return;
12253 } else {
12254 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12255 if (cond.IsNotNever()) {
12256 EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12257 (rn.GetCode() << 16) | rm.GetCode());
12258 return;
12259 }
12260 }
12261 Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
12262}
12263
12264void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012265 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012266 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012267 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012268 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12269 EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12270 rm.GetCode());
12271 AdvanceIT();
12272 return;
12273 } else {
12274 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12275 if (cond.IsNotNever()) {
12276 EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12277 (rn.GetCode() << 16) | rm.GetCode());
12278 return;
12279 }
12280 }
12281 Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
12282}
12283
12284void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012285 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012286 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012287 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012288 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12289 EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12290 rm.GetCode());
12291 AdvanceIT();
12292 return;
12293 } else {
12294 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12295 if (cond.IsNotNever()) {
12296 EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12297 (rn.GetCode() << 16) | rm.GetCode());
12298 return;
12299 }
12300 }
12301 Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
12302}
12303
12304void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012305 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012306 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012307 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012308 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12309 EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12310 rm.GetCode());
12311 AdvanceIT();
12312 return;
12313 } else {
12314 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12315 if (cond.IsNotNever()) {
12316 EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12317 (rn.GetCode() << 16) | rm.GetCode());
12318 return;
12319 }
12320 }
12321 Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
12322}
12323
12324void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012325 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012326 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012327 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012328 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12329 EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12330 rm.GetCode());
12331 AdvanceIT();
12332 return;
12333 } else {
12334 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12335 if (cond.IsNotNever()) {
12336 EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12337 (rn.GetCode() << 16) | rm.GetCode());
12338 return;
12339 }
12340 }
12341 Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
12342}
12343
12344void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012345 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012346 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012347 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012348 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12349 EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12350 rm.GetCode());
12351 AdvanceIT();
12352 return;
12353 } else {
12354 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12355 if (cond.IsNotNever()) {
12356 EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12357 (rn.GetCode() << 16) | rm.GetCode());
12358 return;
12359 }
12360 }
12361 Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
12362}
12363
12364void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012365 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012366 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012367 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012368 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12369 EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12370 rm.GetCode());
12371 AdvanceIT();
12372 return;
12373 } else {
12374 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12375 if (cond.IsNotNever()) {
12376 EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12377 rn.GetCode() | (rm.GetCode() << 8));
12378 return;
12379 }
12380 }
12381 Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
12382}
12383
12384void Assembler::usada8(
12385 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012386 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012387 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012388 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012389 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
12390 if (!ra.Is(pc)) {
12391 EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12392 rm.GetCode() | (ra.GetCode() << 12));
12393 AdvanceIT();
12394 return;
12395 }
12396 } else {
12397 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
12398 if (cond.IsNotNever() && !ra.Is(pc)) {
12399 EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
12400 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
12401 return;
12402 }
12403 }
12404 Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
12405}
12406
12407void Assembler::usat(Condition cond,
12408 Register rd,
12409 uint32_t imm,
12410 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012411 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012412 CheckIT(cond);
12413 if (operand.IsImmediateShiftedRegister()) {
12414 Register rn = operand.GetBaseRegister();
12415 Shift shift = operand.GetShift();
12416 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012417 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012418 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
12419 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31)) {
12420 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
12421 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
12422 ((amount & 0x1c) << 10));
12423 AdvanceIT();
12424 return;
12425 }
12426 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
12427 if ((imm <= 31) && shift.IsLSL() && (amount <= 31)) {
12428 EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
12429 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
12430 ((amount & 0x1c) << 10));
12431 AdvanceIT();
12432 return;
12433 }
12434 } else {
12435 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
12436 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
12437 cond.IsNotNever()) {
12438 uint32_t amount_ = amount % 32;
12439 EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
12440 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
12441 (amount_ << 7));
12442 return;
12443 }
12444 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
12445 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever()) {
12446 EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
12447 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
12448 (amount << 7));
12449 return;
12450 }
12451 }
12452 }
12453 Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
12454}
12455
12456void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012457 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012458 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012459 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012460 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
12461 if ((imm <= 15)) {
12462 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
12463 (rn.GetCode() << 16));
12464 AdvanceIT();
12465 return;
12466 }
12467 } else {
12468 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
12469 if ((imm <= 15) && cond.IsNotNever()) {
12470 EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12471 (imm << 16) | rn.GetCode());
12472 return;
12473 }
12474 }
12475 Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
12476}
12477
12478void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012479 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012480 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012481 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012482 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12483 EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12484 rm.GetCode());
12485 AdvanceIT();
12486 return;
12487 } else {
12488 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12489 if (cond.IsNotNever()) {
12490 EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12491 (rn.GetCode() << 16) | rm.GetCode());
12492 return;
12493 }
12494 }
12495 Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
12496}
12497
12498void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012499 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012500 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012501 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012502 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12503 EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12504 rm.GetCode());
12505 AdvanceIT();
12506 return;
12507 } else {
12508 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12509 if (cond.IsNotNever()) {
12510 EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12511 (rn.GetCode() << 16) | rm.GetCode());
12512 return;
12513 }
12514 }
12515 Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
12516}
12517
12518void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012519 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012520 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012521 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012522 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12523 EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12524 rm.GetCode());
12525 AdvanceIT();
12526 return;
12527 } else {
12528 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
12529 if (cond.IsNotNever()) {
12530 EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12531 (rn.GetCode() << 16) | rm.GetCode());
12532 return;
12533 }
12534 }
12535 Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
12536}
12537
12538void Assembler::uxtab(Condition cond,
12539 Register rd,
12540 Register rn,
12541 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012542 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012543 CheckIT(cond);
12544 if (operand.IsImmediateShiftedRegister()) {
12545 Register rm = operand.GetBaseRegister();
12546 Shift shift = operand.GetShift();
12547 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012548 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012549 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12550 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12551 ((amount % 8) == 0) && !rn.Is(pc)) {
12552 uint32_t amount_ = amount / 8;
12553 EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12554 rm.GetCode() | (amount_ << 4));
12555 AdvanceIT();
12556 return;
12557 }
12558 } else {
12559 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12560 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12561 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12562 uint32_t amount_ = amount / 8;
12563 EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
12564 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12565 (amount_ << 10));
12566 return;
12567 }
12568 }
12569 }
12570 Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
12571}
12572
12573void Assembler::uxtab16(Condition cond,
12574 Register rd,
12575 Register rn,
12576 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012577 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012578 CheckIT(cond);
12579 if (operand.IsImmediateShiftedRegister()) {
12580 Register rm = operand.GetBaseRegister();
12581 Shift shift = operand.GetShift();
12582 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012583 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012584 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12585 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12586 ((amount % 8) == 0) && !rn.Is(pc)) {
12587 uint32_t amount_ = amount / 8;
12588 EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12589 rm.GetCode() | (amount_ << 4));
12590 AdvanceIT();
12591 return;
12592 }
12593 } else {
12594 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12595 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12596 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12597 uint32_t amount_ = amount / 8;
12598 EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
12599 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12600 (amount_ << 10));
12601 return;
12602 }
12603 }
12604 }
12605 Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
12606}
12607
12608void Assembler::uxtah(Condition cond,
12609 Register rd,
12610 Register rn,
12611 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012612 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012613 CheckIT(cond);
12614 if (operand.IsImmediateShiftedRegister()) {
12615 Register rm = operand.GetBaseRegister();
12616 Shift shift = operand.GetShift();
12617 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012618 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012619 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12620 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12621 ((amount % 8) == 0) && !rn.Is(pc)) {
12622 uint32_t amount_ = amount / 8;
12623 EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12624 rm.GetCode() | (amount_ << 4));
12625 AdvanceIT();
12626 return;
12627 }
12628 } else {
12629 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12630 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12631 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc)) {
12632 uint32_t amount_ = amount / 8;
12633 EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
12634 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12635 (amount_ << 10));
12636 return;
12637 }
12638 }
12639 }
12640 Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
12641}
12642
12643void Assembler::uxtb(Condition cond,
12644 EncodingSize size,
12645 Register rd,
12646 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012647 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012648 CheckIT(cond);
12649 if (operand.IsImmediateShiftedRegister()) {
12650 Register rm = operand.GetBaseRegister();
12651 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012652 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012653 // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12654 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12655 EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
12656 AdvanceIT();
12657 return;
12658 }
12659 }
12660 }
12661 Shift shift = operand.GetShift();
12662 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012663 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012664 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12665 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12666 (amount <= 24) && ((amount % 8) == 0)) {
12667 uint32_t amount_ = amount / 8;
12668 EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12669 (amount_ << 4));
12670 AdvanceIT();
12671 return;
12672 }
12673 } else {
12674 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12675 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12676 ((amount % 8) == 0) && cond.IsNotNever()) {
12677 uint32_t amount_ = amount / 8;
12678 EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
12679 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12680 return;
12681 }
12682 }
12683 }
12684 Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
12685}
12686
12687void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012688 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012689 CheckIT(cond);
12690 if (operand.IsImmediateShiftedRegister()) {
12691 Register rm = operand.GetBaseRegister();
12692 Shift shift = operand.GetShift();
12693 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012694 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012695 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12696 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12697 ((amount % 8) == 0)) {
12698 uint32_t amount_ = amount / 8;
12699 EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12700 (amount_ << 4));
12701 AdvanceIT();
12702 return;
12703 }
12704 } else {
12705 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12706 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12707 ((amount % 8) == 0) && cond.IsNotNever()) {
12708 uint32_t amount_ = amount / 8;
12709 EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
12710 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12711 return;
12712 }
12713 }
12714 }
12715 Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
12716}
12717
12718void Assembler::uxth(Condition cond,
12719 EncodingSize size,
12720 Register rd,
12721 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012722 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012723 CheckIT(cond);
12724 if (operand.IsImmediateShiftedRegister()) {
12725 Register rm = operand.GetBaseRegister();
12726 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012727 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012728 // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12729 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12730 EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
12731 AdvanceIT();
12732 return;
12733 }
12734 }
12735 }
12736 Shift shift = operand.GetShift();
12737 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012738 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012739 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12740 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
12741 (amount <= 24) && ((amount % 8) == 0)) {
12742 uint32_t amount_ = amount / 8;
12743 EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12744 (amount_ << 4));
12745 AdvanceIT();
12746 return;
12747 }
12748 } else {
12749 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12750 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
12751 ((amount % 8) == 0) && cond.IsNotNever()) {
12752 uint32_t amount_ = amount / 8;
12753 EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
12754 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12755 return;
12756 }
12757 }
12758 }
12759 Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
12760}
12761
12762void Assembler::vaba(
12763 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012764 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012765 CheckIT(cond);
12766 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012767 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012768 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
12769 if (encoded_dt.IsValid()) {
12770 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12771 EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12772 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12773 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12774 AdvanceIT();
12775 return;
12776 }
12777 }
12778 } else {
12779 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
12780 if (encoded_dt.IsValid()) {
12781 if (cond.Is(al)) {
12782 EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12783 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12784 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12785 return;
12786 }
12787 }
12788 }
12789 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
12790}
12791
12792void Assembler::vaba(
12793 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012794 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012795 CheckIT(cond);
12796 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012797 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012798 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
12799 if (encoded_dt.IsValid()) {
12800 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12801 EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12802 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12803 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12804 AdvanceIT();
12805 return;
12806 }
12807 }
12808 } else {
12809 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
12810 if (encoded_dt.IsValid()) {
12811 if (cond.Is(al)) {
12812 EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12813 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12814 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12815 return;
12816 }
12817 }
12818 }
12819 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
12820}
12821
12822void Assembler::vabal(
12823 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012824 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012825 CheckIT(cond);
12826 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012827 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012828 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
12829 if (encoded_dt.IsValid()) {
12830 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12831 EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12832 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12833 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12834 AdvanceIT();
12835 return;
12836 }
12837 }
12838 } else {
12839 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
12840 if (encoded_dt.IsValid()) {
12841 if (cond.Is(al)) {
12842 EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12843 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12844 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12845 return;
12846 }
12847 }
12848 }
12849 Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
12850}
12851
12852void Assembler::vabd(
12853 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012854 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012855 CheckIT(cond);
12856 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012857 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012858 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
12859 if (dt.Is(F32)) {
12860 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12861 EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12862 rm.Encode(5, 0));
12863 AdvanceIT();
12864 return;
12865 }
12866 }
12867 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
12868 if (encoded_dt.IsValid()) {
12869 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12870 EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12871 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12872 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12873 AdvanceIT();
12874 return;
12875 }
12876 }
12877 } else {
12878 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
12879 if (dt.Is(F32)) {
12880 if (cond.Is(al)) {
12881 EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12882 rm.Encode(5, 0));
12883 return;
12884 }
12885 }
12886 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
12887 if (encoded_dt.IsValid()) {
12888 if (cond.Is(al)) {
12889 EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12890 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12891 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12892 return;
12893 }
12894 }
12895 }
12896 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
12897}
12898
12899void Assembler::vabd(
12900 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012901 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012902 CheckIT(cond);
12903 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012904 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012905 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
12906 if (dt.Is(F32)) {
12907 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12908 EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12909 rm.Encode(5, 0));
12910 AdvanceIT();
12911 return;
12912 }
12913 }
12914 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
12915 if (encoded_dt.IsValid()) {
12916 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12917 EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12918 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12919 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12920 AdvanceIT();
12921 return;
12922 }
12923 }
12924 } else {
12925 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
12926 if (dt.Is(F32)) {
12927 if (cond.Is(al)) {
12928 EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
12929 rm.Encode(5, 0));
12930 return;
12931 }
12932 }
12933 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
12934 if (encoded_dt.IsValid()) {
12935 if (cond.Is(al)) {
12936 EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12937 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12938 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12939 return;
12940 }
12941 }
12942 }
12943 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
12944}
12945
12946void Assembler::vabdl(
12947 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012948 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012949 CheckIT(cond);
12950 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012951 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012952 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
12953 if (encoded_dt.IsValid()) {
12954 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12955 EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12956 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
12957 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12958 AdvanceIT();
12959 return;
12960 }
12961 }
12962 } else {
12963 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
12964 if (encoded_dt.IsValid()) {
12965 if (cond.Is(al)) {
12966 EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
12967 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
12968 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
12969 return;
12970 }
12971 }
12972 }
12973 Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
12974}
12975
12976void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012977 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012978 CheckIT(cond);
12979 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012980 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012981 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
12982 if (encoded_dt.IsValid()) {
12983 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12984 EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
12985 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
12986 rd.Encode(22, 12) | rm.Encode(5, 0));
12987 AdvanceIT();
12988 return;
12989 }
12990 }
12991 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
12992 if (dt.Is(F64)) {
12993 EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
12994 AdvanceIT();
12995 return;
12996 }
12997 } else {
12998 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
12999 if (encoded_dt.IsValid()) {
13000 if (cond.Is(al)) {
13001 EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13002 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13003 rd.Encode(22, 12) | rm.Encode(5, 0));
13004 return;
13005 }
13006 }
13007 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
13008 if (dt.Is(F64) && cond.IsNotNever()) {
13009 EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13010 rm.Encode(5, 0));
13011 return;
13012 }
13013 }
13014 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13015}
13016
13017void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013018 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013019 CheckIT(cond);
13020 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013021 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013022 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
13023 if (encoded_dt.IsValid()) {
13024 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13025 EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13026 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13027 rd.Encode(22, 12) | rm.Encode(5, 0));
13028 AdvanceIT();
13029 return;
13030 }
13031 }
13032 } else {
13033 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
13034 if (encoded_dt.IsValid()) {
13035 if (cond.Is(al)) {
13036 EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13037 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13038 rd.Encode(22, 12) | rm.Encode(5, 0));
13039 return;
13040 }
13041 }
13042 }
13043 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13044}
13045
13046void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013047 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013048 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013049 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013050 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
13051 if (dt.Is(F32)) {
13052 EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
13053 AdvanceIT();
13054 return;
13055 }
13056 } else {
13057 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
13058 if (dt.Is(F32) && cond.IsNotNever()) {
13059 EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13060 rm.Encode(5, 0));
13061 return;
13062 }
13063 }
13064 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
13065}
13066
13067void Assembler::vacge(
13068 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013069 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013070 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013071 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013072 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13073 if (dt.Is(F32)) {
13074 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13075 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13076 rm.Encode(5, 0));
13077 AdvanceIT();
13078 return;
13079 }
13080 }
13081 } else {
13082 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13083 if (dt.Is(F32)) {
13084 if (cond.Is(al)) {
13085 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13086 rm.Encode(5, 0));
13087 return;
13088 }
13089 }
13090 }
13091 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
13092}
13093
13094void Assembler::vacge(
13095 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013096 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013097 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013098 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013099 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13100 if (dt.Is(F32)) {
13101 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13102 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13103 rm.Encode(5, 0));
13104 AdvanceIT();
13105 return;
13106 }
13107 }
13108 } else {
13109 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13110 if (dt.Is(F32)) {
13111 if (cond.Is(al)) {
13112 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13113 rm.Encode(5, 0));
13114 return;
13115 }
13116 }
13117 }
13118 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
13119}
13120
13121void Assembler::vacgt(
13122 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013123 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013124 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013125 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013126 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13127 if (dt.Is(F32)) {
13128 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13129 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13130 rm.Encode(5, 0));
13131 AdvanceIT();
13132 return;
13133 }
13134 }
13135 } else {
13136 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13137 if (dt.Is(F32)) {
13138 if (cond.Is(al)) {
13139 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13140 rm.Encode(5, 0));
13141 return;
13142 }
13143 }
13144 }
13145 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
13146}
13147
13148void Assembler::vacgt(
13149 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013150 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013151 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013152 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013153 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13154 if (dt.Is(F32)) {
13155 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13156 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13157 rm.Encode(5, 0));
13158 AdvanceIT();
13159 return;
13160 }
13161 }
13162 } else {
13163 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13164 if (dt.Is(F32)) {
13165 if (cond.Is(al)) {
13166 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13167 rm.Encode(5, 0));
13168 return;
13169 }
13170 }
13171 }
13172 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
13173}
13174
13175void Assembler::vacle(
13176 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013177 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013178 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013179 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013180 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13181 if (dt.Is(F32)) {
13182 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13183 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13184 rm.Encode(5, 0));
13185 AdvanceIT();
13186 return;
13187 }
13188 }
13189 } else {
13190 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13191 if (dt.Is(F32)) {
13192 if (cond.Is(al)) {
13193 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13194 rm.Encode(5, 0));
13195 return;
13196 }
13197 }
13198 }
13199 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
13200}
13201
13202void Assembler::vacle(
13203 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013204 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013205 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013206 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013207 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13208 if (dt.Is(F32)) {
13209 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13210 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13211 rm.Encode(5, 0));
13212 AdvanceIT();
13213 return;
13214 }
13215 }
13216 } else {
13217 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13218 if (dt.Is(F32)) {
13219 if (cond.Is(al)) {
13220 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13221 rm.Encode(5, 0));
13222 return;
13223 }
13224 }
13225 }
13226 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
13227}
13228
13229void Assembler::vaclt(
13230 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013231 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013232 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013233 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013234 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13235 if (dt.Is(F32)) {
13236 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13237 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13238 rm.Encode(5, 0));
13239 AdvanceIT();
13240 return;
13241 }
13242 }
13243 } else {
13244 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13245 if (dt.Is(F32)) {
13246 if (cond.Is(al)) {
13247 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13248 rm.Encode(5, 0));
13249 return;
13250 }
13251 }
13252 }
13253 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
13254}
13255
13256void Assembler::vaclt(
13257 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013258 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013259 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013260 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013261 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13262 if (dt.Is(F32)) {
13263 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13264 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13265 rm.Encode(5, 0));
13266 AdvanceIT();
13267 return;
13268 }
13269 }
13270 } else {
13271 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13272 if (dt.Is(F32)) {
13273 if (cond.Is(al)) {
13274 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13275 rm.Encode(5, 0));
13276 return;
13277 }
13278 }
13279 }
13280 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
13281}
13282
13283void Assembler::vadd(
13284 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013285 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013286 CheckIT(cond);
13287 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013288 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013289 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13290 if (dt.Is(F32)) {
13291 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13292 EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13293 rm.Encode(5, 0));
13294 AdvanceIT();
13295 return;
13296 }
13297 }
13298 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
13299 if (dt.Is(F64)) {
13300 EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13301 rm.Encode(5, 0));
13302 AdvanceIT();
13303 return;
13304 }
13305 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13306 if (encoded_dt.IsValid()) {
13307 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13308 EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
13309 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13310 AdvanceIT();
13311 return;
13312 }
13313 }
13314 } else {
13315 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13316 if (dt.Is(F32)) {
13317 if (cond.Is(al)) {
13318 EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13319 rm.Encode(5, 0));
13320 return;
13321 }
13322 }
13323 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
13324 if (dt.Is(F64) && cond.IsNotNever()) {
13325 EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13326 rn.Encode(7, 16) | rm.Encode(5, 0));
13327 return;
13328 }
13329 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13330 if (encoded_dt.IsValid()) {
13331 if (cond.Is(al)) {
13332 EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
13333 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13334 return;
13335 }
13336 }
13337 }
13338 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13339}
13340
13341void Assembler::vadd(
13342 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013343 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013344 CheckIT(cond);
13345 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013346 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013347 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
13348 if (dt.Is(F32)) {
13349 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13350 EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13351 rm.Encode(5, 0));
13352 AdvanceIT();
13353 return;
13354 }
13355 }
13356 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
13357 if (encoded_dt.IsValid()) {
13358 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13359 EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
13360 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13361 AdvanceIT();
13362 return;
13363 }
13364 }
13365 } else {
13366 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
13367 if (dt.Is(F32)) {
13368 if (cond.Is(al)) {
13369 EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13370 rm.Encode(5, 0));
13371 return;
13372 }
13373 }
13374 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
13375 if (encoded_dt.IsValid()) {
13376 if (cond.Is(al)) {
13377 EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
13378 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13379 return;
13380 }
13381 }
13382 }
13383 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13384}
13385
13386void Assembler::vadd(
13387 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013388 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013389 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013390 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013391 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
13392 if (dt.Is(F32)) {
13393 EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13394 rm.Encode(5, 0));
13395 AdvanceIT();
13396 return;
13397 }
13398 } else {
13399 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
13400 if (dt.Is(F32) && cond.IsNotNever()) {
13401 EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
13402 rn.Encode(7, 16) | rm.Encode(5, 0));
13403 return;
13404 }
13405 }
13406 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
13407}
13408
13409void Assembler::vaddhn(
13410 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013411 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013412 CheckIT(cond);
13413 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013414 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013415 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
13416 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
13417 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13418 EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
13419 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13420 AdvanceIT();
13421 return;
13422 }
13423 }
13424 } else {
13425 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
13426 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
13427 if (cond.Is(al)) {
13428 EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
13429 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13430 return;
13431 }
13432 }
13433 }
13434 Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
13435}
13436
13437void Assembler::vaddl(
13438 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013439 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013440 CheckIT(cond);
13441 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013442 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013443 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13444 if (encoded_dt.IsValid()) {
13445 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13446 EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13447 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13448 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13449 AdvanceIT();
13450 return;
13451 }
13452 }
13453 } else {
13454 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13455 if (encoded_dt.IsValid()) {
13456 if (cond.Is(al)) {
13457 EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13458 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13459 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13460 return;
13461 }
13462 }
13463 }
13464 Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
13465}
13466
13467void Assembler::vaddw(
13468 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013469 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013470 CheckIT(cond);
13471 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013472 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013473 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
13474 if (encoded_dt.IsValid()) {
13475 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13476 EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13477 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13478 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13479 AdvanceIT();
13480 return;
13481 }
13482 }
13483 } else {
13484 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
13485 if (encoded_dt.IsValid()) {
13486 if (cond.Is(al)) {
13487 EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13488 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13489 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13490 return;
13491 }
13492 }
13493 }
13494 Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
13495}
13496
13497void Assembler::vand(Condition cond,
13498 DataType dt,
13499 DRegister rd,
13500 DRegister rn,
13501 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013502 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013503 CheckIT(cond);
13504 if (operand.IsImmediate()) {
13505 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013506 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013507 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
13508 if (encoded_dt.IsValid() && rd.Is(rn)) {
13509 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13510 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
13511 rd.Encode(22, 12) |
13512 (encoded_dt.GetEncodedImmediate() & 0xf) |
13513 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13514 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13515 AdvanceIT();
13516 return;
13517 }
13518 }
13519 } else {
13520 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
13521 if (encoded_dt.IsValid() && rd.Is(rn)) {
13522 if (cond.Is(al)) {
13523 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
13524 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13525 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13526 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13527 return;
13528 }
13529 }
13530 }
13531 }
13532 if (operand.IsRegister()) {
13533 DRegister rm = operand.GetRegister();
13534 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013536 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13537 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13538 EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13539 rm.Encode(5, 0));
13540 AdvanceIT();
13541 return;
13542 }
13543 } else {
13544 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13545 if (cond.Is(al)) {
13546 EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13547 rm.Encode(5, 0));
13548 return;
13549 }
13550 }
13551 }
13552 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
13553}
13554
13555void Assembler::vand(Condition cond,
13556 DataType dt,
13557 QRegister rd,
13558 QRegister rn,
13559 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013560 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013561 CheckIT(cond);
13562 if (operand.IsImmediate()) {
13563 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013564 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013565 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
13566 if (encoded_dt.IsValid() && rd.Is(rn)) {
13567 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13568 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
13569 rd.Encode(22, 12) |
13570 (encoded_dt.GetEncodedImmediate() & 0xf) |
13571 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13572 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13573 AdvanceIT();
13574 return;
13575 }
13576 }
13577 } else {
13578 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
13579 if (encoded_dt.IsValid() && rd.Is(rn)) {
13580 if (cond.Is(al)) {
13581 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
13582 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13583 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13584 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13585 return;
13586 }
13587 }
13588 }
13589 }
13590 if (operand.IsRegister()) {
13591 QRegister rm = operand.GetRegister();
13592 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013593 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013594 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13595 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13596 EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13597 rm.Encode(5, 0));
13598 AdvanceIT();
13599 return;
13600 }
13601 } else {
13602 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13603 if (cond.Is(al)) {
13604 EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13605 rm.Encode(5, 0));
13606 return;
13607 }
13608 }
13609 }
13610 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
13611}
13612
13613void Assembler::vbic(Condition cond,
13614 DataType dt,
13615 DRegister rd,
13616 DRegister rn,
13617 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013618 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013619 CheckIT(cond);
13620 if (operand.IsImmediate()) {
13621 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013622 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013623 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
13624 if (encoded_dt.IsValid() && rd.Is(rn)) {
13625 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13626 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
13627 rd.Encode(22, 12) |
13628 (encoded_dt.GetEncodedImmediate() & 0xf) |
13629 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13630 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13631 AdvanceIT();
13632 return;
13633 }
13634 }
13635 } else {
13636 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
13637 if (encoded_dt.IsValid() && rd.Is(rn)) {
13638 if (cond.Is(al)) {
13639 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
13640 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13641 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13642 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13643 return;
13644 }
13645 }
13646 }
13647 }
13648 if (operand.IsRegister()) {
13649 DRegister rm = operand.GetRegister();
13650 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013652 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13653 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13654 EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13655 rm.Encode(5, 0));
13656 AdvanceIT();
13657 return;
13658 }
13659 } else {
13660 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13661 if (cond.Is(al)) {
13662 EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13663 rm.Encode(5, 0));
13664 return;
13665 }
13666 }
13667 }
13668 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
13669}
13670
13671void Assembler::vbic(Condition cond,
13672 DataType dt,
13673 QRegister rd,
13674 QRegister rn,
13675 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013676 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013677 CheckIT(cond);
13678 if (operand.IsImmediate()) {
13679 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013680 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013681 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
13682 if (encoded_dt.IsValid() && rd.Is(rn)) {
13683 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13684 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
13685 rd.Encode(22, 12) |
13686 (encoded_dt.GetEncodedImmediate() & 0xf) |
13687 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13688 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
13689 AdvanceIT();
13690 return;
13691 }
13692 }
13693 } else {
13694 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
13695 if (encoded_dt.IsValid() && rd.Is(rn)) {
13696 if (cond.Is(al)) {
13697 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
13698 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
13699 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
13700 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
13701 return;
13702 }
13703 }
13704 }
13705 }
13706 if (operand.IsRegister()) {
13707 QRegister rm = operand.GetRegister();
13708 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013709 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013710 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13711 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13712 EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13713 rm.Encode(5, 0));
13714 AdvanceIT();
13715 return;
13716 }
13717 } else {
13718 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13719 if (cond.Is(al)) {
13720 EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13721 rm.Encode(5, 0));
13722 return;
13723 }
13724 }
13725 }
13726 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
13727}
13728
13729void Assembler::vbif(
13730 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013731 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013732 CheckIT(cond);
13733 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013734 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013735 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13736 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13737 EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13738 rm.Encode(5, 0));
13739 AdvanceIT();
13740 return;
13741 }
13742 } else {
13743 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13744 if (cond.Is(al)) {
13745 EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13746 rm.Encode(5, 0));
13747 return;
13748 }
13749 }
13750 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
13751}
13752
13753void Assembler::vbif(
13754 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013755 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013756 CheckIT(cond);
13757 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013758 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013759 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13760 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13761 EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13762 rm.Encode(5, 0));
13763 AdvanceIT();
13764 return;
13765 }
13766 } else {
13767 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13768 if (cond.Is(al)) {
13769 EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13770 rm.Encode(5, 0));
13771 return;
13772 }
13773 }
13774 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
13775}
13776
13777void Assembler::vbit(
13778 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013779 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013780 CheckIT(cond);
13781 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013783 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13784 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13785 EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13786 rm.Encode(5, 0));
13787 AdvanceIT();
13788 return;
13789 }
13790 } else {
13791 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13792 if (cond.Is(al)) {
13793 EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13794 rm.Encode(5, 0));
13795 return;
13796 }
13797 }
13798 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
13799}
13800
13801void Assembler::vbit(
13802 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013803 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013804 CheckIT(cond);
13805 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013806 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013807 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13808 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13809 EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13810 rm.Encode(5, 0));
13811 AdvanceIT();
13812 return;
13813 }
13814 } else {
13815 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13816 if (cond.Is(al)) {
13817 EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13818 rm.Encode(5, 0));
13819 return;
13820 }
13821 }
13822 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
13823}
13824
13825void Assembler::vbsl(
13826 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013827 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013828 CheckIT(cond);
13829 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013831 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
13832 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13833 EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13834 rm.Encode(5, 0));
13835 AdvanceIT();
13836 return;
13837 }
13838 } else {
13839 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
13840 if (cond.Is(al)) {
13841 EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13842 rm.Encode(5, 0));
13843 return;
13844 }
13845 }
13846 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
13847}
13848
13849void Assembler::vbsl(
13850 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013851 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013852 CheckIT(cond);
13853 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013854 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013855 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
13856 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13857 EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13858 rm.Encode(5, 0));
13859 AdvanceIT();
13860 return;
13861 }
13862 } else {
13863 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
13864 if (cond.Is(al)) {
13865 EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13866 rm.Encode(5, 0));
13867 return;
13868 }
13869 }
13870 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
13871}
13872
13873void Assembler::vceq(Condition cond,
13874 DataType dt,
13875 DRegister rd,
13876 DRegister rm,
13877 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013878 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013879 CheckIT(cond);
13880 if (operand.IsImmediate()) {
13881 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
13882 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
13883 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013884 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013885 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
13886 if (encoded_dt.IsValid() && (imm == 0)) {
13887 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13888 EmitT32_32(0xffb10100U |
13889 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13890 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13891 rd.Encode(22, 12) | rm.Encode(5, 0));
13892 AdvanceIT();
13893 return;
13894 }
13895 }
13896 } else {
13897 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
13898 if (encoded_dt.IsValid() && (imm == 0)) {
13899 if (cond.Is(al)) {
13900 EmitA32(0xf3b10100U |
13901 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13902 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13903 rd.Encode(22, 12) | rm.Encode(5, 0));
13904 return;
13905 }
13906 }
13907 }
13908 }
13909 }
13910 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
13911}
13912
13913void Assembler::vceq(Condition cond,
13914 DataType dt,
13915 QRegister rd,
13916 QRegister rm,
13917 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013918 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013919 CheckIT(cond);
13920 if (operand.IsImmediate()) {
13921 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
13922 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
13923 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013924 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013925 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
13926 if (encoded_dt.IsValid() && (imm == 0)) {
13927 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13928 EmitT32_32(0xffb10140U |
13929 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13930 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13931 rd.Encode(22, 12) | rm.Encode(5, 0));
13932 AdvanceIT();
13933 return;
13934 }
13935 }
13936 } else {
13937 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
13938 if (encoded_dt.IsValid() && (imm == 0)) {
13939 if (cond.Is(al)) {
13940 EmitA32(0xf3b10140U |
13941 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
13942 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
13943 rd.Encode(22, 12) | rm.Encode(5, 0));
13944 return;
13945 }
13946 }
13947 }
13948 }
13949 }
13950 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
13951}
13952
13953void Assembler::vceq(
13954 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013955 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013956 CheckIT(cond);
13957 Dt_size_4 encoded_dt(dt);
13958 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013959 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013960 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13961 if (encoded_dt.IsValid()) {
13962 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13963 EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
13964 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13965 AdvanceIT();
13966 return;
13967 }
13968 }
13969 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
13970 if (encoded_dt_2.IsValid()) {
13971 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13972 EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
13973 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13974 AdvanceIT();
13975 return;
13976 }
13977 }
13978 } else {
13979 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13980 if (encoded_dt.IsValid()) {
13981 if (cond.Is(al)) {
13982 EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
13983 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13984 return;
13985 }
13986 }
13987 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
13988 if (encoded_dt_2.IsValid()) {
13989 if (cond.Is(al)) {
13990 EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
13991 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13992 return;
13993 }
13994 }
13995 }
13996 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
13997}
13998
13999void Assembler::vceq(
14000 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014001 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014002 CheckIT(cond);
14003 Dt_size_4 encoded_dt(dt);
14004 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014005 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014006 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14007 if (encoded_dt.IsValid()) {
14008 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14009 EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
14010 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14011 AdvanceIT();
14012 return;
14013 }
14014 }
14015 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
14016 if (encoded_dt_2.IsValid()) {
14017 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14018 EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
14019 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14020 AdvanceIT();
14021 return;
14022 }
14023 }
14024 } else {
14025 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14026 if (encoded_dt.IsValid()) {
14027 if (cond.Is(al)) {
14028 EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
14029 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14030 return;
14031 }
14032 }
14033 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
14034 if (encoded_dt_2.IsValid()) {
14035 if (cond.Is(al)) {
14036 EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
14037 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14038 return;
14039 }
14040 }
14041 }
14042 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
14043}
14044
14045void Assembler::vcge(Condition cond,
14046 DataType dt,
14047 DRegister rd,
14048 DRegister rm,
14049 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014050 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014051 CheckIT(cond);
14052 if (operand.IsImmediate()) {
14053 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14054 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14055 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014056 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014057 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14058 if (encoded_dt.IsValid() && (imm == 0)) {
14059 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14060 EmitT32_32(0xffb10080U |
14061 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14062 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14063 rd.Encode(22, 12) | rm.Encode(5, 0));
14064 AdvanceIT();
14065 return;
14066 }
14067 }
14068 } else {
14069 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14070 if (encoded_dt.IsValid() && (imm == 0)) {
14071 if (cond.Is(al)) {
14072 EmitA32(0xf3b10080U |
14073 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14074 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14075 rd.Encode(22, 12) | rm.Encode(5, 0));
14076 return;
14077 }
14078 }
14079 }
14080 }
14081 }
14082 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
14083}
14084
14085void Assembler::vcge(Condition cond,
14086 DataType dt,
14087 QRegister rd,
14088 QRegister rm,
14089 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014090 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014091 CheckIT(cond);
14092 if (operand.IsImmediate()) {
14093 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14094 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14095 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014096 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014097 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14098 if (encoded_dt.IsValid() && (imm == 0)) {
14099 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14100 EmitT32_32(0xffb100c0U |
14101 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14102 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14103 rd.Encode(22, 12) | rm.Encode(5, 0));
14104 AdvanceIT();
14105 return;
14106 }
14107 }
14108 } else {
14109 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14110 if (encoded_dt.IsValid() && (imm == 0)) {
14111 if (cond.Is(al)) {
14112 EmitA32(0xf3b100c0U |
14113 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14114 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14115 rd.Encode(22, 12) | rm.Encode(5, 0));
14116 return;
14117 }
14118 }
14119 }
14120 }
14121 }
14122 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
14123}
14124
14125void Assembler::vcge(
14126 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014127 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014128 CheckIT(cond);
14129 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014130 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014131 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14132 if (encoded_dt.IsValid()) {
14133 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14134 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14135 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000014136 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014137 AdvanceIT();
14138 return;
14139 }
14140 }
14141 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14142 if (dt.Is(F32)) {
14143 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14144 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14145 rm.Encode(5, 0));
14146 AdvanceIT();
14147 return;
14148 }
14149 }
14150 } else {
14151 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14152 if (encoded_dt.IsValid()) {
14153 if (cond.Is(al)) {
14154 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14155 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14156 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14157 return;
14158 }
14159 }
14160 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14161 if (dt.Is(F32)) {
14162 if (cond.Is(al)) {
14163 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14164 rm.Encode(5, 0));
14165 return;
14166 }
14167 }
14168 }
14169 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
14170}
14171
14172void Assembler::vcge(
14173 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014174 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014175 CheckIT(cond);
14176 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014177 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014178 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14179 if (encoded_dt.IsValid()) {
14180 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14181 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14182 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000014183 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014184 AdvanceIT();
14185 return;
14186 }
14187 }
14188 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14189 if (dt.Is(F32)) {
14190 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14191 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14192 rm.Encode(5, 0));
14193 AdvanceIT();
14194 return;
14195 }
14196 }
14197 } else {
14198 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14199 if (encoded_dt.IsValid()) {
14200 if (cond.Is(al)) {
14201 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14202 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14203 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14204 return;
14205 }
14206 }
14207 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14208 if (dt.Is(F32)) {
14209 if (cond.Is(al)) {
14210 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14211 rm.Encode(5, 0));
14212 return;
14213 }
14214 }
14215 }
14216 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
14217}
14218
14219void Assembler::vcgt(Condition cond,
14220 DataType dt,
14221 DRegister rd,
14222 DRegister rm,
14223 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014224 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014225 CheckIT(cond);
14226 if (operand.IsImmediate()) {
14227 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14228 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14229 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014230 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014231 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14232 if (encoded_dt.IsValid() && (imm == 0)) {
14233 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14234 EmitT32_32(0xffb10000U |
14235 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14236 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14237 rd.Encode(22, 12) | rm.Encode(5, 0));
14238 AdvanceIT();
14239 return;
14240 }
14241 }
14242 } else {
14243 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14244 if (encoded_dt.IsValid() && (imm == 0)) {
14245 if (cond.Is(al)) {
14246 EmitA32(0xf3b10000U |
14247 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14248 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14249 rd.Encode(22, 12) | rm.Encode(5, 0));
14250 return;
14251 }
14252 }
14253 }
14254 }
14255 }
14256 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
14257}
14258
14259void Assembler::vcgt(Condition cond,
14260 DataType dt,
14261 QRegister rd,
14262 QRegister rm,
14263 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014264 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014265 CheckIT(cond);
14266 if (operand.IsImmediate()) {
14267 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14268 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14269 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014270 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014271 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14272 if (encoded_dt.IsValid() && (imm == 0)) {
14273 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14274 EmitT32_32(0xffb10040U |
14275 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14276 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14277 rd.Encode(22, 12) | rm.Encode(5, 0));
14278 AdvanceIT();
14279 return;
14280 }
14281 }
14282 } else {
14283 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14284 if (encoded_dt.IsValid() && (imm == 0)) {
14285 if (cond.Is(al)) {
14286 EmitA32(0xf3b10040U |
14287 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14288 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14289 rd.Encode(22, 12) | rm.Encode(5, 0));
14290 return;
14291 }
14292 }
14293 }
14294 }
14295 }
14296 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
14297}
14298
14299void Assembler::vcgt(
14300 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014301 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014302 CheckIT(cond);
14303 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014304 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014305 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14306 if (encoded_dt.IsValid()) {
14307 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14308 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14309 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000014310 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014311 AdvanceIT();
14312 return;
14313 }
14314 }
14315 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14316 if (dt.Is(F32)) {
14317 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14318 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14319 rm.Encode(5, 0));
14320 AdvanceIT();
14321 return;
14322 }
14323 }
14324 } else {
14325 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14326 if (encoded_dt.IsValid()) {
14327 if (cond.Is(al)) {
14328 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14329 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14330 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14331 return;
14332 }
14333 }
14334 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14335 if (dt.Is(F32)) {
14336 if (cond.Is(al)) {
14337 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14338 rm.Encode(5, 0));
14339 return;
14340 }
14341 }
14342 }
14343 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
14344}
14345
14346void Assembler::vcgt(
14347 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014349 CheckIT(cond);
14350 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014352 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14353 if (encoded_dt.IsValid()) {
14354 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14355 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14356 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000014357 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014358 AdvanceIT();
14359 return;
14360 }
14361 }
14362 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14363 if (dt.Is(F32)) {
14364 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14365 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14366 rm.Encode(5, 0));
14367 AdvanceIT();
14368 return;
14369 }
14370 }
14371 } else {
14372 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14373 if (encoded_dt.IsValid()) {
14374 if (cond.Is(al)) {
14375 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14376 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14377 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14378 return;
14379 }
14380 }
14381 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14382 if (dt.Is(F32)) {
14383 if (cond.Is(al)) {
14384 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14385 rm.Encode(5, 0));
14386 return;
14387 }
14388 }
14389 }
14390 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
14391}
14392
14393void Assembler::vcle(Condition cond,
14394 DataType dt,
14395 DRegister rd,
14396 DRegister rm,
14397 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014398 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014399 CheckIT(cond);
14400 if (operand.IsImmediate()) {
14401 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14402 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14403 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014404 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014405 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14406 if (encoded_dt.IsValid() && (imm == 0)) {
14407 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14408 EmitT32_32(0xffb10180U |
14409 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14410 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14411 rd.Encode(22, 12) | rm.Encode(5, 0));
14412 AdvanceIT();
14413 return;
14414 }
14415 }
14416 } else {
14417 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14418 if (encoded_dt.IsValid() && (imm == 0)) {
14419 if (cond.Is(al)) {
14420 EmitA32(0xf3b10180U |
14421 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14422 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14423 rd.Encode(22, 12) | rm.Encode(5, 0));
14424 return;
14425 }
14426 }
14427 }
14428 }
14429 }
14430 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
14431}
14432
14433void Assembler::vcle(Condition cond,
14434 DataType dt,
14435 QRegister rd,
14436 QRegister rm,
14437 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014438 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014439 CheckIT(cond);
14440 if (operand.IsImmediate()) {
14441 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14442 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14443 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014444 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014445 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14446 if (encoded_dt.IsValid() && (imm == 0)) {
14447 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14448 EmitT32_32(0xffb101c0U |
14449 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14450 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14451 rd.Encode(22, 12) | rm.Encode(5, 0));
14452 AdvanceIT();
14453 return;
14454 }
14455 }
14456 } else {
14457 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14458 if (encoded_dt.IsValid() && (imm == 0)) {
14459 if (cond.Is(al)) {
14460 EmitA32(0xf3b101c0U |
14461 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14462 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14463 rd.Encode(22, 12) | rm.Encode(5, 0));
14464 return;
14465 }
14466 }
14467 }
14468 }
14469 }
14470 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
14471}
14472
14473void Assembler::vcle(
14474 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014475 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014476 CheckIT(cond);
14477 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014478 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014479 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14480 if (encoded_dt.IsValid()) {
14481 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14482 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14483 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014484 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014485 AdvanceIT();
14486 return;
14487 }
14488 }
14489 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14490 if (dt.Is(F32)) {
14491 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014492 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14493 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014494 AdvanceIT();
14495 return;
14496 }
14497 }
14498 } else {
14499 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14500 if (encoded_dt.IsValid()) {
14501 if (cond.Is(al)) {
14502 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14503 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014504 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014505 return;
14506 }
14507 }
14508 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14509 if (dt.Is(F32)) {
14510 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014511 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14512 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014513 return;
14514 }
14515 }
14516 }
14517 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
14518}
14519
14520void Assembler::vcle(
14521 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014522 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014523 CheckIT(cond);
14524 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014525 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014526 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14527 if (encoded_dt.IsValid()) {
14528 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14529 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14530 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014531 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014532 AdvanceIT();
14533 return;
14534 }
14535 }
14536 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14537 if (dt.Is(F32)) {
14538 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014539 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14540 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014541 AdvanceIT();
14542 return;
14543 }
14544 }
14545 } else {
14546 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14547 if (encoded_dt.IsValid()) {
14548 if (cond.Is(al)) {
14549 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14550 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014551 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014552 return;
14553 }
14554 }
14555 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14556 if (dt.Is(F32)) {
14557 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014558 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14559 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014560 return;
14561 }
14562 }
14563 }
14564 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
14565}
14566
14567void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014568 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014569 CheckIT(cond);
14570 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014571 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014572 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14573 if (encoded_dt.IsValid()) {
14574 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14575 EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
14576 rd.Encode(22, 12) | rm.Encode(5, 0));
14577 AdvanceIT();
14578 return;
14579 }
14580 }
14581 } else {
14582 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14583 if (encoded_dt.IsValid()) {
14584 if (cond.Is(al)) {
14585 EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
14586 rd.Encode(22, 12) | rm.Encode(5, 0));
14587 return;
14588 }
14589 }
14590 }
14591 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
14592}
14593
14594void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014595 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014596 CheckIT(cond);
14597 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014598 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014599 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14600 if (encoded_dt.IsValid()) {
14601 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14602 EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
14603 rd.Encode(22, 12) | rm.Encode(5, 0));
14604 AdvanceIT();
14605 return;
14606 }
14607 }
14608 } else {
14609 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14610 if (encoded_dt.IsValid()) {
14611 if (cond.Is(al)) {
14612 EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
14613 rd.Encode(22, 12) | rm.Encode(5, 0));
14614 return;
14615 }
14616 }
14617 }
14618 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
14619}
14620
14621void Assembler::vclt(Condition cond,
14622 DataType dt,
14623 DRegister rd,
14624 DRegister rm,
14625 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014626 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014627 CheckIT(cond);
14628 if (operand.IsImmediate()) {
14629 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14630 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14631 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014632 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014633 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14634 if (encoded_dt.IsValid() && (imm == 0)) {
14635 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14636 EmitT32_32(0xffb10200U |
14637 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14638 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14639 rd.Encode(22, 12) | rm.Encode(5, 0));
14640 AdvanceIT();
14641 return;
14642 }
14643 }
14644 } else {
14645 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14646 if (encoded_dt.IsValid() && (imm == 0)) {
14647 if (cond.Is(al)) {
14648 EmitA32(0xf3b10200U |
14649 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14650 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14651 rd.Encode(22, 12) | rm.Encode(5, 0));
14652 return;
14653 }
14654 }
14655 }
14656 }
14657 }
14658 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
14659}
14660
14661void Assembler::vclt(Condition cond,
14662 DataType dt,
14663 QRegister rd,
14664 QRegister rm,
14665 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014666 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014667 CheckIT(cond);
14668 if (operand.IsImmediate()) {
14669 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14670 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14671 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014673 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
14674 if (encoded_dt.IsValid() && (imm == 0)) {
14675 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14676 EmitT32_32(0xffb10240U |
14677 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14678 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14679 rd.Encode(22, 12) | rm.Encode(5, 0));
14680 AdvanceIT();
14681 return;
14682 }
14683 }
14684 } else {
14685 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
14686 if (encoded_dt.IsValid() && (imm == 0)) {
14687 if (cond.Is(al)) {
14688 EmitA32(0xf3b10240U |
14689 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14690 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14691 rd.Encode(22, 12) | rm.Encode(5, 0));
14692 return;
14693 }
14694 }
14695 }
14696 }
14697 }
14698 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
14699}
14700
14701void Assembler::vclt(
14702 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014703 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014704 CheckIT(cond);
14705 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014706 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014707 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14708 if (encoded_dt.IsValid()) {
14709 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14710 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14711 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014712 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014713 AdvanceIT();
14714 return;
14715 }
14716 }
14717 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
14718 if (dt.Is(F32)) {
14719 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014720 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14721 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014722 AdvanceIT();
14723 return;
14724 }
14725 }
14726 } else {
14727 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14728 if (encoded_dt.IsValid()) {
14729 if (cond.Is(al)) {
14730 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14731 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014732 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014733 return;
14734 }
14735 }
14736 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
14737 if (dt.Is(F32)) {
14738 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014739 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14740 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014741 return;
14742 }
14743 }
14744 }
14745 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
14746}
14747
14748void Assembler::vclt(
14749 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014750 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014751 CheckIT(cond);
14752 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014754 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14755 if (encoded_dt.IsValid()) {
14756 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14757 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14758 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014759 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014760 AdvanceIT();
14761 return;
14762 }
14763 }
14764 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
14765 if (dt.Is(F32)) {
14766 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014767 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14768 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014769 AdvanceIT();
14770 return;
14771 }
14772 }
14773 } else {
14774 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14775 if (encoded_dt.IsValid()) {
14776 if (cond.Is(al)) {
14777 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14778 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010014779 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014780 return;
14781 }
14782 }
14783 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
14784 if (dt.Is(F32)) {
14785 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010014786 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
14787 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010014788 return;
14789 }
14790 }
14791 }
14792 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
14793}
14794
14795void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014796 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014797 CheckIT(cond);
14798 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014799 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014800 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14801 if (encoded_dt.IsValid()) {
14802 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14803 EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
14804 rd.Encode(22, 12) | rm.Encode(5, 0));
14805 AdvanceIT();
14806 return;
14807 }
14808 }
14809 } else {
14810 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14811 if (encoded_dt.IsValid()) {
14812 if (cond.Is(al)) {
14813 EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
14814 rd.Encode(22, 12) | rm.Encode(5, 0));
14815 return;
14816 }
14817 }
14818 }
14819 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
14820}
14821
14822void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014823 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014824 CheckIT(cond);
14825 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014826 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014827 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14828 if (encoded_dt.IsValid()) {
14829 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14830 EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
14831 rd.Encode(22, 12) | rm.Encode(5, 0));
14832 AdvanceIT();
14833 return;
14834 }
14835 }
14836 } else {
14837 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14838 if (encoded_dt.IsValid()) {
14839 if (cond.Is(al)) {
14840 EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
14841 rd.Encode(22, 12) | rm.Encode(5, 0));
14842 return;
14843 }
14844 }
14845 }
14846 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
14847}
14848
14849void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014850 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014851 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014852 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014853 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
14854 if (dt.Is(F32)) {
14855 EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
14856 AdvanceIT();
14857 return;
14858 }
14859 } else {
14860 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
14861 if (dt.Is(F32) && cond.IsNotNever()) {
14862 EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14863 rm.Encode(5, 0));
14864 return;
14865 }
14866 }
14867 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
14868}
14869
14870void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014871 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014872 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014873 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014874 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
14875 if (dt.Is(F64)) {
14876 EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
14877 AdvanceIT();
14878 return;
14879 }
14880 } else {
14881 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
14882 if (dt.Is(F64) && cond.IsNotNever()) {
14883 EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14884 rm.Encode(5, 0));
14885 return;
14886 }
14887 }
14888 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
14889}
14890
14891void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, double imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014892 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014893 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014894 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014895 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
14896 if (dt.Is(F32) && (imm == 0.0)) {
14897 EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
14898 AdvanceIT();
14899 return;
14900 }
14901 } else {
14902 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
14903 if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
14904 EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14905 return;
14906 }
14907 }
14908 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
14909}
14910
14911void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, double imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014912 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014913 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014914 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014915 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
14916 if (dt.Is(F64) && (imm == 0.0)) {
14917 EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
14918 AdvanceIT();
14919 return;
14920 }
14921 } else {
14922 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
14923 if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
14924 EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14925 return;
14926 }
14927 }
14928 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
14929}
14930
14931void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014932 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014933 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014934 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014935 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
14936 if (dt.Is(F32)) {
14937 EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14938 AdvanceIT();
14939 return;
14940 }
14941 } else {
14942 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
14943 if (dt.Is(F32) && cond.IsNotNever()) {
14944 EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14945 rm.Encode(5, 0));
14946 return;
14947 }
14948 }
14949 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
14950}
14951
14952void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014953 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014954 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014955 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014956 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
14957 if (dt.Is(F64)) {
14958 EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14959 AdvanceIT();
14960 return;
14961 }
14962 } else {
14963 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
14964 if (dt.Is(F64) && cond.IsNotNever()) {
14965 EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14966 rm.Encode(5, 0));
14967 return;
14968 }
14969 }
14970 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
14971}
14972
14973void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, double imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014974 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014975 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014976 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014977 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
14978 if (dt.Is(F32) && (imm == 0.0)) {
14979 EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
14980 AdvanceIT();
14981 return;
14982 }
14983 } else {
14984 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
14985 if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
14986 EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
14987 return;
14988 }
14989 }
14990 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
14991}
14992
14993void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, double imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014994 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014995 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014996 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014997 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
14998 if (dt.Is(F64) && (imm == 0.0)) {
14999 EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
15000 AdvanceIT();
15001 return;
15002 }
15003 } else {
15004 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
15005 if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
15006 EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
15007 return;
15008 }
15009 }
15010 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
15011}
15012
15013void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015014 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015015 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015016 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015017 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
15018 if (dt.Is(Untyped8)) {
15019 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15020 EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
15021 AdvanceIT();
15022 return;
15023 }
15024 }
15025 } else {
15026 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
15027 if (dt.Is(Untyped8)) {
15028 if (cond.Is(al)) {
15029 EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
15030 return;
15031 }
15032 }
15033 }
15034 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
15035}
15036
15037void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015038 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015039 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015040 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015041 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
15042 if (dt.Is(Untyped8)) {
15043 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15044 EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
15045 AdvanceIT();
15046 return;
15047 }
15048 }
15049 } else {
15050 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
15051 if (dt.Is(Untyped8)) {
15052 if (cond.Is(al)) {
15053 EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
15054 return;
15055 }
15056 }
15057 }
15058 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
15059}
15060
15061void Assembler::vcvt(
15062 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015063 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015064 CheckIT(cond);
15065 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015066 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015067 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
15068 if (dt1.Is(F64) && dt2.Is(F32)) {
15069 EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15070 AdvanceIT();
15071 return;
15072 }
15073 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
15074 if (dt1.Is(F64) && encoded_dt.IsValid()) {
15075 EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
15076 rd.Encode(22, 12) | rm.Encode(5, 0));
15077 AdvanceIT();
15078 return;
15079 }
15080 } else {
15081 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
15082 if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
15083 EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15084 rm.Encode(5, 0));
15085 return;
15086 }
15087 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
15088 if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
15089 EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
15090 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
15091 rm.Encode(5, 0));
15092 return;
15093 }
15094 }
15095 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15096}
15097
15098void Assembler::vcvt(
15099 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015100 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015101 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015102 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015103 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
15104 if (dt1.Is(F32) && dt2.Is(F64)) {
15105 EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15106 AdvanceIT();
15107 return;
15108 }
15109 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
15110 if (dt1.Is(U32) && dt2.Is(F64)) {
15111 EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15112 AdvanceIT();
15113 return;
15114 }
15115 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
15116 if (dt1.Is(S32) && dt2.Is(F64)) {
15117 EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15118 AdvanceIT();
15119 return;
15120 }
15121 } else {
15122 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
15123 if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
15124 EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15125 rm.Encode(5, 0));
15126 return;
15127 }
15128 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
15129 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
15130 EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15131 rm.Encode(5, 0));
15132 return;
15133 }
15134 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
15135 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
15136 EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15137 rm.Encode(5, 0));
15138 return;
15139 }
15140 }
15141 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15142}
15143
15144void Assembler::vcvt(Condition cond,
15145 DataType dt1,
15146 DataType dt2,
15147 DRegister rd,
15148 DRegister rm,
15149 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015150 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015151 CheckIT(cond);
15152 Dt_op_U_1 encoded_dt(dt1, dt2);
15153 Dt_U_sx_1 encoded_dt_2(dt2);
15154 Dt_U_sx_1 encoded_dt_3(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015155 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015156 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
15157 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15158 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15159 uint32_t fbits_ = 64 - fbits;
15160 EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
15161 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15162 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15163 AdvanceIT();
15164 return;
15165 }
15166 }
15167 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
15168 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
15169 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15170 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15171 unsigned offset = 32;
15172 if (dt2.Is(S16) || dt2.Is(U16)) {
15173 offset = 16;
15174 }
15175 uint32_t fbits_ = offset - fbits;
15176 EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15177 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15178 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15179 ((fbits_ & 0x1e) >> 1));
15180 AdvanceIT();
15181 return;
15182 }
15183 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
15184 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
15185 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15186 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15187 unsigned offset = 32;
15188 if (dt1.Is(S16) || dt1.Is(U16)) {
15189 offset = 16;
15190 }
15191 uint32_t fbits_ = offset - fbits;
15192 EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
15193 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
15194 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15195 ((fbits_ & 0x1e) >> 1));
15196 AdvanceIT();
15197 return;
15198 }
15199 } else {
15200 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
15201 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15202 if (cond.Is(al)) {
15203 uint32_t fbits_ = 64 - fbits;
15204 EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
15205 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15206 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15207 return;
15208 }
15209 }
15210 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
15211 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
15212 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15213 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15214 cond.IsNotNever()) {
15215 unsigned offset = 32;
15216 if (dt2.Is(S16) || dt2.Is(U16)) {
15217 offset = 16;
15218 }
15219 uint32_t fbits_ = offset - fbits;
15220 EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
15221 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15222 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15223 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15224 ((fbits_ & 0x1e) >> 1));
15225 return;
15226 }
15227 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
15228 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
15229 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15230 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15231 cond.IsNotNever()) {
15232 unsigned offset = 32;
15233 if (dt1.Is(S16) || dt1.Is(U16)) {
15234 offset = 16;
15235 }
15236 uint32_t fbits_ = offset - fbits;
15237 EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
15238 ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
15239 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
15240 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15241 ((fbits_ & 0x1e) >> 1));
15242 return;
15243 }
15244 }
15245 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15246}
15247
15248void Assembler::vcvt(Condition cond,
15249 DataType dt1,
15250 DataType dt2,
15251 QRegister rd,
15252 QRegister rm,
15253 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015254 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015255 CheckIT(cond);
15256 Dt_op_U_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015257 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015258 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
15259 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15260 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15261 uint32_t fbits_ = 64 - fbits;
15262 EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
15263 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15264 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15265 AdvanceIT();
15266 return;
15267 }
15268 }
15269 } else {
15270 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
15271 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
15272 if (cond.Is(al)) {
15273 uint32_t fbits_ = 64 - fbits;
15274 EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
15275 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
15276 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
15277 return;
15278 }
15279 }
15280 }
15281 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15282}
15283
15284void Assembler::vcvt(Condition cond,
15285 DataType dt1,
15286 DataType dt2,
15287 SRegister rd,
15288 SRegister rm,
15289 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015290 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015291 CheckIT(cond);
15292 Dt_U_sx_1 encoded_dt(dt2);
15293 Dt_U_sx_1 encoded_dt_2(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015294 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015295 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
15296 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
15297 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15298 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15299 unsigned offset = 32;
15300 if (dt2.Is(S16) || dt2.Is(U16)) {
15301 offset = 16;
15302 }
15303 uint32_t fbits_ = offset - fbits;
15304 EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
15305 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
15306 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15307 ((fbits_ & 0x1e) >> 1));
15308 AdvanceIT();
15309 return;
15310 }
15311 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
15312 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
15313 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15314 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
15315 unsigned offset = 32;
15316 if (dt1.Is(S16) || dt1.Is(U16)) {
15317 offset = 16;
15318 }
15319 uint32_t fbits_ = offset - fbits;
15320 EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15321 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15322 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15323 ((fbits_ & 0x1e) >> 1));
15324 AdvanceIT();
15325 return;
15326 }
15327 } else {
15328 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
15329 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
15330 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
15331 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15332 cond.IsNotNever()) {
15333 unsigned offset = 32;
15334 if (dt2.Is(S16) || dt2.Is(U16)) {
15335 offset = 16;
15336 }
15337 uint32_t fbits_ = offset - fbits;
15338 EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
15339 ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
15340 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
15341 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15342 ((fbits_ & 0x1e) >> 1));
15343 return;
15344 }
15345 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
15346 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
15347 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
15348 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
15349 cond.IsNotNever()) {
15350 unsigned offset = 32;
15351 if (dt1.Is(S16) || dt1.Is(U16)) {
15352 offset = 16;
15353 }
15354 uint32_t fbits_ = offset - fbits;
15355 EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
15356 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
15357 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
15358 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
15359 ((fbits_ & 0x1e) >> 1));
15360 return;
15361 }
15362 }
15363 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
15364}
15365
15366void Assembler::vcvt(
15367 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015369 CheckIT(cond);
15370 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015371 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015372 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
15373 if (encoded_dt.IsValid()) {
15374 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15375 EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
15376 rd.Encode(22, 12) | rm.Encode(5, 0));
15377 AdvanceIT();
15378 return;
15379 }
15380 }
15381 } else {
15382 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
15383 if (encoded_dt.IsValid()) {
15384 if (cond.Is(al)) {
15385 EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
15386 rd.Encode(22, 12) | rm.Encode(5, 0));
15387 return;
15388 }
15389 }
15390 }
15391 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15392}
15393
15394void Assembler::vcvt(
15395 Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015396 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015397 CheckIT(cond);
15398 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015399 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015400 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
15401 if (encoded_dt.IsValid()) {
15402 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15403 EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
15404 rd.Encode(22, 12) | rm.Encode(5, 0));
15405 AdvanceIT();
15406 return;
15407 }
15408 }
15409 } else {
15410 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
15411 if (encoded_dt.IsValid()) {
15412 if (cond.Is(al)) {
15413 EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
15414 rd.Encode(22, 12) | rm.Encode(5, 0));
15415 return;
15416 }
15417 }
15418 }
15419 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15420}
15421
15422void Assembler::vcvt(
15423 Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015424 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015425 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015426 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015427 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
15428 if (dt1.Is(F16) && dt2.Is(F32)) {
15429 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15430 EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
15431 AdvanceIT();
15432 return;
15433 }
15434 }
15435 } else {
15436 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
15437 if (dt1.Is(F16) && dt2.Is(F32)) {
15438 if (cond.Is(al)) {
15439 EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
15440 return;
15441 }
15442 }
15443 }
15444 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15445}
15446
15447void Assembler::vcvt(
15448 Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015449 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015450 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015451 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015452 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
15453 if (dt1.Is(F32) && dt2.Is(F16)) {
15454 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15455 EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
15456 AdvanceIT();
15457 return;
15458 }
15459 }
15460 } else {
15461 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
15462 if (dt1.Is(F32) && dt2.Is(F16)) {
15463 if (cond.Is(al)) {
15464 EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
15465 return;
15466 }
15467 }
15468 }
15469 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15470}
15471
15472void Assembler::vcvt(
15473 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015474 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015475 CheckIT(cond);
15476 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015477 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015478 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
15479 if (dt1.Is(U32) && dt2.Is(F32)) {
15480 EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15481 AdvanceIT();
15482 return;
15483 }
15484 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
15485 if (dt1.Is(S32) && dt2.Is(F32)) {
15486 EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
15487 AdvanceIT();
15488 return;
15489 }
15490 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
15491 if (dt1.Is(F32) && encoded_dt.IsValid()) {
15492 EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
15493 rd.Encode(22, 12) | rm.Encode(5, 0));
15494 AdvanceIT();
15495 return;
15496 }
15497 } else {
15498 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
15499 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
15500 EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15501 rm.Encode(5, 0));
15502 return;
15503 }
15504 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
15505 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
15506 EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15507 rm.Encode(5, 0));
15508 return;
15509 }
15510 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
15511 if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
15512 EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
15513 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
15514 rm.Encode(5, 0));
15515 return;
15516 }
15517 }
15518 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
15519}
15520
15521void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015522 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015523 CheckIT(al);
15524 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015525 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015526 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15527 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15528 EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
15529 rd.Encode(22, 12) | rm.Encode(5, 0));
15530 AdvanceIT();
15531 return;
15532 }
15533 } else {
15534 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15535 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15536 EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
15537 rd.Encode(22, 12) | rm.Encode(5, 0));
15538 return;
15539 }
15540 }
15541 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15542}
15543
15544void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015545 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015546 CheckIT(al);
15547 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015548 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015549 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15550 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15551 EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
15552 rd.Encode(22, 12) | rm.Encode(5, 0));
15553 AdvanceIT();
15554 return;
15555 }
15556 } else {
15557 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15558 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15559 EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
15560 rd.Encode(22, 12) | rm.Encode(5, 0));
15561 return;
15562 }
15563 }
15564 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15565}
15566
15567void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015568 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015569 CheckIT(al);
15570 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015571 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015572 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15573 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15574 EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
15575 rd.Encode(22, 12) | rm.Encode(5, 0));
15576 AdvanceIT();
15577 return;
15578 }
15579 } else {
15580 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15581 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15582 EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
15583 rd.Encode(22, 12) | rm.Encode(5, 0));
15584 return;
15585 }
15586 }
15587 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15588}
15589
15590void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015591 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015592 CheckIT(al);
15593 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015594 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015595 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15596 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15597 EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
15598 rd.Encode(22, 12) | rm.Encode(5, 0));
15599 AdvanceIT();
15600 return;
15601 }
15602 } else {
15603 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15604 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15605 EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
15606 rd.Encode(22, 12) | rm.Encode(5, 0));
15607 return;
15608 }
15609 }
15610 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
15611}
15612
15613void Assembler::vcvtb(
15614 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015615 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015616 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015617 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015618 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
15619 if (dt1.Is(F32) && dt2.Is(F16)) {
15620 EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15621 AdvanceIT();
15622 return;
15623 }
15624 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
15625 if (dt1.Is(F16) && dt2.Is(F32)) {
15626 EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15627 AdvanceIT();
15628 return;
15629 }
15630 } else {
15631 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
15632 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
15633 EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15634 rm.Encode(5, 0));
15635 return;
15636 }
15637 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
15638 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
15639 EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15640 rm.Encode(5, 0));
15641 return;
15642 }
15643 }
15644 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15645}
15646
15647void Assembler::vcvtb(
15648 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015649 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015650 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015652 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
15653 if (dt1.Is(F64) && dt2.Is(F16)) {
15654 EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15655 AdvanceIT();
15656 return;
15657 }
15658 } else {
15659 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
15660 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
15661 EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15662 rm.Encode(5, 0));
15663 return;
15664 }
15665 }
15666 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15667}
15668
15669void Assembler::vcvtb(
15670 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015671 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015672 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015673 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015674 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
15675 if (dt1.Is(F16) && dt2.Is(F64)) {
15676 EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15677 AdvanceIT();
15678 return;
15679 }
15680 } else {
15681 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
15682 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
15683 EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15684 rm.Encode(5, 0));
15685 return;
15686 }
15687 }
15688 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
15689}
15690
15691void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015692 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015693 CheckIT(al);
15694 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015695 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015696 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15697 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15698 EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
15699 rd.Encode(22, 12) | rm.Encode(5, 0));
15700 AdvanceIT();
15701 return;
15702 }
15703 } else {
15704 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15705 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15706 EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
15707 rd.Encode(22, 12) | rm.Encode(5, 0));
15708 return;
15709 }
15710 }
15711 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15712}
15713
15714void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015715 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015716 CheckIT(al);
15717 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015718 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015719 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15720 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15721 EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
15722 rd.Encode(22, 12) | rm.Encode(5, 0));
15723 AdvanceIT();
15724 return;
15725 }
15726 } else {
15727 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15728 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15729 EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
15730 rd.Encode(22, 12) | rm.Encode(5, 0));
15731 return;
15732 }
15733 }
15734 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15735}
15736
15737void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015738 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015739 CheckIT(al);
15740 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015741 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015742 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15743 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15744 EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
15745 rd.Encode(22, 12) | rm.Encode(5, 0));
15746 AdvanceIT();
15747 return;
15748 }
15749 } else {
15750 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15751 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15752 EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
15753 rd.Encode(22, 12) | rm.Encode(5, 0));
15754 return;
15755 }
15756 }
15757 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15758}
15759
15760void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015761 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015762 CheckIT(al);
15763 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015764 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015765 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15766 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15767 EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
15768 rd.Encode(22, 12) | rm.Encode(5, 0));
15769 AdvanceIT();
15770 return;
15771 }
15772 } else {
15773 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15774 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15775 EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
15776 rd.Encode(22, 12) | rm.Encode(5, 0));
15777 return;
15778 }
15779 }
15780 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
15781}
15782
15783void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015784 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015785 CheckIT(al);
15786 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015787 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015788 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15789 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15790 EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
15791 rd.Encode(22, 12) | rm.Encode(5, 0));
15792 AdvanceIT();
15793 return;
15794 }
15795 } else {
15796 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15797 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15798 EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
15799 rd.Encode(22, 12) | rm.Encode(5, 0));
15800 return;
15801 }
15802 }
15803 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15804}
15805
15806void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015807 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015808 CheckIT(al);
15809 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015810 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015811 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15812 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15813 EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
15814 rd.Encode(22, 12) | rm.Encode(5, 0));
15815 AdvanceIT();
15816 return;
15817 }
15818 } else {
15819 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15820 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15821 EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
15822 rd.Encode(22, 12) | rm.Encode(5, 0));
15823 return;
15824 }
15825 }
15826 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15827}
15828
15829void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015830 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015831 CheckIT(al);
15832 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015833 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015834 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15835 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15836 EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
15837 rd.Encode(22, 12) | rm.Encode(5, 0));
15838 AdvanceIT();
15839 return;
15840 }
15841 } else {
15842 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15843 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15844 EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
15845 rd.Encode(22, 12) | rm.Encode(5, 0));
15846 return;
15847 }
15848 }
15849 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15850}
15851
15852void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015853 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015854 CheckIT(al);
15855 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015856 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015857 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15858 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15859 EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
15860 rd.Encode(22, 12) | rm.Encode(5, 0));
15861 AdvanceIT();
15862 return;
15863 }
15864 } else {
15865 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15866 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15867 EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
15868 rd.Encode(22, 12) | rm.Encode(5, 0));
15869 return;
15870 }
15871 }
15872 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
15873}
15874
15875void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015876 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015877 CheckIT(al);
15878 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015879 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015880 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
15881 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15882 EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
15883 rd.Encode(22, 12) | rm.Encode(5, 0));
15884 AdvanceIT();
15885 return;
15886 }
15887 } else {
15888 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
15889 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15890 EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
15891 rd.Encode(22, 12) | rm.Encode(5, 0));
15892 return;
15893 }
15894 }
15895 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15896}
15897
15898void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015899 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015900 CheckIT(al);
15901 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015902 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015903 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
15904 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15905 EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
15906 rd.Encode(22, 12) | rm.Encode(5, 0));
15907 AdvanceIT();
15908 return;
15909 }
15910 } else {
15911 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
15912 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15913 EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
15914 rd.Encode(22, 12) | rm.Encode(5, 0));
15915 return;
15916 }
15917 }
15918 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15919}
15920
15921void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015922 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015923 CheckIT(al);
15924 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015925 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015926 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
15927 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15928 EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
15929 rd.Encode(22, 12) | rm.Encode(5, 0));
15930 AdvanceIT();
15931 return;
15932 }
15933 } else {
15934 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
15935 if (encoded_dt.IsValid() && dt2.Is(F32)) {
15936 EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
15937 rd.Encode(22, 12) | rm.Encode(5, 0));
15938 return;
15939 }
15940 }
15941 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15942}
15943
15944void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015946 CheckIT(al);
15947 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015948 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015949 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
15950 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15951 EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
15952 rd.Encode(22, 12) | rm.Encode(5, 0));
15953 AdvanceIT();
15954 return;
15955 }
15956 } else {
15957 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
15958 if (encoded_dt.IsValid() && dt2.Is(F64)) {
15959 EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
15960 rd.Encode(22, 12) | rm.Encode(5, 0));
15961 return;
15962 }
15963 }
15964 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
15965}
15966
15967void Assembler::vcvtr(
15968 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015969 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015970 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015971 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015972 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
15973 if (dt1.Is(U32) && dt2.Is(F32)) {
15974 EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15975 AdvanceIT();
15976 return;
15977 }
15978 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
15979 if (dt1.Is(S32) && dt2.Is(F32)) {
15980 EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15981 AdvanceIT();
15982 return;
15983 }
15984 } else {
15985 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
15986 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
15987 EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15988 rm.Encode(5, 0));
15989 return;
15990 }
15991 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
15992 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
15993 EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15994 rm.Encode(5, 0));
15995 return;
15996 }
15997 }
15998 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
15999}
16000
16001void Assembler::vcvtr(
16002 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016003 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016004 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016005 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016006 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16007 if (dt1.Is(U32) && dt2.Is(F64)) {
16008 EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16009 AdvanceIT();
16010 return;
16011 }
16012 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16013 if (dt1.Is(S32) && dt2.Is(F64)) {
16014 EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16015 AdvanceIT();
16016 return;
16017 }
16018 } else {
16019 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16020 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16021 EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16022 rm.Encode(5, 0));
16023 return;
16024 }
16025 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16026 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16027 EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16028 rm.Encode(5, 0));
16029 return;
16030 }
16031 }
16032 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
16033}
16034
16035void Assembler::vcvtt(
16036 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016037 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016038 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016039 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016040 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16041 if (dt1.Is(F32) && dt2.Is(F16)) {
16042 EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16043 AdvanceIT();
16044 return;
16045 }
16046 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16047 if (dt1.Is(F16) && dt2.Is(F32)) {
16048 EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16049 AdvanceIT();
16050 return;
16051 }
16052 } else {
16053 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16054 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16055 EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16056 rm.Encode(5, 0));
16057 return;
16058 }
16059 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16060 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16061 EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16062 rm.Encode(5, 0));
16063 return;
16064 }
16065 }
16066 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16067}
16068
16069void Assembler::vcvtt(
16070 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016071 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016072 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016074 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16075 if (dt1.Is(F64) && dt2.Is(F16)) {
16076 EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16077 AdvanceIT();
16078 return;
16079 }
16080 } else {
16081 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16082 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16083 EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16084 rm.Encode(5, 0));
16085 return;
16086 }
16087 }
16088 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16089}
16090
16091void Assembler::vcvtt(
16092 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016093 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016094 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016095 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016096 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16097 if (dt1.Is(F16) && dt2.Is(F64)) {
16098 EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16099 AdvanceIT();
16100 return;
16101 }
16102 } else {
16103 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16104 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16105 EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16106 rm.Encode(5, 0));
16107 return;
16108 }
16109 }
16110 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
16111}
16112
16113void Assembler::vdiv(
16114 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016115 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016116 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016117 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016118 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
16119 if (dt.Is(F32)) {
16120 EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16121 rm.Encode(5, 0));
16122 AdvanceIT();
16123 return;
16124 }
16125 } else {
16126 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
16127 if (dt.Is(F32) && cond.IsNotNever()) {
16128 EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16129 rn.Encode(7, 16) | rm.Encode(5, 0));
16130 return;
16131 }
16132 }
16133 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
16134}
16135
16136void Assembler::vdiv(
16137 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016138 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016139 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016140 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016141 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
16142 if (dt.Is(F64)) {
16143 EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16144 rm.Encode(5, 0));
16145 AdvanceIT();
16146 return;
16147 }
16148 } else {
16149 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
16150 if (dt.Is(F64) && cond.IsNotNever()) {
16151 EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16152 rn.Encode(7, 16) | rm.Encode(5, 0));
16153 return;
16154 }
16155 }
16156 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
16157}
16158
16159void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016160 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016161 CheckIT(cond);
16162 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016163 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016164 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
16165 if (encoded_dt.IsValid()) {
16166 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16167 EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16168 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16169 rd.Encode(7, 16) | (rt.GetCode() << 12));
16170 AdvanceIT();
16171 return;
16172 }
16173 }
16174 } else {
16175 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
16176 if (encoded_dt.IsValid() && cond.IsNotNever()) {
16177 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16178 EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
16179 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16180 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16181 rd.Encode(7, 16) | (rt.GetCode() << 12));
16182 return;
16183 }
16184 }
16185 }
16186 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
16187}
16188
16189void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016190 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016191 CheckIT(cond);
16192 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016193 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016194 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
16195 if (encoded_dt.IsValid()) {
16196 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16197 EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16198 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16199 rd.Encode(7, 16) | (rt.GetCode() << 12));
16200 AdvanceIT();
16201 return;
16202 }
16203 }
16204 } else {
16205 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
16206 if (encoded_dt.IsValid() && cond.IsNotNever()) {
16207 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16208 EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
16209 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
16210 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
16211 rd.Encode(7, 16) | (rt.GetCode() << 12));
16212 return;
16213 }
16214 }
16215 }
16216 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
16217}
16218
16219void Assembler::vdup(Condition cond,
16220 DataType dt,
16221 DRegister rd,
16222 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016223 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016224 CheckIT(cond);
16225 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016226 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016227 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
16228 if (encoded_dt.IsValid()) {
16229 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16230 EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
16231 rd.Encode(22, 12) | rm.Encode(5, 0));
16232 AdvanceIT();
16233 return;
16234 }
16235 }
16236 } else {
16237 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
16238 if (encoded_dt.IsValid()) {
16239 if (cond.Is(al)) {
16240 EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
16241 rd.Encode(22, 12) | rm.Encode(5, 0));
16242 return;
16243 }
16244 }
16245 }
16246 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
16247}
16248
16249void Assembler::vdup(Condition cond,
16250 DataType dt,
16251 QRegister rd,
16252 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016253 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016254 CheckIT(cond);
16255 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016256 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016257 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
16258 if (encoded_dt.IsValid()) {
16259 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16260 EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
16261 rd.Encode(22, 12) | rm.Encode(5, 0));
16262 AdvanceIT();
16263 return;
16264 }
16265 }
16266 } else {
16267 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
16268 if (encoded_dt.IsValid()) {
16269 if (cond.Is(al)) {
16270 EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
16271 rd.Encode(22, 12) | rm.Encode(5, 0));
16272 return;
16273 }
16274 }
16275 }
16276 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
16277}
16278
16279void Assembler::veor(
16280 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016281 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016282 CheckIT(cond);
16283 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016285 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
16286 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16287 EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16288 rm.Encode(5, 0));
16289 AdvanceIT();
16290 return;
16291 }
16292 } else {
16293 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
16294 if (cond.Is(al)) {
16295 EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16296 rm.Encode(5, 0));
16297 return;
16298 }
16299 }
16300 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
16301}
16302
16303void Assembler::veor(
16304 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016305 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016306 CheckIT(cond);
16307 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016308 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016309 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
16310 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16311 EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16312 rm.Encode(5, 0));
16313 AdvanceIT();
16314 return;
16315 }
16316 } else {
16317 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
16318 if (cond.Is(al)) {
16319 EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16320 rm.Encode(5, 0));
16321 return;
16322 }
16323 }
16324 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
16325}
16326
16327void Assembler::vext(Condition cond,
16328 DataType dt,
16329 DRegister rd,
16330 DRegister rn,
16331 DRegister rm,
16332 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016333 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016334 CheckIT(cond);
16335 if (operand.IsImmediate()) {
16336 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
16337 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016338 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016339 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
16340 if (dt.Is(Untyped8) && (imm <= 7)) {
16341 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16342 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16343 rm.Encode(5, 0) | (imm << 8));
16344 AdvanceIT();
16345 return;
16346 }
16347 }
16348 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
16349 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
16350 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16351 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16352 uint32_t imm4 = imm / dt.GetSize();
16353 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16354 rm.Encode(5, 0) | (imm4 << 8));
16355 AdvanceIT();
16356 return;
16357 }
16358 }
16359 } else {
16360 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
16361 if (dt.Is(Untyped8) && (imm <= 7)) {
16362 if (cond.Is(al)) {
16363 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16364 rm.Encode(5, 0) | (imm << 8));
16365 return;
16366 }
16367 }
16368 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
16369 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
16370 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16371 if (cond.Is(al)) {
16372 uint32_t imm4 = imm / dt.GetSize();
16373 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16374 rm.Encode(5, 0) | (imm4 << 8));
16375 return;
16376 }
16377 }
16378 }
16379 }
16380 }
16381 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
16382}
16383
16384void Assembler::vext(Condition cond,
16385 DataType dt,
16386 QRegister rd,
16387 QRegister rn,
16388 QRegister rm,
16389 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016390 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016391 CheckIT(cond);
16392 if (operand.IsImmediate()) {
16393 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
16394 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016396 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
16397 if (dt.Is(Untyped8) && (imm <= 15)) {
16398 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16399 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16400 rm.Encode(5, 0) | (imm << 8));
16401 AdvanceIT();
16402 return;
16403 }
16404 }
16405 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
16406 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
16407 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16408 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16409 uint32_t imm4 = imm / dt.GetSize();
16410 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16411 rm.Encode(5, 0) | (imm4 << 8));
16412 AdvanceIT();
16413 return;
16414 }
16415 }
16416 } else {
16417 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
16418 if (dt.Is(Untyped8) && (imm <= 15)) {
16419 if (cond.Is(al)) {
16420 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16421 rm.Encode(5, 0) | (imm << 8));
16422 return;
16423 }
16424 }
16425 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
16426 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
16427 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
16428 if (cond.Is(al)) {
16429 uint32_t imm4 = imm / dt.GetSize();
16430 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16431 rm.Encode(5, 0) | (imm4 << 8));
16432 return;
16433 }
16434 }
16435 }
16436 }
16437 }
16438 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
16439}
16440
16441void Assembler::vfma(
16442 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016443 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016444 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016445 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016446 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
16447 if (dt.Is(F32)) {
16448 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16449 EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16450 rm.Encode(5, 0));
16451 AdvanceIT();
16452 return;
16453 }
16454 }
16455 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
16456 if (dt.Is(F64)) {
16457 EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16458 rm.Encode(5, 0));
16459 AdvanceIT();
16460 return;
16461 }
16462 } else {
16463 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
16464 if (dt.Is(F32)) {
16465 if (cond.Is(al)) {
16466 EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16467 rm.Encode(5, 0));
16468 return;
16469 }
16470 }
16471 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
16472 if (dt.Is(F64) && cond.IsNotNever()) {
16473 EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16474 rn.Encode(7, 16) | rm.Encode(5, 0));
16475 return;
16476 }
16477 }
16478 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16479}
16480
16481void Assembler::vfma(
16482 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016483 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016484 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016485 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016486 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
16487 if (dt.Is(F32)) {
16488 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16489 EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16490 rm.Encode(5, 0));
16491 AdvanceIT();
16492 return;
16493 }
16494 }
16495 } else {
16496 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
16497 if (dt.Is(F32)) {
16498 if (cond.Is(al)) {
16499 EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16500 rm.Encode(5, 0));
16501 return;
16502 }
16503 }
16504 }
16505 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16506}
16507
16508void Assembler::vfma(
16509 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016510 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016511 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016512 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016513 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
16514 if (dt.Is(F32)) {
16515 EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16516 rm.Encode(5, 0));
16517 AdvanceIT();
16518 return;
16519 }
16520 } else {
16521 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
16522 if (dt.Is(F32) && cond.IsNotNever()) {
16523 EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16524 rn.Encode(7, 16) | rm.Encode(5, 0));
16525 return;
16526 }
16527 }
16528 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
16529}
16530
16531void Assembler::vfms(
16532 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016534 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016536 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
16537 if (dt.Is(F32)) {
16538 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16539 EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16540 rm.Encode(5, 0));
16541 AdvanceIT();
16542 return;
16543 }
16544 }
16545 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
16546 if (dt.Is(F64)) {
16547 EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16548 rm.Encode(5, 0));
16549 AdvanceIT();
16550 return;
16551 }
16552 } else {
16553 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
16554 if (dt.Is(F32)) {
16555 if (cond.Is(al)) {
16556 EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16557 rm.Encode(5, 0));
16558 return;
16559 }
16560 }
16561 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
16562 if (dt.Is(F64) && cond.IsNotNever()) {
16563 EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16564 rn.Encode(7, 16) | rm.Encode(5, 0));
16565 return;
16566 }
16567 }
16568 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16569}
16570
16571void Assembler::vfms(
16572 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016573 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016574 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016575 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016576 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
16577 if (dt.Is(F32)) {
16578 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16579 EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16580 rm.Encode(5, 0));
16581 AdvanceIT();
16582 return;
16583 }
16584 }
16585 } else {
16586 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
16587 if (dt.Is(F32)) {
16588 if (cond.Is(al)) {
16589 EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16590 rm.Encode(5, 0));
16591 return;
16592 }
16593 }
16594 }
16595 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16596}
16597
16598void Assembler::vfms(
16599 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016600 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016601 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016602 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016603 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
16604 if (dt.Is(F32)) {
16605 EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16606 rm.Encode(5, 0));
16607 AdvanceIT();
16608 return;
16609 }
16610 } else {
16611 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
16612 if (dt.Is(F32) && cond.IsNotNever()) {
16613 EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16614 rn.Encode(7, 16) | rm.Encode(5, 0));
16615 return;
16616 }
16617 }
16618 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
16619}
16620
16621void Assembler::vfnma(
16622 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016623 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016624 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016625 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016626 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
16627 if (dt.Is(F32)) {
16628 EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16629 rm.Encode(5, 0));
16630 AdvanceIT();
16631 return;
16632 }
16633 } else {
16634 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
16635 if (dt.Is(F32) && cond.IsNotNever()) {
16636 EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16637 rn.Encode(7, 16) | rm.Encode(5, 0));
16638 return;
16639 }
16640 }
16641 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
16642}
16643
16644void Assembler::vfnma(
16645 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016646 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016647 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016648 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016649 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
16650 if (dt.Is(F64)) {
16651 EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16652 rm.Encode(5, 0));
16653 AdvanceIT();
16654 return;
16655 }
16656 } else {
16657 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
16658 if (dt.Is(F64) && cond.IsNotNever()) {
16659 EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16660 rn.Encode(7, 16) | rm.Encode(5, 0));
16661 return;
16662 }
16663 }
16664 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
16665}
16666
16667void Assembler::vfnms(
16668 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016669 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016670 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016671 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016672 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
16673 if (dt.Is(F32)) {
16674 EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16675 rm.Encode(5, 0));
16676 AdvanceIT();
16677 return;
16678 }
16679 } else {
16680 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
16681 if (dt.Is(F32) && cond.IsNotNever()) {
16682 EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16683 rn.Encode(7, 16) | rm.Encode(5, 0));
16684 return;
16685 }
16686 }
16687 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
16688}
16689
16690void Assembler::vfnms(
16691 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016692 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016693 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016694 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016695 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
16696 if (dt.Is(F64)) {
16697 EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
16698 rm.Encode(5, 0));
16699 AdvanceIT();
16700 return;
16701 }
16702 } else {
16703 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
16704 if (dt.Is(F64) && cond.IsNotNever()) {
16705 EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16706 rn.Encode(7, 16) | rm.Encode(5, 0));
16707 return;
16708 }
16709 }
16710 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
16711}
16712
16713void Assembler::vhadd(
16714 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016715 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016716 CheckIT(cond);
16717 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016718 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016719 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
16720 if (encoded_dt.IsValid()) {
16721 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16722 EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16723 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16724 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16725 AdvanceIT();
16726 return;
16727 }
16728 }
16729 } else {
16730 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
16731 if (encoded_dt.IsValid()) {
16732 if (cond.Is(al)) {
16733 EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16734 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16735 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16736 return;
16737 }
16738 }
16739 }
16740 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
16741}
16742
16743void Assembler::vhadd(
16744 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016745 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016746 CheckIT(cond);
16747 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016748 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016749 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
16750 if (encoded_dt.IsValid()) {
16751 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16752 EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16753 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16754 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16755 AdvanceIT();
16756 return;
16757 }
16758 }
16759 } else {
16760 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
16761 if (encoded_dt.IsValid()) {
16762 if (cond.Is(al)) {
16763 EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16764 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16765 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16766 return;
16767 }
16768 }
16769 }
16770 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
16771}
16772
16773void Assembler::vhsub(
16774 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016775 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016776 CheckIT(cond);
16777 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016778 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016779 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
16780 if (encoded_dt.IsValid()) {
16781 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16782 EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16783 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16784 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16785 AdvanceIT();
16786 return;
16787 }
16788 }
16789 } else {
16790 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
16791 if (encoded_dt.IsValid()) {
16792 if (cond.Is(al)) {
16793 EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16794 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16795 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16796 return;
16797 }
16798 }
16799 }
16800 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
16801}
16802
16803void Assembler::vhsub(
16804 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016805 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016806 CheckIT(cond);
16807 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016808 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016809 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
16810 if (encoded_dt.IsValid()) {
16811 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16812 EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16813 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
16814 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16815 AdvanceIT();
16816 return;
16817 }
16818 }
16819 } else {
16820 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
16821 if (encoded_dt.IsValid()) {
16822 if (cond.Is(al)) {
16823 EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
16824 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
16825 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
16826 return;
16827 }
16828 }
16829 }
16830 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
16831}
16832
16833void Assembler::vld1(Condition cond,
16834 DataType dt,
16835 const NeonRegisterList& nreglist,
16836 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016837 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016838 CheckIT(cond);
16839 if (operand.IsImmediateZero()) {
16840 Register rn = operand.GetBaseRegister();
16841 Alignment align = operand.GetAlignment();
16842 Dt_size_6 encoded_dt(dt);
16843 Dt_size_7 encoded_dt_2(dt);
16844 Align_align_1 encoded_align_1(align, nreglist);
16845 Align_a_1 encoded_align_2(align, dt);
16846 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016847 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016848 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16849 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16850 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16851 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
16852 ((!rn.IsPC()) || AllowUnpredictable())) {
16853 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16854 const DRegister& first = nreglist.GetFirstDRegister();
16855 uint32_t len_encoding;
16856 switch (nreglist.GetLength()) {
16857 default:
16858 VIXL_UNREACHABLE_OR_FALLTHROUGH();
16859 case 1:
16860 len_encoding = 0x7;
16861 break;
16862 case 2:
16863 len_encoding = 0xa;
16864 break;
16865 case 3:
16866 len_encoding = 0x6;
16867 break;
16868 case 4:
16869 len_encoding = 0x2;
16870 break;
16871 }
16872 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
16873 (encoded_align_1.GetEncodingValue() << 4) |
16874 first.Encode(22, 12) | (len_encoding << 8) |
16875 (rn.GetCode() << 16));
16876 AdvanceIT();
16877 return;
16878 }
16879 }
16880 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16881 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16882 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16883 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
16884 ((!rn.IsPC()) || AllowUnpredictable())) {
16885 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16886 const DRegister& first = nreglist.GetFirstDRegister();
16887 uint32_t len_encoding;
16888 switch (nreglist.GetLength()) {
16889 default:
16890 VIXL_UNREACHABLE_OR_FALLTHROUGH();
16891 case 1:
16892 len_encoding = 0x7;
16893 break;
16894 case 2:
16895 len_encoding = 0xa;
16896 break;
16897 case 3:
16898 len_encoding = 0x6;
16899 break;
16900 case 4:
16901 len_encoding = 0x2;
16902 break;
16903 }
16904 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
16905 (encoded_align_1.GetEncodingValue() << 4) |
16906 first.Encode(22, 12) | (len_encoding << 8) |
16907 (rn.GetCode() << 16));
16908 AdvanceIT();
16909 return;
16910 }
16911 }
16912 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16913 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
16914 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
16915 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
16916 ((!rn.IsPC()) || AllowUnpredictable())) {
16917 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16918 const DRegister& first = nreglist.GetFirstDRegister();
16919 uint32_t len_encoding = nreglist.GetLength() - 1;
16920 EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
16921 (encoded_align_2.GetEncodingValue() << 4) |
16922 first.Encode(22, 12) | (len_encoding << 5) |
16923 (rn.GetCode() << 16));
16924 AdvanceIT();
16925 return;
16926 }
16927 }
16928 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16929 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
16930 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
16931 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
16932 ((!rn.IsPC()) || AllowUnpredictable())) {
16933 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16934 const DRegister& first = nreglist.GetFirstDRegister();
16935 uint32_t len_encoding = nreglist.GetLength() - 1;
16936 EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
16937 (encoded_align_2.GetEncodingValue() << 4) |
16938 first.Encode(22, 12) | (len_encoding << 5) |
16939 (rn.GetCode() << 16));
16940 AdvanceIT();
16941 return;
16942 }
16943 }
16944 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
16945 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
16946 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
16947 encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
16948 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16949 const DRegister& first = nreglist.GetFirstDRegister();
16950 EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
16951 (encoded_align_3.GetEncodingValue() << 4) |
16952 first.Encode(22, 12) | (rn.GetCode() << 16));
16953 AdvanceIT();
16954 return;
16955 }
16956 }
16957 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
16958 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
16959 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
16960 encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
16961 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16962 const DRegister& first = nreglist.GetFirstDRegister();
16963 EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
16964 (encoded_align_3.GetEncodingValue() << 4) |
16965 first.Encode(22, 12) | (rn.GetCode() << 16));
16966 AdvanceIT();
16967 return;
16968 }
16969 }
16970 } else {
16971 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
16972 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
16973 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
16974 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
16975 ((!rn.IsPC()) || AllowUnpredictable())) {
16976 if (cond.Is(al)) {
16977 const DRegister& first = nreglist.GetFirstDRegister();
16978 uint32_t len_encoding;
16979 switch (nreglist.GetLength()) {
16980 default:
16981 VIXL_UNREACHABLE_OR_FALLTHROUGH();
16982 case 1:
16983 len_encoding = 0x7;
16984 break;
16985 case 2:
16986 len_encoding = 0xa;
16987 break;
16988 case 3:
16989 len_encoding = 0x6;
16990 break;
16991 case 4:
16992 len_encoding = 0x2;
16993 break;
16994 }
16995 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
16996 (encoded_align_1.GetEncodingValue() << 4) |
16997 first.Encode(22, 12) | (len_encoding << 8) |
16998 (rn.GetCode() << 16));
16999 return;
17000 }
17001 }
17002 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17003 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17004 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17005 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17006 ((!rn.IsPC()) || AllowUnpredictable())) {
17007 if (cond.Is(al)) {
17008 const DRegister& first = nreglist.GetFirstDRegister();
17009 uint32_t len_encoding;
17010 switch (nreglist.GetLength()) {
17011 default:
17012 VIXL_UNREACHABLE_OR_FALLTHROUGH();
17013 case 1:
17014 len_encoding = 0x7;
17015 break;
17016 case 2:
17017 len_encoding = 0xa;
17018 break;
17019 case 3:
17020 len_encoding = 0x6;
17021 break;
17022 case 4:
17023 len_encoding = 0x2;
17024 break;
17025 }
17026 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17027 (encoded_align_1.GetEncodingValue() << 4) |
17028 first.Encode(22, 12) | (len_encoding << 8) |
17029 (rn.GetCode() << 16));
17030 return;
17031 }
17032 }
17033 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17034 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17035 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17036 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17037 ((!rn.IsPC()) || AllowUnpredictable())) {
17038 if (cond.Is(al)) {
17039 const DRegister& first = nreglist.GetFirstDRegister();
17040 uint32_t len_encoding = nreglist.GetLength() - 1;
17041 EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
17042 (encoded_align_2.GetEncodingValue() << 4) |
17043 first.Encode(22, 12) | (len_encoding << 5) |
17044 (rn.GetCode() << 16));
17045 return;
17046 }
17047 }
17048 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17049 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17050 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17051 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17052 ((!rn.IsPC()) || AllowUnpredictable())) {
17053 if (cond.Is(al)) {
17054 const DRegister& first = nreglist.GetFirstDRegister();
17055 uint32_t len_encoding = nreglist.GetLength() - 1;
17056 EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
17057 (encoded_align_2.GetEncodingValue() << 4) |
17058 first.Encode(22, 12) | (len_encoding << 5) |
17059 (rn.GetCode() << 16));
17060 return;
17061 }
17062 }
17063 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17064 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17065 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
17066 encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
17067 if (cond.Is(al)) {
17068 const DRegister& first = nreglist.GetFirstDRegister();
17069 EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
17070 (encoded_align_3.GetEncodingValue() << 4) |
17071 first.Encode(22, 12) | (rn.GetCode() << 16));
17072 return;
17073 }
17074 }
17075 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17076 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17077 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
17078 encoded_align_3.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
17079 if (cond.Is(al)) {
17080 const DRegister& first = nreglist.GetFirstDRegister();
17081 EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
17082 (encoded_align_3.GetEncodingValue() << 4) |
17083 first.Encode(22, 12) | (rn.GetCode() << 16));
17084 return;
17085 }
17086 }
17087 }
17088 }
17089 if (operand.IsPlainRegister()) {
17090 Register rn = operand.GetBaseRegister();
17091 Alignment align = operand.GetAlignment();
17092 Register rm = operand.GetOffsetRegister();
17093 Dt_size_6 encoded_dt(dt);
17094 Dt_size_7 encoded_dt_2(dt);
17095 Align_align_1 encoded_align_1(align, nreglist);
17096 Align_a_1 encoded_align_2(align, dt);
17097 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017098 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017099 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17100 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17101 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17102 !rm.IsPC() && !rm.IsSP()) {
17103 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17104 const DRegister& first = nreglist.GetFirstDRegister();
17105 uint32_t len_encoding;
17106 switch (nreglist.GetLength()) {
17107 default:
17108 VIXL_UNREACHABLE_OR_FALLTHROUGH();
17109 case 1:
17110 len_encoding = 0x7;
17111 break;
17112 case 2:
17113 len_encoding = 0xa;
17114 break;
17115 case 3:
17116 len_encoding = 0x6;
17117 break;
17118 case 4:
17119 len_encoding = 0x2;
17120 break;
17121 }
17122 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17123 (encoded_align_1.GetEncodingValue() << 4) |
17124 first.Encode(22, 12) | (len_encoding << 8) |
17125 (rn.GetCode() << 16) | rm.GetCode());
17126 AdvanceIT();
17127 return;
17128 }
17129 }
17130 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17131 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17132 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17133 !rm.IsPC() && !rm.IsSP()) {
17134 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17135 const DRegister& first = nreglist.GetFirstDRegister();
17136 uint32_t len_encoding = nreglist.GetLength() - 1;
17137 EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
17138 (encoded_align_2.GetEncodingValue() << 4) |
17139 first.Encode(22, 12) | (len_encoding << 5) |
17140 (rn.GetCode() << 16) | rm.GetCode());
17141 AdvanceIT();
17142 return;
17143 }
17144 }
17145 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17146 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17147 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
17148 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17149 const DRegister& first = nreglist.GetFirstDRegister();
17150 EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
17151 (encoded_align_3.GetEncodingValue() << 4) |
17152 first.Encode(22, 12) | (rn.GetCode() << 16) |
17153 rm.GetCode());
17154 AdvanceIT();
17155 return;
17156 }
17157 }
17158 } else {
17159 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17160 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17161 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
17162 !rm.IsPC() && !rm.IsSP()) {
17163 if (cond.Is(al)) {
17164 const DRegister& first = nreglist.GetFirstDRegister();
17165 uint32_t len_encoding;
17166 switch (nreglist.GetLength()) {
17167 default:
17168 VIXL_UNREACHABLE_OR_FALLTHROUGH();
17169 case 1:
17170 len_encoding = 0x7;
17171 break;
17172 case 2:
17173 len_encoding = 0xa;
17174 break;
17175 case 3:
17176 len_encoding = 0x6;
17177 break;
17178 case 4:
17179 len_encoding = 0x2;
17180 break;
17181 }
17182 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17183 (encoded_align_1.GetEncodingValue() << 4) |
17184 first.Encode(22, 12) | (len_encoding << 8) |
17185 (rn.GetCode() << 16) | rm.GetCode());
17186 return;
17187 }
17188 }
17189 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17190 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17191 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
17192 !rm.IsPC() && !rm.IsSP()) {
17193 if (cond.Is(al)) {
17194 const DRegister& first = nreglist.GetFirstDRegister();
17195 uint32_t len_encoding = nreglist.GetLength() - 1;
17196 EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
17197 (encoded_align_2.GetEncodingValue() << 4) |
17198 first.Encode(22, 12) | (len_encoding << 5) |
17199 (rn.GetCode() << 16) | rm.GetCode());
17200 return;
17201 }
17202 }
17203 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17204 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
17205 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
17206 if (cond.Is(al)) {
17207 const DRegister& first = nreglist.GetFirstDRegister();
17208 EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
17209 (encoded_align_3.GetEncodingValue() << 4) |
17210 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17211 return;
17212 }
17213 }
17214 }
17215 }
17216 Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
17217}
17218
17219void Assembler::vld2(Condition cond,
17220 DataType dt,
17221 const NeonRegisterList& nreglist,
17222 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017223 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017224 CheckIT(cond);
17225 if (operand.IsImmediateZero()) {
17226 Register rn = operand.GetBaseRegister();
17227 Alignment align = operand.GetAlignment();
17228 Dt_size_7 encoded_dt(dt);
17229 Align_align_2 encoded_align_1(align, nreglist);
17230 Align_a_2 encoded_align_2(align, dt);
17231 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017232 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017233 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17234 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17235 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17236 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17237 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17238 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17239 ((!rn.IsPC()) || AllowUnpredictable())) {
17240 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17241 const DRegister& first = nreglist.GetFirstDRegister();
17242 uint32_t len_encoding;
17243 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17244 len_encoding = 0x8;
17245 }
17246 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17247 len_encoding = 0x9;
17248 }
17249 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17250 len_encoding = 0x3;
17251 }
17252 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17253 (encoded_align_1.GetEncodingValue() << 4) |
17254 first.Encode(22, 12) | (len_encoding << 8) |
17255 (rn.GetCode() << 16));
17256 AdvanceIT();
17257 return;
17258 }
17259 }
17260 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17261 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17262 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17263 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17264 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17265 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17266 ((!rn.IsPC()) || AllowUnpredictable())) {
17267 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17268 const DRegister& first = nreglist.GetFirstDRegister();
17269 uint32_t len_encoding;
17270 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17271 len_encoding = 0x8;
17272 }
17273 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17274 len_encoding = 0x9;
17275 }
17276 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17277 len_encoding = 0x3;
17278 }
17279 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17280 (encoded_align_1.GetEncodingValue() << 4) |
17281 first.Encode(22, 12) | (len_encoding << 8) |
17282 (rn.GetCode() << 16));
17283 AdvanceIT();
17284 return;
17285 }
17286 }
17287 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17288 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17289 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17290 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17291 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17292 ((!rn.IsPC()) || AllowUnpredictable())) {
17293 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17294 const DRegister& first = nreglist.GetFirstDRegister();
17295 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17296 EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
17297 (encoded_align_2.GetEncodingValue() << 4) |
17298 first.Encode(22, 12) | (len_encoding << 5) |
17299 (rn.GetCode() << 16));
17300 AdvanceIT();
17301 return;
17302 }
17303 }
17304 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17305 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17306 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17307 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17308 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17309 ((!rn.IsPC()) || AllowUnpredictable())) {
17310 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17311 const DRegister& first = nreglist.GetFirstDRegister();
17312 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17313 EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
17314 (encoded_align_2.GetEncodingValue() << 4) |
17315 first.Encode(22, 12) | (len_encoding << 5) |
17316 (rn.GetCode() << 16));
17317 AdvanceIT();
17318 return;
17319 }
17320 }
17321 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17322 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17323 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17324 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17325 (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
17326 ((!rn.IsPC()) || AllowUnpredictable())) {
17327 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17328 const DRegister& first = nreglist.GetFirstDRegister();
17329 EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
17330 (encoded_align_3.GetEncodingValue() << 4) |
17331 first.Encode(22, 12) | (rn.GetCode() << 16));
17332 AdvanceIT();
17333 return;
17334 }
17335 }
17336 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17337 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17338 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17339 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17340 (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
17341 ((!rn.IsPC()) || AllowUnpredictable())) {
17342 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17343 const DRegister& first = nreglist.GetFirstDRegister();
17344 EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
17345 (encoded_align_3.GetEncodingValue() << 4) |
17346 first.Encode(22, 12) | (rn.GetCode() << 16));
17347 AdvanceIT();
17348 return;
17349 }
17350 }
17351 } else {
17352 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17353 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17354 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17355 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17356 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17357 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17358 ((!rn.IsPC()) || AllowUnpredictable())) {
17359 if (cond.Is(al)) {
17360 const DRegister& first = nreglist.GetFirstDRegister();
17361 uint32_t len_encoding;
17362 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17363 len_encoding = 0x8;
17364 }
17365 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17366 len_encoding = 0x9;
17367 }
17368 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17369 len_encoding = 0x3;
17370 }
17371 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
17372 (encoded_align_1.GetEncodingValue() << 4) |
17373 first.Encode(22, 12) | (len_encoding << 8) |
17374 (rn.GetCode() << 16));
17375 return;
17376 }
17377 }
17378 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17379 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17380 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17381 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17382 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17383 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17384 ((!rn.IsPC()) || AllowUnpredictable())) {
17385 if (cond.Is(al)) {
17386 const DRegister& first = nreglist.GetFirstDRegister();
17387 uint32_t len_encoding;
17388 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17389 len_encoding = 0x8;
17390 }
17391 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17392 len_encoding = 0x9;
17393 }
17394 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17395 len_encoding = 0x3;
17396 }
17397 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17398 (encoded_align_1.GetEncodingValue() << 4) |
17399 first.Encode(22, 12) | (len_encoding << 8) |
17400 (rn.GetCode() << 16));
17401 return;
17402 }
17403 }
17404 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17405 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17406 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17407 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17408 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17409 ((!rn.IsPC()) || AllowUnpredictable())) {
17410 if (cond.Is(al)) {
17411 const DRegister& first = nreglist.GetFirstDRegister();
17412 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17413 EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
17414 (encoded_align_2.GetEncodingValue() << 4) |
17415 first.Encode(22, 12) | (len_encoding << 5) |
17416 (rn.GetCode() << 16));
17417 return;
17418 }
17419 }
17420 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17421 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17422 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17423 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17424 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17425 ((!rn.IsPC()) || AllowUnpredictable())) {
17426 if (cond.Is(al)) {
17427 const DRegister& first = nreglist.GetFirstDRegister();
17428 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17429 EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
17430 (encoded_align_2.GetEncodingValue() << 4) |
17431 first.Encode(22, 12) | (len_encoding << 5) |
17432 (rn.GetCode() << 16));
17433 return;
17434 }
17435 }
17436 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17437 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17438 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17439 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17440 (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
17441 ((!rn.IsPC()) || AllowUnpredictable())) {
17442 if (cond.Is(al)) {
17443 const DRegister& first = nreglist.GetFirstDRegister();
17444 EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
17445 (encoded_align_3.GetEncodingValue() << 4) |
17446 first.Encode(22, 12) | (rn.GetCode() << 16));
17447 return;
17448 }
17449 }
17450 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17451 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17452 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17453 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17454 (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
17455 ((!rn.IsPC()) || AllowUnpredictable())) {
17456 if (cond.Is(al)) {
17457 const DRegister& first = nreglist.GetFirstDRegister();
17458 EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
17459 (encoded_align_3.GetEncodingValue() << 4) |
17460 first.Encode(22, 12) | (rn.GetCode() << 16));
17461 return;
17462 }
17463 }
17464 }
17465 }
17466 if (operand.IsPlainRegister()) {
17467 Register rn = operand.GetBaseRegister();
17468 Alignment align = operand.GetAlignment();
17469 Register rm = operand.GetOffsetRegister();
17470 Dt_size_7 encoded_dt(dt);
17471 Align_align_2 encoded_align_1(align, nreglist);
17472 Align_a_2 encoded_align_2(align, dt);
17473 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017474 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017475 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17476 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17477 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17478 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17479 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17480 !rm.IsPC() && !rm.IsSP()) {
17481 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17482 const DRegister& first = nreglist.GetFirstDRegister();
17483 uint32_t len_encoding;
17484 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17485 len_encoding = 0x8;
17486 }
17487 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17488 len_encoding = 0x9;
17489 }
17490 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17491 len_encoding = 0x3;
17492 }
17493 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17494 (encoded_align_1.GetEncodingValue() << 4) |
17495 first.Encode(22, 12) | (len_encoding << 8) |
17496 (rn.GetCode() << 16) | rm.GetCode());
17497 AdvanceIT();
17498 return;
17499 }
17500 }
17501 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17502 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17503 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17504 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17505 !rm.IsPC() && !rm.IsSP()) {
17506 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17507 const DRegister& first = nreglist.GetFirstDRegister();
17508 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17509 EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
17510 (encoded_align_2.GetEncodingValue() << 4) |
17511 first.Encode(22, 12) | (len_encoding << 5) |
17512 (rn.GetCode() << 16) | rm.GetCode());
17513 AdvanceIT();
17514 return;
17515 }
17516 }
17517 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17518 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17519 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17520 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17521 !rm.IsPC() && !rm.IsSP()) {
17522 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17523 const DRegister& first = nreglist.GetFirstDRegister();
17524 EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
17525 (encoded_align_3.GetEncodingValue() << 4) |
17526 first.Encode(22, 12) | (rn.GetCode() << 16) |
17527 rm.GetCode());
17528 AdvanceIT();
17529 return;
17530 }
17531 }
17532 } else {
17533 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17534 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17535 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17536 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
17537 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
17538 !rm.IsPC() && !rm.IsSP()) {
17539 if (cond.Is(al)) {
17540 const DRegister& first = nreglist.GetFirstDRegister();
17541 uint32_t len_encoding;
17542 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
17543 len_encoding = 0x8;
17544 }
17545 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
17546 len_encoding = 0x9;
17547 }
17548 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
17549 len_encoding = 0x3;
17550 }
17551 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17552 (encoded_align_1.GetEncodingValue() << 4) |
17553 first.Encode(22, 12) | (len_encoding << 8) |
17554 (rn.GetCode() << 16) | rm.GetCode());
17555 return;
17556 }
17557 }
17558 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17559 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17560 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17561 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17562 !rm.IsPC() && !rm.IsSP()) {
17563 if (cond.Is(al)) {
17564 const DRegister& first = nreglist.GetFirstDRegister();
17565 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17566 EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
17567 (encoded_align_2.GetEncodingValue() << 4) |
17568 first.Encode(22, 12) | (len_encoding << 5) |
17569 (rn.GetCode() << 16) | rm.GetCode());
17570 return;
17571 }
17572 }
17573 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17574 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17575 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
17576 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
17577 !rm.IsPC() && !rm.IsSP()) {
17578 if (cond.Is(al)) {
17579 const DRegister& first = nreglist.GetFirstDRegister();
17580 EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
17581 (encoded_align_3.GetEncodingValue() << 4) |
17582 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17583 return;
17584 }
17585 }
17586 }
17587 }
17588 Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
17589}
17590
17591void Assembler::vld3(Condition cond,
17592 DataType dt,
17593 const NeonRegisterList& nreglist,
17594 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017595 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017596 CheckIT(cond);
17597 if (operand.IsImmediateZero()) {
17598 Register rn = operand.GetBaseRegister();
17599 Alignment align = operand.GetAlignment();
17600 Dt_size_7 encoded_dt(dt);
17601 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017602 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017603 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17604 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17605 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17606 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17607 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17608 ((!rn.IsPC()) || AllowUnpredictable())) {
17609 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17610 const DRegister& first = nreglist.GetFirstDRegister();
17611 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17612 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17613 (encoded_align_1.GetEncodingValue() << 4) |
17614 first.Encode(22, 12) | (len_encoding << 8) |
17615 (rn.GetCode() << 16));
17616 AdvanceIT();
17617 return;
17618 }
17619 }
17620 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17621 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17622 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17623 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17624 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17625 ((!rn.IsPC()) || AllowUnpredictable())) {
17626 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17627 const DRegister& first = nreglist.GetFirstDRegister();
17628 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17629 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17630 (encoded_align_1.GetEncodingValue() << 4) |
17631 first.Encode(22, 12) | (len_encoding << 8) |
17632 (rn.GetCode() << 16));
17633 AdvanceIT();
17634 return;
17635 }
17636 }
17637 } else {
17638 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
17639 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17640 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17641 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17642 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17643 ((!rn.IsPC()) || AllowUnpredictable())) {
17644 if (cond.Is(al)) {
17645 const DRegister& first = nreglist.GetFirstDRegister();
17646 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17647 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
17648 (encoded_align_1.GetEncodingValue() << 4) |
17649 first.Encode(22, 12) | (len_encoding << 8) |
17650 (rn.GetCode() << 16));
17651 return;
17652 }
17653 }
17654 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
17655 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17656 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17657 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17658 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17659 ((!rn.IsPC()) || AllowUnpredictable())) {
17660 if (cond.Is(al)) {
17661 const DRegister& first = nreglist.GetFirstDRegister();
17662 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17663 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
17664 (encoded_align_1.GetEncodingValue() << 4) |
17665 first.Encode(22, 12) | (len_encoding << 8) |
17666 (rn.GetCode() << 16));
17667 return;
17668 }
17669 }
17670 }
17671 }
17672 if (operand.IsPlainRegister()) {
17673 Register rn = operand.GetBaseRegister();
17674 Alignment align = operand.GetAlignment();
17675 Register rm = operand.GetOffsetRegister();
17676 Dt_size_7 encoded_dt(dt);
17677 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017678 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017679 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
17680 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17681 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17682 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17683 !rm.IsPC() && !rm.IsSP()) {
17684 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17685 const DRegister& first = nreglist.GetFirstDRegister();
17686 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17687 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
17688 (encoded_align_1.GetEncodingValue() << 4) |
17689 first.Encode(22, 12) | (len_encoding << 8) |
17690 (rn.GetCode() << 16) | rm.GetCode());
17691 AdvanceIT();
17692 return;
17693 }
17694 }
17695 } else {
17696 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
17697 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17698 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17699 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17700 !rm.IsPC() && !rm.IsSP()) {
17701 if (cond.Is(al)) {
17702 const DRegister& first = nreglist.GetFirstDRegister();
17703 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
17704 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
17705 (encoded_align_1.GetEncodingValue() << 4) |
17706 first.Encode(22, 12) | (len_encoding << 8) |
17707 (rn.GetCode() << 16) | rm.GetCode());
17708 return;
17709 }
17710 }
17711 }
17712 }
17713 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
17714}
17715
17716void Assembler::vld3(Condition cond,
17717 DataType dt,
17718 const NeonRegisterList& nreglist,
17719 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017721 CheckIT(cond);
17722 if (operand.IsImmediateZero()) {
17723 Register rn = operand.GetBaseRegister();
17724 Dt_size_7 encoded_dt(dt);
17725 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017726 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017727 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
17728 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17729 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17730 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17731 (operand.GetAddrMode() == Offset) &&
17732 ((!rn.IsPC()) || AllowUnpredictable())) {
17733 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17734 const DRegister& first = nreglist.GetFirstDRegister();
17735 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17736 EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
17737 first.Encode(22, 12) | (len_encoding << 5) |
17738 (rn.GetCode() << 16));
17739 AdvanceIT();
17740 return;
17741 }
17742 }
17743 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
17744 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17745 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17746 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17747 (operand.GetAddrMode() == PreIndex) &&
17748 ((!rn.IsPC()) || AllowUnpredictable())) {
17749 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17750 const DRegister& first = nreglist.GetFirstDRegister();
17751 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17752 EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
17753 first.Encode(22, 12) | (len_encoding << 5) |
17754 (rn.GetCode() << 16));
17755 AdvanceIT();
17756 return;
17757 }
17758 }
17759 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
17760 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17761 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17762 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17763 (operand.GetAddrMode() == Offset) &&
17764 ((!rn.IsPC()) || AllowUnpredictable())) {
17765 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17766 const DRegister& first = nreglist.GetFirstDRegister();
17767 EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
17768 (encoded_align_1.GetEncodingValue() << 4) |
17769 first.Encode(22, 12) | (rn.GetCode() << 16));
17770 AdvanceIT();
17771 return;
17772 }
17773 }
17774 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
17775 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17776 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17777 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17778 (operand.GetAddrMode() == PreIndex) &&
17779 ((!rn.IsPC()) || AllowUnpredictable())) {
17780 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17781 const DRegister& first = nreglist.GetFirstDRegister();
17782 EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
17783 (encoded_align_1.GetEncodingValue() << 4) |
17784 first.Encode(22, 12) | (rn.GetCode() << 16));
17785 AdvanceIT();
17786 return;
17787 }
17788 }
17789 } else {
17790 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
17791 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17792 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17793 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17794 (operand.GetAddrMode() == Offset) &&
17795 ((!rn.IsPC()) || AllowUnpredictable())) {
17796 if (cond.Is(al)) {
17797 const DRegister& first = nreglist.GetFirstDRegister();
17798 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17799 EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
17800 first.Encode(22, 12) | (len_encoding << 5) |
17801 (rn.GetCode() << 16));
17802 return;
17803 }
17804 }
17805 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
17806 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17807 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17808 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17809 (operand.GetAddrMode() == PreIndex) &&
17810 ((!rn.IsPC()) || AllowUnpredictable())) {
17811 if (cond.Is(al)) {
17812 const DRegister& first = nreglist.GetFirstDRegister();
17813 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17814 EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
17815 first.Encode(22, 12) | (len_encoding << 5) |
17816 (rn.GetCode() << 16));
17817 return;
17818 }
17819 }
17820 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
17821 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17822 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17823 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17824 (operand.GetAddrMode() == Offset) &&
17825 ((!rn.IsPC()) || AllowUnpredictable())) {
17826 if (cond.Is(al)) {
17827 const DRegister& first = nreglist.GetFirstDRegister();
17828 EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
17829 (encoded_align_1.GetEncodingValue() << 4) |
17830 first.Encode(22, 12) | (rn.GetCode() << 16));
17831 return;
17832 }
17833 }
17834 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
17835 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17836 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17837 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17838 (operand.GetAddrMode() == PreIndex) &&
17839 ((!rn.IsPC()) || AllowUnpredictable())) {
17840 if (cond.Is(al)) {
17841 const DRegister& first = nreglist.GetFirstDRegister();
17842 EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
17843 (encoded_align_1.GetEncodingValue() << 4) |
17844 first.Encode(22, 12) | (rn.GetCode() << 16));
17845 return;
17846 }
17847 }
17848 }
17849 }
17850 if (operand.IsPlainRegister()) {
17851 Register rn = operand.GetBaseRegister();
17852 Sign sign = operand.GetSign();
17853 Register rm = operand.GetOffsetRegister();
17854 Dt_size_7 encoded_dt(dt);
17855 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017856 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017857 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
17858 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17859 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17860 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17861 sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17862 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17863 const DRegister& first = nreglist.GetFirstDRegister();
17864 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17865 EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
17866 first.Encode(22, 12) | (len_encoding << 5) |
17867 (rn.GetCode() << 16) | rm.GetCode());
17868 AdvanceIT();
17869 return;
17870 }
17871 }
17872 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
17873 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17874 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17875 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17876 sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17877 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17878 const DRegister& first = nreglist.GetFirstDRegister();
17879 EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
17880 (encoded_align_1.GetEncodingValue() << 4) |
17881 first.Encode(22, 12) | (rn.GetCode() << 16) |
17882 rm.GetCode());
17883 AdvanceIT();
17884 return;
17885 }
17886 }
17887 } else {
17888 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
17889 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
17890 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17891 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17892 sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17893 if (cond.Is(al)) {
17894 const DRegister& first = nreglist.GetFirstDRegister();
17895 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17896 EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
17897 first.Encode(22, 12) | (len_encoding << 5) |
17898 (rn.GetCode() << 16) | rm.GetCode());
17899 return;
17900 }
17901 }
17902 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
17903 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
17904 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
17905 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
17906 sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
17907 if (cond.Is(al)) {
17908 const DRegister& first = nreglist.GetFirstDRegister();
17909 EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
17910 (encoded_align_1.GetEncodingValue() << 4) |
17911 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
17912 return;
17913 }
17914 }
17915 }
17916 }
17917 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
17918}
17919
17920void Assembler::vld4(Condition cond,
17921 DataType dt,
17922 const NeonRegisterList& nreglist,
17923 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017924 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017925 CheckIT(cond);
17926 if (operand.IsImmediateZero()) {
17927 Register rn = operand.GetBaseRegister();
17928 Alignment align = operand.GetAlignment();
17929 Dt_size_7 encoded_dt(dt);
17930 Dt_size_8 encoded_dt_2(dt, align);
17931 Align_align_4 encoded_align_1(align);
17932 Align_a_3 encoded_align_2(align, dt);
17933 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017934 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017935 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17936 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17937 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17938 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17939 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
17940 ((!rn.IsPC()) || AllowUnpredictable())) {
17941 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17942 const DRegister& first = nreglist.GetFirstDRegister();
17943 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17944 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17945 (encoded_align_1.GetEncodingValue() << 4) |
17946 first.Encode(22, 12) | (len_encoding << 8) |
17947 (rn.GetCode() << 16));
17948 AdvanceIT();
17949 return;
17950 }
17951 }
17952 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17953 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17954 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17955 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17956 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
17957 ((!rn.IsPC()) || AllowUnpredictable())) {
17958 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17959 const DRegister& first = nreglist.GetFirstDRegister();
17960 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17961 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
17962 (encoded_align_1.GetEncodingValue() << 4) |
17963 first.Encode(22, 12) | (len_encoding << 8) |
17964 (rn.GetCode() << 16));
17965 AdvanceIT();
17966 return;
17967 }
17968 }
17969 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17970 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17971 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17972 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17973 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
17974 ((!rn.IsPC()) || AllowUnpredictable())) {
17975 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17976 const DRegister& first = nreglist.GetFirstDRegister();
17977 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17978 EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
17979 (encoded_align_2.GetEncodingValue() << 4) |
17980 first.Encode(22, 12) | (len_encoding << 5) |
17981 (rn.GetCode() << 16));
17982 AdvanceIT();
17983 return;
17984 }
17985 }
17986 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17987 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
17988 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
17989 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
17990 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
17991 ((!rn.IsPC()) || AllowUnpredictable())) {
17992 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17993 const DRegister& first = nreglist.GetFirstDRegister();
17994 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
17995 EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
17996 (encoded_align_2.GetEncodingValue() << 4) |
17997 first.Encode(22, 12) | (len_encoding << 5) |
17998 (rn.GetCode() << 16));
17999 AdvanceIT();
18000 return;
18001 }
18002 }
18003 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18004 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18005 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18006 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18007 (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
18008 ((!rn.IsPC()) || AllowUnpredictable())) {
18009 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18010 const DRegister& first = nreglist.GetFirstDRegister();
18011 EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
18012 (encoded_align_3.GetEncodingValue() << 4) |
18013 first.Encode(22, 12) | (rn.GetCode() << 16));
18014 AdvanceIT();
18015 return;
18016 }
18017 }
18018 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18019 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18020 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18021 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18022 (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
18023 ((!rn.IsPC()) || AllowUnpredictable())) {
18024 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18025 const DRegister& first = nreglist.GetFirstDRegister();
18026 EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
18027 (encoded_align_3.GetEncodingValue() << 4) |
18028 first.Encode(22, 12) | (rn.GetCode() << 16));
18029 AdvanceIT();
18030 return;
18031 }
18032 }
18033 } else {
18034 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18035 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18036 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18037 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18038 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
18039 ((!rn.IsPC()) || AllowUnpredictable())) {
18040 if (cond.Is(al)) {
18041 const DRegister& first = nreglist.GetFirstDRegister();
18042 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18043 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18044 (encoded_align_1.GetEncodingValue() << 4) |
18045 first.Encode(22, 12) | (len_encoding << 8) |
18046 (rn.GetCode() << 16));
18047 return;
18048 }
18049 }
18050 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18051 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18052 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18053 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18054 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
18055 ((!rn.IsPC()) || AllowUnpredictable())) {
18056 if (cond.Is(al)) {
18057 const DRegister& first = nreglist.GetFirstDRegister();
18058 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18059 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18060 (encoded_align_1.GetEncodingValue() << 4) |
18061 first.Encode(22, 12) | (len_encoding << 8) |
18062 (rn.GetCode() << 16));
18063 return;
18064 }
18065 }
18066 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18067 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18068 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18069 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18070 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
18071 ((!rn.IsPC()) || AllowUnpredictable())) {
18072 if (cond.Is(al)) {
18073 const DRegister& first = nreglist.GetFirstDRegister();
18074 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18075 EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18076 (encoded_align_2.GetEncodingValue() << 4) |
18077 first.Encode(22, 12) | (len_encoding << 5) |
18078 (rn.GetCode() << 16));
18079 return;
18080 }
18081 }
18082 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18083 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18084 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18085 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18086 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
18087 ((!rn.IsPC()) || AllowUnpredictable())) {
18088 if (cond.Is(al)) {
18089 const DRegister& first = nreglist.GetFirstDRegister();
18090 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18091 EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18092 (encoded_align_2.GetEncodingValue() << 4) |
18093 first.Encode(22, 12) | (len_encoding << 5) |
18094 (rn.GetCode() << 16));
18095 return;
18096 }
18097 }
18098 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18099 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18100 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18101 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18102 (operand.GetAddrMode() == Offset) && encoded_align_3.IsValid() &&
18103 ((!rn.IsPC()) || AllowUnpredictable())) {
18104 if (cond.Is(al)) {
18105 const DRegister& first = nreglist.GetFirstDRegister();
18106 EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
18107 (encoded_align_3.GetEncodingValue() << 4) |
18108 first.Encode(22, 12) | (rn.GetCode() << 16));
18109 return;
18110 }
18111 }
18112 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18113 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18114 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18115 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18116 (operand.GetAddrMode() == PostIndex) && encoded_align_3.IsValid() &&
18117 ((!rn.IsPC()) || AllowUnpredictable())) {
18118 if (cond.Is(al)) {
18119 const DRegister& first = nreglist.GetFirstDRegister();
18120 EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
18121 (encoded_align_3.GetEncodingValue() << 4) |
18122 first.Encode(22, 12) | (rn.GetCode() << 16));
18123 return;
18124 }
18125 }
18126 }
18127 }
18128 if (operand.IsPlainRegister()) {
18129 Register rn = operand.GetBaseRegister();
18130 Alignment align = operand.GetAlignment();
18131 Register rm = operand.GetOffsetRegister();
18132 Dt_size_7 encoded_dt(dt);
18133 Dt_size_8 encoded_dt_2(dt, align);
18134 Align_align_4 encoded_align_1(align);
18135 Align_a_3 encoded_align_2(align, dt);
18136 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018137 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018138 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18139 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18140 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18141 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18142 !rm.IsPC() && !rm.IsSP()) {
18143 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18144 const DRegister& first = nreglist.GetFirstDRegister();
18145 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18146 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18147 (encoded_align_1.GetEncodingValue() << 4) |
18148 first.Encode(22, 12) | (len_encoding << 8) |
18149 (rn.GetCode() << 16) | rm.GetCode());
18150 AdvanceIT();
18151 return;
18152 }
18153 }
18154 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18155 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18156 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18157 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18158 !rm.IsPC() && !rm.IsSP()) {
18159 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18160 const DRegister& first = nreglist.GetFirstDRegister();
18161 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18162 EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
18163 (encoded_align_2.GetEncodingValue() << 4) |
18164 first.Encode(22, 12) | (len_encoding << 5) |
18165 (rn.GetCode() << 16) | rm.GetCode());
18166 AdvanceIT();
18167 return;
18168 }
18169 }
18170 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18171 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18172 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18173 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18174 !rm.IsPC() && !rm.IsSP()) {
18175 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18176 const DRegister& first = nreglist.GetFirstDRegister();
18177 EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
18178 (encoded_align_3.GetEncodingValue() << 4) |
18179 first.Encode(22, 12) | (rn.GetCode() << 16) |
18180 rm.GetCode());
18181 AdvanceIT();
18182 return;
18183 }
18184 }
18185 } else {
18186 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18187 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18188 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18189 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18190 !rm.IsPC() && !rm.IsSP()) {
18191 if (cond.Is(al)) {
18192 const DRegister& first = nreglist.GetFirstDRegister();
18193 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18194 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18195 (encoded_align_1.GetEncodingValue() << 4) |
18196 first.Encode(22, 12) | (len_encoding << 8) |
18197 (rn.GetCode() << 16) | rm.GetCode());
18198 return;
18199 }
18200 }
18201 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18202 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18203 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18204 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18205 !rm.IsPC() && !rm.IsSP()) {
18206 if (cond.Is(al)) {
18207 const DRegister& first = nreglist.GetFirstDRegister();
18208 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18209 EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
18210 (encoded_align_2.GetEncodingValue() << 4) |
18211 first.Encode(22, 12) | (len_encoding << 5) |
18212 (rn.GetCode() << 16) | rm.GetCode());
18213 return;
18214 }
18215 }
18216 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18217 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18218 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
18219 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
18220 !rm.IsPC() && !rm.IsSP()) {
18221 if (cond.Is(al)) {
18222 const DRegister& first = nreglist.GetFirstDRegister();
18223 EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
18224 (encoded_align_3.GetEncodingValue() << 4) |
18225 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18226 return;
18227 }
18228 }
18229 }
18230 }
18231 Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
18232}
18233
18234void Assembler::vldm(Condition cond,
18235 DataType dt,
18236 Register rn,
18237 WriteBack write_back,
18238 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018239 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018240 CheckIT(cond);
18241 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018242 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018243 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
18244 if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18245 const DRegister& dreg = dreglist.GetFirstDRegister();
18246 unsigned len = dreglist.GetLength() * 2;
18247 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
18248 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18249 (len & 0xff));
18250 AdvanceIT();
18251 return;
18252 }
18253 } else {
18254 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
18255 if (cond.IsNotNever() &&
18256 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18257 const DRegister& dreg = dreglist.GetFirstDRegister();
18258 unsigned len = dreglist.GetLength() * 2;
18259 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18260 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18261 (len & 0xff));
18262 return;
18263 }
18264 }
18265 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
18266}
18267
18268void Assembler::vldm(Condition cond,
18269 DataType dt,
18270 Register rn,
18271 WriteBack write_back,
18272 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018273 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018274 CheckIT(cond);
18275 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018276 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018277 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
18278 const SRegister& sreg = sreglist.GetFirstSRegister();
18279 unsigned len = sreglist.GetLength();
18280 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
18281 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18282 (len & 0xff));
18283 AdvanceIT();
18284 return;
18285 } else {
18286 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
18287 if (cond.IsNotNever()) {
18288 const SRegister& sreg = sreglist.GetFirstSRegister();
18289 unsigned len = sreglist.GetLength();
18290 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18291 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18292 (len & 0xff));
18293 return;
18294 }
18295 }
18296 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
18297}
18298
18299void Assembler::vldmdb(Condition cond,
18300 DataType dt,
18301 Register rn,
18302 WriteBack write_back,
18303 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018304 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018305 CheckIT(cond);
18306 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018307 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018308 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
18309 if (write_back.DoesWriteBack() &&
18310 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18311 const DRegister& dreg = dreglist.GetFirstDRegister();
18312 unsigned len = dreglist.GetLength() * 2;
18313 EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
18314 (len & 0xff));
18315 AdvanceIT();
18316 return;
18317 }
18318 } else {
18319 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
18320 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
18321 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18322 const DRegister& dreg = dreglist.GetFirstDRegister();
18323 unsigned len = dreglist.GetLength() * 2;
18324 EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18325 dreg.Encode(22, 12) | (len & 0xff));
18326 return;
18327 }
18328 }
18329 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
18330}
18331
18332void Assembler::vldmdb(Condition cond,
18333 DataType dt,
18334 Register rn,
18335 WriteBack write_back,
18336 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018337 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018338 CheckIT(cond);
18339 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018340 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018341 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
18342 if (write_back.DoesWriteBack()) {
18343 const SRegister& sreg = sreglist.GetFirstSRegister();
18344 unsigned len = sreglist.GetLength();
18345 EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
18346 (len & 0xff));
18347 AdvanceIT();
18348 return;
18349 }
18350 } else {
18351 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
18352 if (write_back.DoesWriteBack() && cond.IsNotNever()) {
18353 const SRegister& sreg = sreglist.GetFirstSRegister();
18354 unsigned len = sreglist.GetLength();
18355 EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18356 sreg.Encode(22, 12) | (len & 0xff));
18357 return;
18358 }
18359 }
18360 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
18361}
18362
18363void Assembler::vldmia(Condition cond,
18364 DataType dt,
18365 Register rn,
18366 WriteBack write_back,
18367 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018369 CheckIT(cond);
18370 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018371 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018372 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
18373 if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18374 const DRegister& dreg = dreglist.GetFirstDRegister();
18375 unsigned len = dreglist.GetLength() * 2;
18376 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
18377 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18378 (len & 0xff));
18379 AdvanceIT();
18380 return;
18381 }
18382 } else {
18383 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
18384 if (cond.IsNotNever() &&
18385 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
18386 const DRegister& dreg = dreglist.GetFirstDRegister();
18387 unsigned len = dreglist.GetLength() * 2;
18388 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18389 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
18390 (len & 0xff));
18391 return;
18392 }
18393 }
18394 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
18395}
18396
18397void Assembler::vldmia(Condition cond,
18398 DataType dt,
18399 Register rn,
18400 WriteBack write_back,
18401 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018402 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018403 CheckIT(cond);
18404 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018405 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018406 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
18407 const SRegister& sreg = sreglist.GetFirstSRegister();
18408 unsigned len = sreglist.GetLength();
18409 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
18410 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18411 (len & 0xff));
18412 AdvanceIT();
18413 return;
18414 } else {
18415 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
18416 if (cond.IsNotNever()) {
18417 const SRegister& sreg = sreglist.GetFirstSRegister();
18418 unsigned len = sreglist.GetLength();
18419 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
18420 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
18421 (len & 0xff));
18422 return;
18423 }
18424 }
18425 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
18426}
18427
18428void Assembler::vldr(Condition cond, DataType dt, DRegister rd, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018429 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018430 CheckIT(cond);
18431 Label::Offset offset =
18432 label->IsBound()
18433 ? label->GetLocation() -
18434 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
18435 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018436 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018437 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
18438 if (dt.IsNoneOr(Untyped64) &&
18439 ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18440 ((offset & 0x3) == 0)) ||
18441 !label->IsBound())) {
18442 static class EmitOp : public Label::LabelEmitOperator {
18443 public:
18444 EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000018445 virtual uint32_t Encode(uint32_t instr,
18446 Label::Offset pc,
18447 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018448 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18449 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18450 ((offset & 0x3) == 0));
18451 int32_t target = offset >> 2;
18452 uint32_t U = (target >= 0) && !label->IsMinusZero();
18453 target = abs(target) | (U << 8);
18454 return instr | (target & 0xff) | ((target & 0x100) << 15);
18455 }
18456 } immop;
18457 EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12), label, immop));
18458 AdvanceIT();
18459 return;
18460 }
18461 } else {
18462 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
18463 if (dt.IsNoneOr(Untyped64) &&
18464 ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18465 ((offset & 0x3) == 0)) ||
18466 !label->IsBound()) &&
18467 cond.IsNotNever()) {
18468 static class EmitOp : public Label::LabelEmitOperator {
18469 public:
18470 EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000018471 virtual uint32_t Encode(uint32_t instr,
18472 Label::Offset pc,
18473 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018474 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18475 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18476 ((offset & 0x3) == 0));
18477 int32_t target = offset >> 2;
18478 uint32_t U = (target >= 0) && !label->IsMinusZero();
18479 target = abs(target) | (U << 8);
18480 return instr | (target & 0xff) | ((target & 0x100) << 15);
18481 }
18482 } immop;
18483 EmitA32(
18484 Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
18485 label,
18486 immop));
18487 return;
18488 }
18489 }
18490 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, label);
18491}
18492
18493void Assembler::vldr(Condition cond,
18494 DataType dt,
18495 DRegister rd,
18496 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018497 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018498 CheckIT(cond);
18499 if (operand.IsImmediate()) {
18500 Register rn = operand.GetBaseRegister();
18501 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018502 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018503 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
18504 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18505 ((offset % 4) == 0) && rn.Is(pc) &&
18506 (operand.GetAddrMode() == Offset)) {
18507 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18508 uint32_t offset_ = abs(offset) >> 2;
18509 EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
18510 AdvanceIT();
18511 return;
18512 }
18513 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
18514 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18515 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18516 ((rn.GetCode() & 0xf) != 0xf)) {
18517 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18518 uint32_t offset_ = abs(offset) >> 2;
18519 EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
18520 offset_ | (sign << 23));
18521 AdvanceIT();
18522 return;
18523 }
18524 } else {
18525 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
18526 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18527 ((offset % 4) == 0) && rn.Is(pc) &&
18528 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
18529 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18530 uint32_t offset_ = abs(offset) >> 2;
18531 EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18532 offset_ | (sign << 23));
18533 return;
18534 }
18535 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
18536 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
18537 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18538 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
18539 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18540 uint32_t offset_ = abs(offset) >> 2;
18541 EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18542 (rn.GetCode() << 16) | offset_ | (sign << 23));
18543 return;
18544 }
18545 }
18546 }
18547 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
18548}
18549
18550void Assembler::vldr(Condition cond, DataType dt, SRegister rd, Label* label) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018551 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018552 CheckIT(cond);
18553 Label::Offset offset =
18554 label->IsBound()
18555 ? label->GetLocation() -
18556 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
18557 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018558 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018559 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
18560 if (dt.IsNoneOr(Untyped32) &&
18561 ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18562 ((offset & 0x3) == 0)) ||
18563 !label->IsBound())) {
18564 static class EmitOp : public Label::LabelEmitOperator {
18565 public:
18566 EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000018567 virtual uint32_t Encode(uint32_t instr,
18568 Label::Offset pc,
18569 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018570 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18571 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18572 ((offset & 0x3) == 0));
18573 int32_t target = offset >> 2;
18574 uint32_t U = (target >= 0) && !label->IsMinusZero();
18575 target = abs(target) | (U << 8);
18576 return instr | (target & 0xff) | ((target & 0x100) << 15);
18577 }
18578 } immop;
18579 EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12), label, immop));
18580 AdvanceIT();
18581 return;
18582 }
18583 } else {
18584 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
18585 if (dt.IsNoneOr(Untyped32) &&
18586 ((label->IsBound() && (offset >= -1020) && (offset <= 1020) &&
18587 ((offset & 0x3) == 0)) ||
18588 !label->IsBound()) &&
18589 cond.IsNotNever()) {
18590 static class EmitOp : public Label::LabelEmitOperator {
18591 public:
18592 EmitOp() : Label::LabelEmitOperator(-1020, 1020) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000018593 virtual uint32_t Encode(uint32_t instr,
18594 Label::Offset pc,
18595 const Label* label) const VIXL_OVERRIDE {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018596 Label::Offset offset = label->GetLocation() - AlignDown(pc, 4);
18597 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
18598 ((offset & 0x3) == 0));
18599 int32_t target = offset >> 2;
18600 uint32_t U = (target >= 0) && !label->IsMinusZero();
18601 target = abs(target) | (U << 8);
18602 return instr | (target & 0xff) | ((target & 0x100) << 15);
18603 }
18604 } immop;
18605 EmitA32(
18606 Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
18607 label,
18608 immop));
18609 return;
18610 }
18611 }
18612 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, label);
18613}
18614
18615void Assembler::vldr(Condition cond,
18616 DataType dt,
18617 SRegister rd,
18618 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018619 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018620 CheckIT(cond);
18621 if (operand.IsImmediate()) {
18622 Register rn = operand.GetBaseRegister();
18623 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018624 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018625 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
18626 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18627 ((offset % 4) == 0) && rn.Is(pc) &&
18628 (operand.GetAddrMode() == Offset)) {
18629 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18630 uint32_t offset_ = abs(offset) >> 2;
18631 EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
18632 AdvanceIT();
18633 return;
18634 }
18635 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
18636 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18637 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18638 ((rn.GetCode() & 0xf) != 0xf)) {
18639 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18640 uint32_t offset_ = abs(offset) >> 2;
18641 EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
18642 offset_ | (sign << 23));
18643 AdvanceIT();
18644 return;
18645 }
18646 } else {
18647 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
18648 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18649 ((offset % 4) == 0) && rn.Is(pc) &&
18650 (operand.GetAddrMode() == Offset) && cond.IsNotNever()) {
18651 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18652 uint32_t offset_ = abs(offset) >> 2;
18653 EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18654 offset_ | (sign << 23));
18655 return;
18656 }
18657 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
18658 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
18659 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
18660 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
18661 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
18662 uint32_t offset_ = abs(offset) >> 2;
18663 EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
18664 (rn.GetCode() << 16) | offset_ | (sign << 23));
18665 return;
18666 }
18667 }
18668 }
18669 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
18670}
18671
18672void Assembler::vmax(
18673 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018674 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018675 CheckIT(cond);
18676 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018677 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018678 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
18679 if (dt.Is(F32)) {
18680 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18681 EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18682 rm.Encode(5, 0));
18683 AdvanceIT();
18684 return;
18685 }
18686 }
18687 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
18688 if (encoded_dt.IsValid()) {
18689 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18690 EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18691 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18692 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18693 AdvanceIT();
18694 return;
18695 }
18696 }
18697 } else {
18698 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
18699 if (dt.Is(F32)) {
18700 if (cond.Is(al)) {
18701 EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18702 rm.Encode(5, 0));
18703 return;
18704 }
18705 }
18706 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
18707 if (encoded_dt.IsValid()) {
18708 if (cond.Is(al)) {
18709 EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18710 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18711 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18712 return;
18713 }
18714 }
18715 }
18716 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
18717}
18718
18719void Assembler::vmax(
18720 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018721 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018722 CheckIT(cond);
18723 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018724 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018725 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
18726 if (dt.Is(F32)) {
18727 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18728 EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18729 rm.Encode(5, 0));
18730 AdvanceIT();
18731 return;
18732 }
18733 }
18734 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
18735 if (encoded_dt.IsValid()) {
18736 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18737 EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18738 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18739 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18740 AdvanceIT();
18741 return;
18742 }
18743 }
18744 } else {
18745 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
18746 if (dt.Is(F32)) {
18747 if (cond.Is(al)) {
18748 EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18749 rm.Encode(5, 0));
18750 return;
18751 }
18752 }
18753 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
18754 if (encoded_dt.IsValid()) {
18755 if (cond.Is(al)) {
18756 EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18757 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18758 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18759 return;
18760 }
18761 }
18762 }
18763 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
18764}
18765
18766void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018767 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018768 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018769 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018770 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
18771 if (OutsideITBlock() && dt.Is(F32)) {
18772 EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18773 rm.Encode(5, 0));
18774 AdvanceIT();
18775 return;
18776 }
18777 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
18778 if (OutsideITBlock() && dt.Is(F64)) {
18779 EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18780 rm.Encode(5, 0));
18781 AdvanceIT();
18782 return;
18783 }
18784 } else {
18785 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
18786 if (dt.Is(F32)) {
18787 EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18788 rm.Encode(5, 0));
18789 return;
18790 }
18791 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
18792 if (dt.Is(F64)) {
18793 EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18794 rm.Encode(5, 0));
18795 return;
18796 }
18797 }
18798 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18799}
18800
18801void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018802 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018803 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018804 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018805 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
18806 if (OutsideITBlock() && dt.Is(F32)) {
18807 EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18808 rm.Encode(5, 0));
18809 AdvanceIT();
18810 return;
18811 }
18812 } else {
18813 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
18814 if (dt.Is(F32)) {
18815 EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18816 rm.Encode(5, 0));
18817 return;
18818 }
18819 }
18820 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18821}
18822
18823void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018824 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018825 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018826 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018827 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
18828 if (OutsideITBlock() && dt.Is(F32)) {
18829 EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18830 rm.Encode(5, 0));
18831 AdvanceIT();
18832 return;
18833 }
18834 } else {
18835 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
18836 if (dt.Is(F32)) {
18837 EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18838 rm.Encode(5, 0));
18839 return;
18840 }
18841 }
18842 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
18843}
18844
18845void Assembler::vmin(
18846 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018847 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018848 CheckIT(cond);
18849 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018850 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018851 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
18852 if (dt.Is(F32)) {
18853 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18854 EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18855 rm.Encode(5, 0));
18856 AdvanceIT();
18857 return;
18858 }
18859 }
18860 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
18861 if (encoded_dt.IsValid()) {
18862 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18863 EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18864 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18865 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18866 AdvanceIT();
18867 return;
18868 }
18869 }
18870 } else {
18871 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
18872 if (dt.Is(F32)) {
18873 if (cond.Is(al)) {
18874 EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18875 rm.Encode(5, 0));
18876 return;
18877 }
18878 }
18879 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
18880 if (encoded_dt.IsValid()) {
18881 if (cond.Is(al)) {
18882 EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18883 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18884 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18885 return;
18886 }
18887 }
18888 }
18889 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
18890}
18891
18892void Assembler::vmin(
18893 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018894 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018895 CheckIT(cond);
18896 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018897 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018898 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
18899 if (dt.Is(F32)) {
18900 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18901 EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18902 rm.Encode(5, 0));
18903 AdvanceIT();
18904 return;
18905 }
18906 }
18907 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
18908 if (encoded_dt.IsValid()) {
18909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18910 EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18911 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
18912 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18913 AdvanceIT();
18914 return;
18915 }
18916 }
18917 } else {
18918 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
18919 if (dt.Is(F32)) {
18920 if (cond.Is(al)) {
18921 EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18922 rm.Encode(5, 0));
18923 return;
18924 }
18925 }
18926 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
18927 if (encoded_dt.IsValid()) {
18928 if (cond.Is(al)) {
18929 EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
18930 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
18931 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
18932 return;
18933 }
18934 }
18935 }
18936 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
18937}
18938
18939void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018940 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018941 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018942 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018943 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
18944 if (OutsideITBlock() && dt.Is(F32)) {
18945 EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18946 rm.Encode(5, 0));
18947 AdvanceIT();
18948 return;
18949 }
18950 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
18951 if (OutsideITBlock() && dt.Is(F64)) {
18952 EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18953 rm.Encode(5, 0));
18954 AdvanceIT();
18955 return;
18956 }
18957 } else {
18958 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
18959 if (dt.Is(F32)) {
18960 EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18961 rm.Encode(5, 0));
18962 return;
18963 }
18964 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
18965 if (dt.Is(F64)) {
18966 EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18967 rm.Encode(5, 0));
18968 return;
18969 }
18970 }
18971 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18972}
18973
18974void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018975 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018976 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018977 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018978 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
18979 if (OutsideITBlock() && dt.Is(F32)) {
18980 EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18981 rm.Encode(5, 0));
18982 AdvanceIT();
18983 return;
18984 }
18985 } else {
18986 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
18987 if (dt.Is(F32)) {
18988 EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
18989 rm.Encode(5, 0));
18990 return;
18991 }
18992 }
18993 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
18994}
18995
18996void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018997 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018998 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018999 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019000 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19001 if (OutsideITBlock() && dt.Is(F32)) {
19002 EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19003 rm.Encode(5, 0));
19004 AdvanceIT();
19005 return;
19006 }
19007 } else {
19008 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19009 if (dt.Is(F32)) {
19010 EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19011 rm.Encode(5, 0));
19012 return;
19013 }
19014 }
19015 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
19016}
19017
19018void Assembler::vmla(
19019 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019020 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019021 CheckIT(cond);
19022 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019023 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019024 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
19025 if (encoded_dt.IsValid() &&
19026 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19027 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19028 (rm.GetLane() <= 1)))) {
19029 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19030 EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19031 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19032 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19033 AdvanceIT();
19034 return;
19035 }
19036 }
19037 } else {
19038 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
19039 if (encoded_dt.IsValid() &&
19040 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19041 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19042 (rm.GetLane() <= 1)))) {
19043 if (cond.Is(al)) {
19044 EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19045 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19046 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19047 return;
19048 }
19049 }
19050 }
19051 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19052}
19053
19054void Assembler::vmla(
19055 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019056 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019057 CheckIT(cond);
19058 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019059 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019060 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
19061 if (encoded_dt.IsValid() &&
19062 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19063 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19064 (rm.GetLane() <= 1)))) {
19065 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19066 EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19067 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19068 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19069 AdvanceIT();
19070 return;
19071 }
19072 }
19073 } else {
19074 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
19075 if (encoded_dt.IsValid() &&
19076 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19077 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19078 (rm.GetLane() <= 1)))) {
19079 if (cond.Is(al)) {
19080 EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
19081 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19082 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19083 return;
19084 }
19085 }
19086 }
19087 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19088}
19089
19090void Assembler::vmla(
19091 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019092 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019093 CheckIT(cond);
19094 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019095 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019096 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19097 if (dt.Is(F32)) {
19098 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19099 EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19100 rm.Encode(5, 0));
19101 AdvanceIT();
19102 return;
19103 }
19104 }
19105 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19106 if (dt.Is(F64)) {
19107 EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19108 rm.Encode(5, 0));
19109 AdvanceIT();
19110 return;
19111 }
19112 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
19113 if (encoded_dt.IsValid()) {
19114 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19115 EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
19116 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19117 AdvanceIT();
19118 return;
19119 }
19120 }
19121 } else {
19122 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19123 if (dt.Is(F32)) {
19124 if (cond.Is(al)) {
19125 EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19126 rm.Encode(5, 0));
19127 return;
19128 }
19129 }
19130 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19131 if (dt.Is(F64) && cond.IsNotNever()) {
19132 EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19133 rn.Encode(7, 16) | rm.Encode(5, 0));
19134 return;
19135 }
19136 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
19137 if (encoded_dt.IsValid()) {
19138 if (cond.Is(al)) {
19139 EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
19140 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19141 return;
19142 }
19143 }
19144 }
19145 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19146}
19147
19148void Assembler::vmla(
19149 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019150 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019151 CheckIT(cond);
19152 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019153 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019154 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19155 if (dt.Is(F32)) {
19156 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19157 EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19158 rm.Encode(5, 0));
19159 AdvanceIT();
19160 return;
19161 }
19162 }
19163 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
19164 if (encoded_dt.IsValid()) {
19165 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19166 EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
19167 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19168 AdvanceIT();
19169 return;
19170 }
19171 }
19172 } else {
19173 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19174 if (dt.Is(F32)) {
19175 if (cond.Is(al)) {
19176 EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19177 rm.Encode(5, 0));
19178 return;
19179 }
19180 }
19181 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
19182 if (encoded_dt.IsValid()) {
19183 if (cond.Is(al)) {
19184 EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
19185 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19186 return;
19187 }
19188 }
19189 }
19190 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19191}
19192
19193void Assembler::vmla(
19194 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019195 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019196 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019197 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019198 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19199 if (dt.Is(F32)) {
19200 EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19201 rm.Encode(5, 0));
19202 AdvanceIT();
19203 return;
19204 }
19205 } else {
19206 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19207 if (dt.Is(F32) && cond.IsNotNever()) {
19208 EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19209 rn.Encode(7, 16) | rm.Encode(5, 0));
19210 return;
19211 }
19212 }
19213 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
19214}
19215
19216void Assembler::vmlal(
19217 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019218 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019219 CheckIT(cond);
19220 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019221 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019222 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
19223 if (encoded_dt.IsValid() &&
19224 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19225 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19226 (rm.GetLane() <= 1)))) {
19227 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19228 EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
19229 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19230 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19231 AdvanceIT();
19232 return;
19233 }
19234 }
19235 } else {
19236 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
19237 if (encoded_dt.IsValid() &&
19238 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19239 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19240 (rm.GetLane() <= 1)))) {
19241 if (cond.Is(al)) {
19242 EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
19243 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19244 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19245 return;
19246 }
19247 }
19248 }
19249 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
19250}
19251
19252void Assembler::vmlal(
19253 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019254 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019255 CheckIT(cond);
19256 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019257 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019258 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
19259 if (encoded_dt.IsValid()) {
19260 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19261 EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
19262 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19263 rn.Encode(7, 16) | rm.Encode(5, 0));
19264 AdvanceIT();
19265 return;
19266 }
19267 }
19268 } else {
19269 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
19270 if (encoded_dt.IsValid()) {
19271 if (cond.Is(al)) {
19272 EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
19273 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19274 rn.Encode(7, 16) | rm.Encode(5, 0));
19275 return;
19276 }
19277 }
19278 }
19279 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
19280}
19281
19282void Assembler::vmls(
19283 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019284 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019285 CheckIT(cond);
19286 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019287 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019288 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
19289 if (encoded_dt.IsValid() &&
19290 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19291 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19292 (rm.GetLane() <= 1)))) {
19293 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19294 EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19295 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19296 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19297 AdvanceIT();
19298 return;
19299 }
19300 }
19301 } else {
19302 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
19303 if (encoded_dt.IsValid() &&
19304 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19305 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19306 (rm.GetLane() <= 1)))) {
19307 if (cond.Is(al)) {
19308 EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19309 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19310 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19311 return;
19312 }
19313 }
19314 }
19315 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19316}
19317
19318void Assembler::vmls(
19319 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019320 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019321 CheckIT(cond);
19322 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019323 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019324 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
19325 if (encoded_dt.IsValid() &&
19326 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19327 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19328 (rm.GetLane() <= 1)))) {
19329 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19330 EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19331 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19332 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19333 AdvanceIT();
19334 return;
19335 }
19336 }
19337 } else {
19338 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
19339 if (encoded_dt.IsValid() &&
19340 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19341 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19342 (rm.GetLane() <= 1)))) {
19343 if (cond.Is(al)) {
19344 EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
19345 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19346 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19347 return;
19348 }
19349 }
19350 }
19351 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19352}
19353
19354void Assembler::vmls(
19355 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019356 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019357 CheckIT(cond);
19358 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019359 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019360 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19361 if (dt.Is(F32)) {
19362 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19363 EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19364 rm.Encode(5, 0));
19365 AdvanceIT();
19366 return;
19367 }
19368 }
19369 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19370 if (dt.Is(F64)) {
19371 EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19372 rm.Encode(5, 0));
19373 AdvanceIT();
19374 return;
19375 }
19376 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
19377 if (encoded_dt.IsValid()) {
19378 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19379 EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
19380 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19381 AdvanceIT();
19382 return;
19383 }
19384 }
19385 } else {
19386 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19387 if (dt.Is(F32)) {
19388 if (cond.Is(al)) {
19389 EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19390 rm.Encode(5, 0));
19391 return;
19392 }
19393 }
19394 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19395 if (dt.Is(F64) && cond.IsNotNever()) {
19396 EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19397 rn.Encode(7, 16) | rm.Encode(5, 0));
19398 return;
19399 }
19400 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
19401 if (encoded_dt.IsValid()) {
19402 if (cond.Is(al)) {
19403 EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
19404 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19405 return;
19406 }
19407 }
19408 }
19409 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19410}
19411
19412void Assembler::vmls(
19413 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019414 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019415 CheckIT(cond);
19416 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019417 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019418 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19419 if (dt.Is(F32)) {
19420 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19421 EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19422 rm.Encode(5, 0));
19423 AdvanceIT();
19424 return;
19425 }
19426 }
19427 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
19428 if (encoded_dt.IsValid()) {
19429 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19430 EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
19431 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19432 AdvanceIT();
19433 return;
19434 }
19435 }
19436 } else {
19437 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19438 if (dt.Is(F32)) {
19439 if (cond.Is(al)) {
19440 EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19441 rm.Encode(5, 0));
19442 return;
19443 }
19444 }
19445 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
19446 if (encoded_dt.IsValid()) {
19447 if (cond.Is(al)) {
19448 EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
19449 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19450 return;
19451 }
19452 }
19453 }
19454 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19455}
19456
19457void Assembler::vmls(
19458 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019459 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019460 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019461 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019462 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
19463 if (dt.Is(F32)) {
19464 EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19465 rm.Encode(5, 0));
19466 AdvanceIT();
19467 return;
19468 }
19469 } else {
19470 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
19471 if (dt.Is(F32) && cond.IsNotNever()) {
19472 EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19473 rn.Encode(7, 16) | rm.Encode(5, 0));
19474 return;
19475 }
19476 }
19477 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
19478}
19479
19480void Assembler::vmlsl(
19481 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019482 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019483 CheckIT(cond);
19484 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019485 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019486 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
19487 if (encoded_dt.IsValid() &&
19488 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19489 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19490 (rm.GetLane() <= 1)))) {
19491 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19492 EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
19493 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19494 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19495 AdvanceIT();
19496 return;
19497 }
19498 }
19499 } else {
19500 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
19501 if (encoded_dt.IsValid() &&
19502 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
19503 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
19504 (rm.GetLane() <= 1)))) {
19505 if (cond.Is(al)) {
19506 EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
19507 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19508 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
19509 return;
19510 }
19511 }
19512 }
19513 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
19514}
19515
19516void Assembler::vmlsl(
19517 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019518 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019519 CheckIT(cond);
19520 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019521 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019522 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
19523 if (encoded_dt.IsValid()) {
19524 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19525 EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
19526 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19527 rn.Encode(7, 16) | rm.Encode(5, 0));
19528 AdvanceIT();
19529 return;
19530 }
19531 }
19532 } else {
19533 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
19534 if (encoded_dt.IsValid()) {
19535 if (cond.Is(al)) {
19536 EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
19537 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
19538 rn.Encode(7, 16) | rm.Encode(5, 0));
19539 return;
19540 }
19541 }
19542 }
19543 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
19544}
19545
19546void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019547 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019548 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019549 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019550 // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
19551 EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
19552 AdvanceIT();
19553 return;
19554 } else {
19555 // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
19556 if (cond.IsNotNever()) {
19557 EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19558 rn.Encode(7, 16));
19559 return;
19560 }
19561 }
19562 Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
19563}
19564
19565void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019566 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019567 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019568 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019569 // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
19570 EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
19571 AdvanceIT();
19572 return;
19573 } else {
19574 // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
19575 if (cond.IsNotNever()) {
19576 EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
19577 (rt.GetCode() << 12));
19578 return;
19579 }
19580 }
19581 Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
19582}
19583
19584void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019585 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019586 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019587 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019588 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
19589 EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
19590 rm.Encode(5, 0));
19591 AdvanceIT();
19592 return;
19593 } else {
19594 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
19595 if (cond.IsNotNever()) {
19596 EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19597 (rt2.GetCode() << 16) | rm.Encode(5, 0));
19598 return;
19599 }
19600 }
19601 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
19602}
19603
19604void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019605 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019606 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019607 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019608 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
19609 EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
19610 (rt2.GetCode() << 16));
19611 AdvanceIT();
19612 return;
19613 } else {
19614 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
19615 if (cond.IsNotNever()) {
19616 EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
19617 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
19618 return;
19619 }
19620 }
19621 Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
19622}
19623
19624void Assembler::vmov(
19625 Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019626 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019627 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019628 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019629 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
19630 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode())) {
19631 EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
19632 rm.Encode(5, 0));
19633 AdvanceIT();
19634 return;
19635 }
19636 } else {
19637 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
19638 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
19639 cond.IsNotNever()) {
19640 EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
19641 (rt2.GetCode() << 16) | rm.Encode(5, 0));
19642 return;
19643 }
19644 }
19645 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
19646}
19647
19648void Assembler::vmov(
19649 Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019650 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019651 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019652 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019653 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
19654 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode())) {
19655 EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
19656 (rt2.GetCode() << 16));
19657 AdvanceIT();
19658 return;
19659 }
19660 } else {
19661 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
19662 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
19663 cond.IsNotNever()) {
19664 EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
19665 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
19666 return;
19667 }
19668 }
19669 Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
19670}
19671
19672void Assembler::vmov(Condition cond,
19673 DataType dt,
19674 DRegisterLane rd,
19675 Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019676 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019677 CheckIT(cond);
19678 Dt_opc1_opc2_1 encoded_dt(dt, rd);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019679 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019680 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
19681 if (encoded_dt.IsValid()) {
19682 EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19683 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19684 rd.Encode(7, 16) | (rt.GetCode() << 12));
19685 AdvanceIT();
19686 return;
19687 }
19688 } else {
19689 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
19690 if (encoded_dt.IsValid() && cond.IsNotNever()) {
19691 EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
19692 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19693 ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
19694 (rt.GetCode() << 12));
19695 return;
19696 }
19697 }
19698 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
19699}
19700
19701void Assembler::vmov(Condition cond,
19702 DataType dt,
19703 DRegister rd,
19704 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019705 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019706 CheckIT(cond);
19707 if (operand.IsImmediate()) {
19708 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
19709 ImmediateVFP vfp(operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019710 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019711 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
19712 if (encoded_dt.IsValid()) {
19713 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19714 EmitT32_32(
19715 0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19716 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19717 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19718 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19719 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
19720 AdvanceIT();
19721 return;
19722 }
19723 }
19724 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
19725 if (dt.Is(F64) && vfp.IsValid()) {
19726 EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
19727 (vfp.GetEncodingValue() & 0xf) |
19728 ((vfp.GetEncodingValue() & 0xf0) << 12));
19729 AdvanceIT();
19730 return;
19731 }
19732 } else {
19733 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
19734 if (encoded_dt.IsValid()) {
19735 if (cond.Is(al)) {
19736 EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19737 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19738 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19739 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19740 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
19741 return;
19742 }
19743 }
19744 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
19745 if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
19746 EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19747 (vfp.GetEncodingValue() & 0xf) |
19748 ((vfp.GetEncodingValue() & 0xf0) << 12));
19749 return;
19750 }
19751 }
19752 }
19753 if (operand.IsRegister()) {
19754 DRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019756 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
19757 if (dt.Is(F64)) {
19758 EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
19759 AdvanceIT();
19760 return;
19761 }
19762 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
19763 if (!dt.Is(F64)) {
19764 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19765 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19766 rm.Encode(5, 0));
19767 AdvanceIT();
19768 return;
19769 }
19770 }
19771 } else {
19772 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
19773 if (dt.Is(F64) && cond.IsNotNever()) {
19774 EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19775 rm.Encode(5, 0));
19776 return;
19777 }
19778 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
19779 if (!dt.Is(F64)) {
19780 if (cond.Is(al)) {
19781 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19782 rm.Encode(5, 0));
19783 return;
19784 }
19785 }
19786 }
19787 }
19788 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19789}
19790
19791void Assembler::vmov(Condition cond,
19792 DataType dt,
19793 QRegister rd,
19794 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019795 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019796 CheckIT(cond);
19797 if (operand.IsImmediate()) {
19798 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019799 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019800 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
19801 if (encoded_dt.IsValid()) {
19802 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19803 EmitT32_32(
19804 0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19805 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19806 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19807 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19808 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
19809 AdvanceIT();
19810 return;
19811 }
19812 }
19813 } else {
19814 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
19815 if (encoded_dt.IsValid()) {
19816 if (cond.Is(al)) {
19817 EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
19818 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
19819 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
19820 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
19821 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
19822 return;
19823 }
19824 }
19825 }
19826 }
19827 if (operand.IsRegister()) {
19828 QRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019829 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019830 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
19831 if (!dt.Is(F64)) {
19832 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19833 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19834 rm.Encode(5, 0));
19835 AdvanceIT();
19836 return;
19837 }
19838 }
19839 } else {
19840 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
19841 if (!dt.Is(F64)) {
19842 if (cond.Is(al)) {
19843 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
19844 rm.Encode(5, 0));
19845 return;
19846 }
19847 }
19848 }
19849 }
19850 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19851}
19852
19853void Assembler::vmov(Condition cond,
19854 DataType dt,
19855 SRegister rd,
19856 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019857 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019858 CheckIT(cond);
19859 if (operand.IsImmediate()) {
19860 ImmediateVFP vfp(operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019861 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019862 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
19863 if (dt.Is(F32) && vfp.IsValid()) {
19864 EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
19865 (vfp.GetEncodingValue() & 0xf) |
19866 ((vfp.GetEncodingValue() & 0xf0) << 12));
19867 AdvanceIT();
19868 return;
19869 }
19870 } else {
19871 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
19872 if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
19873 EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19874 (vfp.GetEncodingValue() & 0xf) |
19875 ((vfp.GetEncodingValue() & 0xf0) << 12));
19876 return;
19877 }
19878 }
19879 }
19880 if (operand.IsRegister()) {
19881 SRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019882 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019883 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
19884 if (dt.Is(F32)) {
19885 EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
19886 AdvanceIT();
19887 return;
19888 }
19889 } else {
19890 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
19891 if (dt.Is(F32) && cond.IsNotNever()) {
19892 EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19893 rm.Encode(5, 0));
19894 return;
19895 }
19896 }
19897 }
19898 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
19899}
19900
19901void Assembler::vmov(Condition cond,
19902 DataType dt,
19903 Register rt,
19904 DRegisterLane rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019905 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019906 CheckIT(cond);
19907 Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019908 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019909 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
19910 if (encoded_dt.IsValid()) {
19911 EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19912 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19913 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
19914 (rt.GetCode() << 12) | rn.Encode(7, 16));
19915 AdvanceIT();
19916 return;
19917 }
19918 } else {
19919 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
19920 if (encoded_dt.IsValid() && cond.IsNotNever()) {
19921 EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
19922 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
19923 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
19924 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
19925 (rt.GetCode() << 12) | rn.Encode(7, 16));
19926 return;
19927 }
19928 }
19929 Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
19930}
19931
19932void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019933 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019934 CheckIT(cond);
19935 Dt_U_imm3H_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019936 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019937 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
19938 if (encoded_dt.IsValid()) {
19939 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19940 EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
19941 ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
19942 rd.Encode(22, 12) | rm.Encode(5, 0));
19943 AdvanceIT();
19944 return;
19945 }
19946 }
19947 } else {
19948 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
19949 if (encoded_dt.IsValid()) {
19950 if (cond.Is(al)) {
19951 EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
19952 ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
19953 rd.Encode(22, 12) | rm.Encode(5, 0));
19954 return;
19955 }
19956 }
19957 }
19958 Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
19959}
19960
19961void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019962 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019963 CheckIT(cond);
19964 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019965 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019966 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
19967 if (encoded_dt.IsValid()) {
19968 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19969 EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
19970 rd.Encode(22, 12) | rm.Encode(5, 0));
19971 AdvanceIT();
19972 return;
19973 }
19974 }
19975 } else {
19976 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
19977 if (encoded_dt.IsValid()) {
19978 if (cond.Is(al)) {
19979 EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
19980 rd.Encode(22, 12) | rm.Encode(5, 0));
19981 return;
19982 }
19983 }
19984 }
19985 Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
19986}
19987
19988void Assembler::vmrs(Condition cond,
19989 RegisterOrAPSR_nzcv rt,
19990 SpecialFPRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019991 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019992 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019993 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019994 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
19995 EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
19996 AdvanceIT();
19997 return;
19998 } else {
19999 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
20000 if (cond.IsNotNever()) {
20001 EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20002 (spec_reg.GetReg() << 16));
20003 return;
20004 }
20005 }
20006 Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
20007}
20008
20009void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020010 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020011 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020012 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020013 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
20014 EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
20015 AdvanceIT();
20016 return;
20017 } else {
20018 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
20019 if (cond.IsNotNever()) {
20020 EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
20021 (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
20022 return;
20023 }
20024 }
20025 Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
20026}
20027
20028void Assembler::vmul(Condition cond,
20029 DataType dt,
20030 DRegister rd,
20031 DRegister rn,
20032 DRegister dm,
20033 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020034 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020035 CheckIT(cond);
20036 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020037 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020038 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
20039 if (encoded_dt.IsValid() &&
20040 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20041 (!dt.Is(I16) && (index <= 1)))) {
20042 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20043 uint32_t shift = 4;
20044 if (dt.Is(I16)) {
20045 shift = 3;
20046 }
20047 uint32_t mvm = dm.GetCode() | index << shift;
20048 EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20049 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20050 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20051 ((mvm & 0x10) << 1));
20052 AdvanceIT();
20053 return;
20054 }
20055 }
20056 } else {
20057 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
20058 if (encoded_dt.IsValid() &&
20059 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20060 (!dt.Is(I16) && (index <= 1)))) {
20061 if (cond.Is(al)) {
20062 uint32_t shift = 4;
20063 if (dt.Is(I16)) {
20064 shift = 3;
20065 }
20066 uint32_t mvm = dm.GetCode() | index << shift;
20067 EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20068 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20069 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20070 ((mvm & 0x10) << 1));
20071 return;
20072 }
20073 }
20074 }
20075 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
20076}
20077
20078void Assembler::vmul(Condition cond,
20079 DataType dt,
20080 QRegister rd,
20081 QRegister rn,
20082 DRegister dm,
20083 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020084 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020085 CheckIT(cond);
20086 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020087 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020088 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
20089 if (encoded_dt.IsValid() &&
20090 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20091 (!dt.Is(I16) && (index <= 1)))) {
20092 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20093 uint32_t shift = 4;
20094 if (dt.Is(I16)) {
20095 shift = 3;
20096 }
20097 uint32_t mvm = dm.GetCode() | index << shift;
20098 EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20099 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20100 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20101 ((mvm & 0x10) << 1));
20102 AdvanceIT();
20103 return;
20104 }
20105 }
20106 } else {
20107 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
20108 if (encoded_dt.IsValid() &&
20109 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
20110 (!dt.Is(I16) && (index <= 1)))) {
20111 if (cond.Is(al)) {
20112 uint32_t shift = 4;
20113 if (dt.Is(I16)) {
20114 shift = 3;
20115 }
20116 uint32_t mvm = dm.GetCode() | index << shift;
20117 EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20118 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
20119 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20120 ((mvm & 0x10) << 1));
20121 return;
20122 }
20123 }
20124 }
20125 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
20126}
20127
20128void Assembler::vmul(
20129 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020130 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020131 CheckIT(cond);
20132 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020133 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020134 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20135 if (dt.Is(F32)) {
20136 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20137 EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20138 rm.Encode(5, 0));
20139 AdvanceIT();
20140 return;
20141 }
20142 }
20143 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
20144 if (dt.Is(F64)) {
20145 EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20146 rm.Encode(5, 0));
20147 AdvanceIT();
20148 return;
20149 }
20150 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20151 if (encoded_dt.IsValid()) {
20152 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20153 EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20154 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20155 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20156 AdvanceIT();
20157 return;
20158 }
20159 }
20160 } else {
20161 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20162 if (dt.Is(F32)) {
20163 if (cond.Is(al)) {
20164 EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20165 rm.Encode(5, 0));
20166 return;
20167 }
20168 }
20169 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
20170 if (dt.Is(F64) && cond.IsNotNever()) {
20171 EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20172 rn.Encode(7, 16) | rm.Encode(5, 0));
20173 return;
20174 }
20175 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20176 if (encoded_dt.IsValid()) {
20177 if (cond.Is(al)) {
20178 EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20179 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20180 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20181 return;
20182 }
20183 }
20184 }
20185 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20186}
20187
20188void Assembler::vmul(
20189 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020190 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020191 CheckIT(cond);
20192 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020193 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020194 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20195 if (dt.Is(F32)) {
20196 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20197 EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20198 rm.Encode(5, 0));
20199 AdvanceIT();
20200 return;
20201 }
20202 }
20203 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20204 if (encoded_dt.IsValid()) {
20205 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20206 EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20207 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20208 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20209 AdvanceIT();
20210 return;
20211 }
20212 }
20213 } else {
20214 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20215 if (dt.Is(F32)) {
20216 if (cond.Is(al)) {
20217 EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20218 rm.Encode(5, 0));
20219 return;
20220 }
20221 }
20222 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20223 if (encoded_dt.IsValid()) {
20224 if (cond.Is(al)) {
20225 EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20226 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20227 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20228 return;
20229 }
20230 }
20231 }
20232 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20233}
20234
20235void Assembler::vmul(
20236 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020237 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020238 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020239 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020240 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
20241 if (dt.Is(F32)) {
20242 EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20243 rm.Encode(5, 0));
20244 AdvanceIT();
20245 return;
20246 }
20247 } else {
20248 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
20249 if (dt.Is(F32) && cond.IsNotNever()) {
20250 EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20251 rn.Encode(7, 16) | rm.Encode(5, 0));
20252 return;
20253 }
20254 }
20255 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
20256}
20257
20258void Assembler::vmull(Condition cond,
20259 DataType dt,
20260 QRegister rd,
20261 DRegister rn,
20262 DRegister dm,
20263 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020264 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020265 CheckIT(cond);
20266 Dt_U_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020267 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020268 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
20269 if (encoded_dt.IsValid() &&
20270 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
20271 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
20272 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20273 uint32_t shift = 4;
20274 if (dt.Is(S16) || dt.Is(U16)) {
20275 shift = 3;
20276 }
20277 uint32_t mvm = dm.GetCode() | index << shift;
20278 EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20279 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20280 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20281 ((mvm & 0x10) << 1));
20282 AdvanceIT();
20283 return;
20284 }
20285 }
20286 } else {
20287 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
20288 if (encoded_dt.IsValid() &&
20289 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
20290 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
20291 if (cond.Is(al)) {
20292 uint32_t shift = 4;
20293 if (dt.Is(S16) || dt.Is(U16)) {
20294 shift = 3;
20295 }
20296 uint32_t mvm = dm.GetCode() | index << shift;
20297 EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20298 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20299 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
20300 ((mvm & 0x10) << 1));
20301 return;
20302 }
20303 }
20304 }
20305 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
20306}
20307
20308void Assembler::vmull(
20309 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020310 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020311 CheckIT(cond);
20312 Dt_op_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020313 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020314 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
20315 if (encoded_dt.IsValid()) {
20316 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20317 EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20318 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20319 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
20320 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20321 AdvanceIT();
20322 return;
20323 }
20324 }
20325 } else {
20326 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
20327 if (encoded_dt.IsValid()) {
20328 if (cond.Is(al)) {
20329 EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20330 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20331 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
20332 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20333 return;
20334 }
20335 }
20336 }
20337 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
20338}
20339
20340void Assembler::vmvn(Condition cond,
20341 DataType dt,
20342 DRegister rd,
20343 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020344 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020345 CheckIT(cond);
20346 if (operand.IsImmediate()) {
20347 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020348 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020349 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20350 if (encoded_dt.IsValid()) {
20351 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20352 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
20353 rd.Encode(22, 12) |
20354 (encoded_dt.GetEncodedImmediate() & 0xf) |
20355 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20356 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20357 AdvanceIT();
20358 return;
20359 }
20360 }
20361 } else {
20362 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20363 if (encoded_dt.IsValid()) {
20364 if (cond.Is(al)) {
20365 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
20366 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20367 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20368 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20369 return;
20370 }
20371 }
20372 }
20373 }
20374 if (operand.IsRegister()) {
20375 DRegister rm = operand.GetRegister();
20376 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020377 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020378 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
20379 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20380 EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
20381 AdvanceIT();
20382 return;
20383 }
20384 } else {
20385 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
20386 if (cond.Is(al)) {
20387 EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
20388 return;
20389 }
20390 }
20391 }
20392 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
20393}
20394
20395void Assembler::vmvn(Condition cond,
20396 DataType dt,
20397 QRegister rd,
20398 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020399 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020400 CheckIT(cond);
20401 if (operand.IsImmediate()) {
20402 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020403 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020404 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
20405 if (encoded_dt.IsValid()) {
20406 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20407 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
20408 rd.Encode(22, 12) |
20409 (encoded_dt.GetEncodedImmediate() & 0xf) |
20410 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20411 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20412 AdvanceIT();
20413 return;
20414 }
20415 }
20416 } else {
20417 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
20418 if (encoded_dt.IsValid()) {
20419 if (cond.Is(al)) {
20420 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
20421 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20422 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20423 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20424 return;
20425 }
20426 }
20427 }
20428 }
20429 if (operand.IsRegister()) {
20430 QRegister rm = operand.GetRegister();
20431 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020432 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020433 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
20434 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20435 EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
20436 AdvanceIT();
20437 return;
20438 }
20439 } else {
20440 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
20441 if (cond.Is(al)) {
20442 EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
20443 return;
20444 }
20445 }
20446 }
20447 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
20448}
20449
20450void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020451 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020452 CheckIT(cond);
20453 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020454 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020455 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20456 if (encoded_dt.IsValid()) {
20457 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20458 EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20459 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20460 rd.Encode(22, 12) | rm.Encode(5, 0));
20461 AdvanceIT();
20462 return;
20463 }
20464 }
20465 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
20466 if (dt.Is(F64)) {
20467 EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20468 AdvanceIT();
20469 return;
20470 }
20471 } else {
20472 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
20473 if (encoded_dt.IsValid()) {
20474 if (cond.Is(al)) {
20475 EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20476 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20477 rd.Encode(22, 12) | rm.Encode(5, 0));
20478 return;
20479 }
20480 }
20481 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
20482 if (dt.Is(F64) && cond.IsNotNever()) {
20483 EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20484 rm.Encode(5, 0));
20485 return;
20486 }
20487 }
20488 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20489}
20490
20491void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020493 CheckIT(cond);
20494 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020495 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020496 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
20497 if (encoded_dt.IsValid()) {
20498 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20499 EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20500 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20501 rd.Encode(22, 12) | rm.Encode(5, 0));
20502 AdvanceIT();
20503 return;
20504 }
20505 }
20506 } else {
20507 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
20508 if (encoded_dt.IsValid()) {
20509 if (cond.Is(al)) {
20510 EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20511 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
20512 rd.Encode(22, 12) | rm.Encode(5, 0));
20513 return;
20514 }
20515 }
20516 }
20517 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20518}
20519
20520void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020521 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020522 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020523 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020524 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
20525 if (dt.Is(F32)) {
20526 EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20527 AdvanceIT();
20528 return;
20529 }
20530 } else {
20531 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
20532 if (dt.Is(F32) && cond.IsNotNever()) {
20533 EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20534 rm.Encode(5, 0));
20535 return;
20536 }
20537 }
20538 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
20539}
20540
20541void Assembler::vnmla(
20542 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020543 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020544 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020545 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020546 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
20547 if (dt.Is(F32)) {
20548 EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20549 rm.Encode(5, 0));
20550 AdvanceIT();
20551 return;
20552 }
20553 } else {
20554 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
20555 if (dt.Is(F32) && cond.IsNotNever()) {
20556 EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20557 rn.Encode(7, 16) | rm.Encode(5, 0));
20558 return;
20559 }
20560 }
20561 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
20562}
20563
20564void Assembler::vnmla(
20565 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020566 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020567 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020568 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020569 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
20570 if (dt.Is(F64)) {
20571 EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20572 rm.Encode(5, 0));
20573 AdvanceIT();
20574 return;
20575 }
20576 } else {
20577 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
20578 if (dt.Is(F64) && cond.IsNotNever()) {
20579 EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20580 rn.Encode(7, 16) | rm.Encode(5, 0));
20581 return;
20582 }
20583 }
20584 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
20585}
20586
20587void Assembler::vnmls(
20588 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020589 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020590 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020591 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020592 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
20593 if (dt.Is(F32)) {
20594 EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20595 rm.Encode(5, 0));
20596 AdvanceIT();
20597 return;
20598 }
20599 } else {
20600 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
20601 if (dt.Is(F32) && cond.IsNotNever()) {
20602 EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20603 rn.Encode(7, 16) | rm.Encode(5, 0));
20604 return;
20605 }
20606 }
20607 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
20608}
20609
20610void Assembler::vnmls(
20611 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020612 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020613 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020614 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020615 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
20616 if (dt.Is(F64)) {
20617 EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20618 rm.Encode(5, 0));
20619 AdvanceIT();
20620 return;
20621 }
20622 } else {
20623 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
20624 if (dt.Is(F64) && cond.IsNotNever()) {
20625 EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20626 rn.Encode(7, 16) | rm.Encode(5, 0));
20627 return;
20628 }
20629 }
20630 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
20631}
20632
20633void Assembler::vnmul(
20634 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020635 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020636 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020637 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020638 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
20639 if (dt.Is(F32)) {
20640 EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20641 rm.Encode(5, 0));
20642 AdvanceIT();
20643 return;
20644 }
20645 } else {
20646 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
20647 if (dt.Is(F32) && cond.IsNotNever()) {
20648 EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20649 rn.Encode(7, 16) | rm.Encode(5, 0));
20650 return;
20651 }
20652 }
20653 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
20654}
20655
20656void Assembler::vnmul(
20657 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020658 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020659 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020660 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020661 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
20662 if (dt.Is(F64)) {
20663 EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20664 rm.Encode(5, 0));
20665 AdvanceIT();
20666 return;
20667 }
20668 } else {
20669 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
20670 if (dt.Is(F64) && cond.IsNotNever()) {
20671 EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20672 rn.Encode(7, 16) | rm.Encode(5, 0));
20673 return;
20674 }
20675 }
20676 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
20677}
20678
20679void Assembler::vorn(Condition cond,
20680 DataType dt,
20681 DRegister rd,
20682 DRegister rn,
20683 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020684 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020685 CheckIT(cond);
20686 if (operand.IsImmediate()) {
20687 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020688 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020689 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
20690 if (encoded_dt.IsValid() && rd.Is(rn)) {
20691 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20692 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
20693 rd.Encode(22, 12) |
20694 (encoded_dt.GetEncodedImmediate() & 0xf) |
20695 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20696 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20697 AdvanceIT();
20698 return;
20699 }
20700 }
20701 } else {
20702 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
20703 if (encoded_dt.IsValid() && rd.Is(rn)) {
20704 if (cond.Is(al)) {
20705 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
20706 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20707 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20708 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20709 return;
20710 }
20711 }
20712 }
20713 }
20714 if (operand.IsRegister()) {
20715 DRegister rm = operand.GetRegister();
20716 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020717 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020718 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
20719 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20720 EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20721 rm.Encode(5, 0));
20722 AdvanceIT();
20723 return;
20724 }
20725 } else {
20726 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
20727 if (cond.Is(al)) {
20728 EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20729 rm.Encode(5, 0));
20730 return;
20731 }
20732 }
20733 }
20734 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
20735}
20736
20737void Assembler::vorn(Condition cond,
20738 DataType dt,
20739 QRegister rd,
20740 QRegister rn,
20741 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020742 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020743 CheckIT(cond);
20744 if (operand.IsImmediate()) {
20745 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020746 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020747 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
20748 if (encoded_dt.IsValid() && rd.Is(rn)) {
20749 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20750 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
20751 rd.Encode(22, 12) |
20752 (encoded_dt.GetEncodedImmediate() & 0xf) |
20753 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20754 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20755 AdvanceIT();
20756 return;
20757 }
20758 }
20759 } else {
20760 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
20761 if (encoded_dt.IsValid() && rd.Is(rn)) {
20762 if (cond.Is(al)) {
20763 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
20764 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20765 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20766 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20767 return;
20768 }
20769 }
20770 }
20771 }
20772 if (operand.IsRegister()) {
20773 QRegister rm = operand.GetRegister();
20774 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020775 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020776 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
20777 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20778 EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20779 rm.Encode(5, 0));
20780 AdvanceIT();
20781 return;
20782 }
20783 } else {
20784 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
20785 if (cond.Is(al)) {
20786 EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20787 rm.Encode(5, 0));
20788 return;
20789 }
20790 }
20791 }
20792 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
20793}
20794
20795void Assembler::vorr(Condition cond,
20796 DataType dt,
20797 DRegister rd,
20798 DRegister rn,
20799 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020800 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020801 CheckIT(cond);
20802 if (operand.IsRegister()) {
20803 DRegister rm = operand.GetRegister();
20804 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020806 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
20807 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20808 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20809 rm.Encode(5, 0));
20810 AdvanceIT();
20811 return;
20812 }
20813 } else {
20814 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
20815 if (cond.Is(al)) {
20816 EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20817 rm.Encode(5, 0));
20818 return;
20819 }
20820 }
20821 }
20822 if (operand.IsImmediate()) {
20823 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020824 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020825 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
20826 if (encoded_dt.IsValid() && rd.Is(rn)) {
20827 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20828 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
20829 rd.Encode(22, 12) |
20830 (encoded_dt.GetEncodedImmediate() & 0xf) |
20831 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20832 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20833 AdvanceIT();
20834 return;
20835 }
20836 }
20837 } else {
20838 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
20839 if (encoded_dt.IsValid() && rd.Is(rn)) {
20840 if (cond.Is(al)) {
20841 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
20842 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20843 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20844 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20845 return;
20846 }
20847 }
20848 }
20849 }
20850 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
20851}
20852
20853void Assembler::vorr(Condition cond,
20854 DataType dt,
20855 QRegister rd,
20856 QRegister rn,
20857 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020858 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020859 CheckIT(cond);
20860 if (operand.IsRegister()) {
20861 QRegister rm = operand.GetRegister();
20862 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020863 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020864 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
20865 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20866 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20867 rm.Encode(5, 0));
20868 AdvanceIT();
20869 return;
20870 }
20871 } else {
20872 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
20873 if (cond.Is(al)) {
20874 EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20875 rm.Encode(5, 0));
20876 return;
20877 }
20878 }
20879 }
20880 if (operand.IsImmediate()) {
20881 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020882 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020883 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
20884 if (encoded_dt.IsValid() && rd.Is(rn)) {
20885 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20886 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
20887 rd.Encode(22, 12) |
20888 (encoded_dt.GetEncodedImmediate() & 0xf) |
20889 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20890 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20891 AdvanceIT();
20892 return;
20893 }
20894 }
20895 } else {
20896 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
20897 if (encoded_dt.IsValid() && rd.Is(rn)) {
20898 if (cond.Is(al)) {
20899 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
20900 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20901 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20902 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20903 return;
20904 }
20905 }
20906 }
20907 }
20908 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
20909}
20910
20911void Assembler::vpadal(Condition cond,
20912 DataType dt,
20913 DRegister rd,
20914 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020915 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020916 CheckIT(cond);
20917 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020918 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020919 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
20920 if (encoded_dt.IsValid()) {
20921 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20922 EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20923 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20924 rd.Encode(22, 12) | rm.Encode(5, 0));
20925 AdvanceIT();
20926 return;
20927 }
20928 }
20929 } else {
20930 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
20931 if (encoded_dt.IsValid()) {
20932 if (cond.Is(al)) {
20933 EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20934 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20935 rd.Encode(22, 12) | rm.Encode(5, 0));
20936 return;
20937 }
20938 }
20939 }
20940 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
20941}
20942
20943void Assembler::vpadal(Condition cond,
20944 DataType dt,
20945 QRegister rd,
20946 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020947 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020948 CheckIT(cond);
20949 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020950 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020951 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
20952 if (encoded_dt.IsValid()) {
20953 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20954 EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20955 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20956 rd.Encode(22, 12) | rm.Encode(5, 0));
20957 AdvanceIT();
20958 return;
20959 }
20960 }
20961 } else {
20962 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
20963 if (encoded_dt.IsValid()) {
20964 if (cond.Is(al)) {
20965 EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
20966 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
20967 rd.Encode(22, 12) | rm.Encode(5, 0));
20968 return;
20969 }
20970 }
20971 }
20972 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
20973}
20974
20975void Assembler::vpadd(
20976 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020977 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020978 CheckIT(cond);
20979 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020980 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020981 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20982 if (dt.Is(F32)) {
20983 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20984 EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20985 rm.Encode(5, 0));
20986 AdvanceIT();
20987 return;
20988 }
20989 }
20990 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20991 if (encoded_dt.IsValid()) {
20992 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20993 EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
20994 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20995 AdvanceIT();
20996 return;
20997 }
20998 }
20999 } else {
21000 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21001 if (dt.Is(F32)) {
21002 if (cond.Is(al)) {
21003 EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21004 rm.Encode(5, 0));
21005 return;
21006 }
21007 }
21008 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21009 if (encoded_dt.IsValid()) {
21010 if (cond.Is(al)) {
21011 EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
21012 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21013 return;
21014 }
21015 }
21016 }
21017 Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
21018}
21019
21020void Assembler::vpaddl(Condition cond,
21021 DataType dt,
21022 DRegister rd,
21023 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021024 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021025 CheckIT(cond);
21026 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021027 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021028 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21029 if (encoded_dt.IsValid()) {
21030 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21031 EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21032 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21033 rd.Encode(22, 12) | rm.Encode(5, 0));
21034 AdvanceIT();
21035 return;
21036 }
21037 }
21038 } else {
21039 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21040 if (encoded_dt.IsValid()) {
21041 if (cond.Is(al)) {
21042 EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21043 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21044 rd.Encode(22, 12) | rm.Encode(5, 0));
21045 return;
21046 }
21047 }
21048 }
21049 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
21050}
21051
21052void Assembler::vpaddl(Condition cond,
21053 DataType dt,
21054 QRegister rd,
21055 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021056 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021057 CheckIT(cond);
21058 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021059 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021060 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21061 if (encoded_dt.IsValid()) {
21062 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21063 EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21064 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21065 rd.Encode(22, 12) | rm.Encode(5, 0));
21066 AdvanceIT();
21067 return;
21068 }
21069 }
21070 } else {
21071 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21072 if (encoded_dt.IsValid()) {
21073 if (cond.Is(al)) {
21074 EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21075 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
21076 rd.Encode(22, 12) | rm.Encode(5, 0));
21077 return;
21078 }
21079 }
21080 }
21081 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
21082}
21083
21084void Assembler::vpmax(
21085 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021086 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021087 CheckIT(cond);
21088 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021089 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021090 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21091 if (dt.Is(F32)) {
21092 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21093 EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21094 rm.Encode(5, 0));
21095 AdvanceIT();
21096 return;
21097 }
21098 }
21099 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21100 if (encoded_dt.IsValid()) {
21101 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21102 EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21103 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21104 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21105 AdvanceIT();
21106 return;
21107 }
21108 }
21109 } else {
21110 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21111 if (dt.Is(F32)) {
21112 if (cond.Is(al)) {
21113 EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21114 rm.Encode(5, 0));
21115 return;
21116 }
21117 }
21118 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21119 if (encoded_dt.IsValid()) {
21120 if (cond.Is(al)) {
21121 EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21122 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21123 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21124 return;
21125 }
21126 }
21127 }
21128 Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
21129}
21130
21131void Assembler::vpmin(
21132 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021133 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021134 CheckIT(cond);
21135 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021136 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021137 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21138 if (dt.Is(F32)) {
21139 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21140 EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21141 rm.Encode(5, 0));
21142 AdvanceIT();
21143 return;
21144 }
21145 }
21146 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21147 if (encoded_dt.IsValid()) {
21148 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21149 EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21150 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21151 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21152 AdvanceIT();
21153 return;
21154 }
21155 }
21156 } else {
21157 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21158 if (dt.Is(F32)) {
21159 if (cond.Is(al)) {
21160 EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21161 rm.Encode(5, 0));
21162 return;
21163 }
21164 }
21165 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21166 if (encoded_dt.IsValid()) {
21167 if (cond.Is(al)) {
21168 EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21169 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21170 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21171 return;
21172 }
21173 }
21174 }
21175 Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
21176}
21177
21178void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021179 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021180 CheckIT(cond);
21181 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021182 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021183 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
21184 if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21185 const DRegister& dreg = dreglist.GetFirstDRegister();
21186 unsigned len = dreglist.GetLength() * 2;
21187 EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
21188 AdvanceIT();
21189 return;
21190 }
21191 } else {
21192 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
21193 if (cond.IsNotNever() &&
21194 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21195 const DRegister& dreg = dreglist.GetFirstDRegister();
21196 unsigned len = dreglist.GetLength() * 2;
21197 EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
21198 (len & 0xff));
21199 return;
21200 }
21201 }
21202 Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
21203}
21204
21205void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021206 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021207 CheckIT(cond);
21208 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021209 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021210 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
21211 const SRegister& sreg = sreglist.GetFirstSRegister();
21212 unsigned len = sreglist.GetLength();
21213 EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
21214 AdvanceIT();
21215 return;
21216 } else {
21217 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
21218 if (cond.IsNotNever()) {
21219 const SRegister& sreg = sreglist.GetFirstSRegister();
21220 unsigned len = sreglist.GetLength();
21221 EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
21222 (len & 0xff));
21223 return;
21224 }
21225 }
21226 Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
21227}
21228
21229void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021230 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021231 CheckIT(cond);
21232 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021233 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021234 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
21235 if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21236 const DRegister& dreg = dreglist.GetFirstDRegister();
21237 unsigned len = dreglist.GetLength() * 2;
21238 EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
21239 AdvanceIT();
21240 return;
21241 }
21242 } else {
21243 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
21244 if (cond.IsNotNever() &&
21245 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
21246 const DRegister& dreg = dreglist.GetFirstDRegister();
21247 unsigned len = dreglist.GetLength() * 2;
21248 EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
21249 (len & 0xff));
21250 return;
21251 }
21252 }
21253 Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
21254}
21255
21256void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021257 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021258 CheckIT(cond);
21259 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021260 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021261 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
21262 const SRegister& sreg = sreglist.GetFirstSRegister();
21263 unsigned len = sreglist.GetLength();
21264 EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
21265 AdvanceIT();
21266 return;
21267 } else {
21268 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
21269 if (cond.IsNotNever()) {
21270 const SRegister& sreg = sreglist.GetFirstSRegister();
21271 unsigned len = sreglist.GetLength();
21272 EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
21273 (len & 0xff));
21274 return;
21275 }
21276 }
21277 Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
21278}
21279
21280void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021281 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021282 CheckIT(cond);
21283 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021285 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21286 if (encoded_dt.IsValid()) {
21287 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21288 EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
21289 rd.Encode(22, 12) | rm.Encode(5, 0));
21290 AdvanceIT();
21291 return;
21292 }
21293 }
21294 } else {
21295 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21296 if (encoded_dt.IsValid()) {
21297 if (cond.Is(al)) {
21298 EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
21299 rd.Encode(22, 12) | rm.Encode(5, 0));
21300 return;
21301 }
21302 }
21303 }
21304 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
21305}
21306
21307void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021308 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021309 CheckIT(cond);
21310 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021311 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021312 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21313 if (encoded_dt.IsValid()) {
21314 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21315 EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
21316 rd.Encode(22, 12) | rm.Encode(5, 0));
21317 AdvanceIT();
21318 return;
21319 }
21320 }
21321 } else {
21322 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21323 if (encoded_dt.IsValid()) {
21324 if (cond.Is(al)) {
21325 EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
21326 rd.Encode(22, 12) | rm.Encode(5, 0));
21327 return;
21328 }
21329 }
21330 }
21331 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
21332}
21333
21334void Assembler::vqadd(
21335 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021336 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021337 CheckIT(cond);
21338 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021339 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021340 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21341 if (encoded_dt.IsValid()) {
21342 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21343 EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21344 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21345 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21346 AdvanceIT();
21347 return;
21348 }
21349 }
21350 } else {
21351 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21352 if (encoded_dt.IsValid()) {
21353 if (cond.Is(al)) {
21354 EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21355 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21356 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21357 return;
21358 }
21359 }
21360 }
21361 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
21362}
21363
21364void Assembler::vqadd(
21365 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021366 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021367 CheckIT(cond);
21368 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021369 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021370 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21371 if (encoded_dt.IsValid()) {
21372 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21373 EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21374 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21375 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21376 AdvanceIT();
21377 return;
21378 }
21379 }
21380 } else {
21381 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21382 if (encoded_dt.IsValid()) {
21383 if (cond.Is(al)) {
21384 EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21385 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21386 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21387 return;
21388 }
21389 }
21390 }
21391 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
21392}
21393
21394void Assembler::vqdmlal(
21395 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021396 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021397 CheckIT(cond);
21398 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021399 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021400 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21401 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21402 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21403 EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
21404 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21405 AdvanceIT();
21406 return;
21407 }
21408 }
21409 } else {
21410 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21411 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21412 if (cond.Is(al)) {
21413 EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
21414 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21415 return;
21416 }
21417 }
21418 }
21419 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
21420}
21421
21422void Assembler::vqdmlal(Condition cond,
21423 DataType dt,
21424 QRegister rd,
21425 DRegister rn,
21426 DRegister dm,
21427 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021428 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021429 CheckIT(cond);
21430 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021431 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021432 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
21433 if (encoded_dt.IsValid() &&
21434 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21435 (!dt.Is(S16) && (index <= 1))) &&
21436 (dt.Is(S16) || dt.Is(S32))) {
21437 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21438 uint32_t shift = 4;
21439 if (dt.Is(S16)) {
21440 shift = 3;
21441 }
21442 uint32_t mvm = dm.GetCode() | index << shift;
21443 EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
21444 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21445 ((mvm & 0x10) << 1));
21446 AdvanceIT();
21447 return;
21448 }
21449 }
21450 } else {
21451 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
21452 if (encoded_dt.IsValid() &&
21453 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21454 (!dt.Is(S16) && (index <= 1))) &&
21455 (dt.Is(S16) || dt.Is(S32))) {
21456 if (cond.Is(al)) {
21457 uint32_t shift = 4;
21458 if (dt.Is(S16)) {
21459 shift = 3;
21460 }
21461 uint32_t mvm = dm.GetCode() | index << shift;
21462 EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
21463 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21464 ((mvm & 0x10) << 1));
21465 return;
21466 }
21467 }
21468 }
21469 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
21470}
21471
21472void Assembler::vqdmlsl(
21473 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021474 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021475 CheckIT(cond);
21476 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021477 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021478 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21479 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21480 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21481 EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
21482 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21483 AdvanceIT();
21484 return;
21485 }
21486 }
21487 } else {
21488 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21489 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21490 if (cond.Is(al)) {
21491 EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
21492 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21493 return;
21494 }
21495 }
21496 }
21497 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
21498}
21499
21500void Assembler::vqdmlsl(Condition cond,
21501 DataType dt,
21502 QRegister rd,
21503 DRegister rn,
21504 DRegister dm,
21505 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021506 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021507 CheckIT(cond);
21508 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021509 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021510 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
21511 if (encoded_dt.IsValid() &&
21512 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21513 (!dt.Is(S16) && (index <= 1))) &&
21514 (dt.Is(S16) || dt.Is(S32))) {
21515 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21516 uint32_t shift = 4;
21517 if (dt.Is(S16)) {
21518 shift = 3;
21519 }
21520 uint32_t mvm = dm.GetCode() | index << shift;
21521 EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
21522 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21523 ((mvm & 0x10) << 1));
21524 AdvanceIT();
21525 return;
21526 }
21527 }
21528 } else {
21529 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
21530 if (encoded_dt.IsValid() &&
21531 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21532 (!dt.Is(S16) && (index <= 1))) &&
21533 (dt.Is(S16) || dt.Is(S32))) {
21534 if (cond.Is(al)) {
21535 uint32_t shift = 4;
21536 if (dt.Is(S16)) {
21537 shift = 3;
21538 }
21539 uint32_t mvm = dm.GetCode() | index << shift;
21540 EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
21541 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21542 ((mvm & 0x10) << 1));
21543 return;
21544 }
21545 }
21546 }
21547 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
21548}
21549
21550void Assembler::vqdmulh(
21551 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021552 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021553 CheckIT(cond);
21554 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021555 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021556 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21557 if (encoded_dt.IsValid()) {
21558 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21559 EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
21560 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21561 AdvanceIT();
21562 return;
21563 }
21564 }
21565 } else {
21566 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21567 if (encoded_dt.IsValid()) {
21568 if (cond.Is(al)) {
21569 EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
21570 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21571 return;
21572 }
21573 }
21574 }
21575 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21576}
21577
21578void Assembler::vqdmulh(
21579 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021580 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021581 CheckIT(cond);
21582 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021583 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021584 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21585 if (encoded_dt.IsValid()) {
21586 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21587 EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
21588 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21589 AdvanceIT();
21590 return;
21591 }
21592 }
21593 } else {
21594 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21595 if (encoded_dt.IsValid()) {
21596 if (cond.Is(al)) {
21597 EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
21598 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21599 return;
21600 }
21601 }
21602 }
21603 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21604}
21605
21606void Assembler::vqdmulh(
21607 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021608 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021609 CheckIT(cond);
21610 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021611 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021612 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
21613 if (encoded_dt.IsValid() &&
21614 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21615 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21616 (rm.GetLane() <= 1))) &&
21617 (dt.Is(S16) || dt.Is(S32))) {
21618 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21619 EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
21620 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21621 AdvanceIT();
21622 return;
21623 }
21624 }
21625 } else {
21626 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
21627 if (encoded_dt.IsValid() &&
21628 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21629 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21630 (rm.GetLane() <= 1))) &&
21631 (dt.Is(S16) || dt.Is(S32))) {
21632 if (cond.Is(al)) {
21633 EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
21634 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21635 return;
21636 }
21637 }
21638 }
21639 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21640}
21641
21642void Assembler::vqdmulh(
21643 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021644 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021645 CheckIT(cond);
21646 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021647 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021648 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
21649 if (encoded_dt.IsValid() &&
21650 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21651 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21652 (rm.GetLane() <= 1))) &&
21653 (dt.Is(S16) || dt.Is(S32))) {
21654 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21655 EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
21656 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21657 AdvanceIT();
21658 return;
21659 }
21660 }
21661 } else {
21662 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
21663 if (encoded_dt.IsValid() &&
21664 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21665 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21666 (rm.GetLane() <= 1))) &&
21667 (dt.Is(S16) || dt.Is(S32))) {
21668 if (cond.Is(al)) {
21669 EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
21670 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21671 return;
21672 }
21673 }
21674 }
21675 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
21676}
21677
21678void Assembler::vqdmull(
21679 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021680 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021681 CheckIT(cond);
21682 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021683 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021684 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21685 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21686 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21687 EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
21688 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21689 AdvanceIT();
21690 return;
21691 }
21692 }
21693 } else {
21694 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21695 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
21696 if (cond.Is(al)) {
21697 EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
21698 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21699 return;
21700 }
21701 }
21702 }
21703 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
21704}
21705
21706void Assembler::vqdmull(
21707 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021708 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021709 CheckIT(cond);
21710 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021711 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021712 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
21713 if (encoded_dt.IsValid() &&
21714 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21715 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21716 (rm.GetLane() <= 1))) &&
21717 (dt.Is(S16) || dt.Is(S32))) {
21718 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21719 EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
21720 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21721 AdvanceIT();
21722 return;
21723 }
21724 }
21725 } else {
21726 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
21727 if (encoded_dt.IsValid() &&
21728 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21729 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21730 (rm.GetLane() <= 1))) &&
21731 (dt.Is(S16) || dt.Is(S32))) {
21732 if (cond.Is(al)) {
21733 EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
21734 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21735 return;
21736 }
21737 }
21738 }
21739 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
21740}
21741
21742void Assembler::vqmovn(Condition cond,
21743 DataType dt,
21744 DRegister rd,
21745 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021746 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021747 CheckIT(cond);
21748 Dt_op_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021749 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021750 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21751 if (encoded_dt.IsValid()) {
21752 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21753 EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21754 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
21755 rd.Encode(22, 12) | rm.Encode(5, 0));
21756 AdvanceIT();
21757 return;
21758 }
21759 }
21760 } else {
21761 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21762 if (encoded_dt.IsValid()) {
21763 if (cond.Is(al)) {
21764 EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21765 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
21766 rd.Encode(22, 12) | rm.Encode(5, 0));
21767 return;
21768 }
21769 }
21770 }
21771 Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
21772}
21773
21774void Assembler::vqmovun(Condition cond,
21775 DataType dt,
21776 DRegister rd,
21777 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021778 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021779 CheckIT(cond);
21780 Dt_size_14 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021781 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021782 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21783 if (encoded_dt.IsValid()) {
21784 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21785 EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
21786 rd.Encode(22, 12) | rm.Encode(5, 0));
21787 AdvanceIT();
21788 return;
21789 }
21790 }
21791 } else {
21792 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21793 if (encoded_dt.IsValid()) {
21794 if (cond.Is(al)) {
21795 EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
21796 rd.Encode(22, 12) | rm.Encode(5, 0));
21797 return;
21798 }
21799 }
21800 }
21801 Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
21802}
21803
21804void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021805 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021806 CheckIT(cond);
21807 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021808 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021809 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21810 if (encoded_dt.IsValid()) {
21811 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21812 EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
21813 rd.Encode(22, 12) | rm.Encode(5, 0));
21814 AdvanceIT();
21815 return;
21816 }
21817 }
21818 } else {
21819 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21820 if (encoded_dt.IsValid()) {
21821 if (cond.Is(al)) {
21822 EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
21823 rd.Encode(22, 12) | rm.Encode(5, 0));
21824 return;
21825 }
21826 }
21827 }
21828 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
21829}
21830
21831void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021832 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021833 CheckIT(cond);
21834 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021835 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021836 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21837 if (encoded_dt.IsValid()) {
21838 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21839 EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
21840 rd.Encode(22, 12) | rm.Encode(5, 0));
21841 AdvanceIT();
21842 return;
21843 }
21844 }
21845 } else {
21846 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21847 if (encoded_dt.IsValid()) {
21848 if (cond.Is(al)) {
21849 EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
21850 rd.Encode(22, 12) | rm.Encode(5, 0));
21851 return;
21852 }
21853 }
21854 }
21855 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
21856}
21857
21858void Assembler::vqrdmulh(
21859 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021860 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021861 CheckIT(cond);
21862 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021863 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021864 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21865 if (encoded_dt.IsValid()) {
21866 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21867 EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
21868 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21869 AdvanceIT();
21870 return;
21871 }
21872 }
21873 } else {
21874 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21875 if (encoded_dt.IsValid()) {
21876 if (cond.Is(al)) {
21877 EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
21878 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21879 return;
21880 }
21881 }
21882 }
21883 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21884}
21885
21886void Assembler::vqrdmulh(
21887 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021888 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021889 CheckIT(cond);
21890 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021891 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021892 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21893 if (encoded_dt.IsValid()) {
21894 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21895 EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
21896 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21897 AdvanceIT();
21898 return;
21899 }
21900 }
21901 } else {
21902 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21903 if (encoded_dt.IsValid()) {
21904 if (cond.Is(al)) {
21905 EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
21906 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21907 return;
21908 }
21909 }
21910 }
21911 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21912}
21913
21914void Assembler::vqrdmulh(
21915 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021916 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021917 CheckIT(cond);
21918 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021919 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021920 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
21921 if (encoded_dt.IsValid() &&
21922 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21923 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21924 (rm.GetLane() <= 1))) &&
21925 (dt.Is(S16) || dt.Is(S32))) {
21926 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21927 EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
21928 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21929 AdvanceIT();
21930 return;
21931 }
21932 }
21933 } else {
21934 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
21935 if (encoded_dt.IsValid() &&
21936 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21937 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21938 (rm.GetLane() <= 1))) &&
21939 (dt.Is(S16) || dt.Is(S32))) {
21940 if (cond.Is(al)) {
21941 EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
21942 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21943 return;
21944 }
21945 }
21946 }
21947 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21948}
21949
21950void Assembler::vqrdmulh(
21951 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021952 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021953 CheckIT(cond);
21954 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021955 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021956 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
21957 if (encoded_dt.IsValid() &&
21958 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21959 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21960 (rm.GetLane() <= 1))) &&
21961 (dt.Is(S16) || dt.Is(S32))) {
21962 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21963 EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
21964 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21965 AdvanceIT();
21966 return;
21967 }
21968 }
21969 } else {
21970 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
21971 if (encoded_dt.IsValid() &&
21972 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
21973 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
21974 (rm.GetLane() <= 1))) &&
21975 (dt.Is(S16) || dt.Is(S32))) {
21976 if (cond.Is(al)) {
21977 EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
21978 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
21979 return;
21980 }
21981 }
21982 }
21983 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
21984}
21985
21986void Assembler::vqrshl(
21987 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021988 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021989 CheckIT(cond);
21990 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021991 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021992 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
21993 if (encoded_dt.IsValid()) {
21994 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21995 EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21996 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21997 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
21998 AdvanceIT();
21999 return;
22000 }
22001 }
22002 } else {
22003 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
22004 if (encoded_dt.IsValid()) {
22005 if (cond.Is(al)) {
22006 EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22007 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22008 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22009 return;
22010 }
22011 }
22012 }
22013 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
22014}
22015
22016void Assembler::vqrshl(
22017 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022018 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022019 CheckIT(cond);
22020 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022021 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022022 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
22023 if (encoded_dt.IsValid()) {
22024 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22025 EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22026 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22027 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22028 AdvanceIT();
22029 return;
22030 }
22031 }
22032 } else {
22033 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
22034 if (encoded_dt.IsValid()) {
22035 if (cond.Is(al)) {
22036 EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22037 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22038 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22039 return;
22040 }
22041 }
22042 }
22043 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
22044}
22045
22046void Assembler::vqrshrn(Condition cond,
22047 DataType dt,
22048 DRegister rd,
22049 QRegister rm,
22050 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022051 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022052 CheckIT(cond);
22053 if (operand.IsImmediate()) {
22054 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22055 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22056 Dt_op_size_3 encoded_dt(dt);
22057 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022058 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022059 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22060 if (encoded_dt.IsValid() && (imm == 0)) {
22061 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22062 EmitT32_32(0xffb20280U |
22063 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22064 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22065 rd.Encode(22, 12) | rm.Encode(5, 0));
22066 AdvanceIT();
22067 return;
22068 }
22069 }
22070 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22071 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22072 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22073 uint32_t imm6 = dt.GetSize() / 2 - imm;
22074 EmitT32_32(0xef800950U |
22075 (encoded_dt_2.GetTypeEncodingValue() << 28) |
22076 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22077 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22078 AdvanceIT();
22079 return;
22080 }
22081 }
22082 } else {
22083 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22084 if (encoded_dt.IsValid() && (imm == 0)) {
22085 if (cond.Is(al)) {
22086 EmitA32(0xf3b20280U |
22087 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22088 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22089 rd.Encode(22, 12) | rm.Encode(5, 0));
22090 return;
22091 }
22092 }
22093 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22094 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22095 if (cond.Is(al)) {
22096 uint32_t imm6 = dt.GetSize() / 2 - imm;
22097 EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
22098 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22099 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22100 return;
22101 }
22102 }
22103 }
22104 }
22105 }
22106 Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
22107}
22108
22109void Assembler::vqrshrun(Condition cond,
22110 DataType dt,
22111 DRegister rd,
22112 QRegister rm,
22113 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022114 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022115 CheckIT(cond);
22116 if (operand.IsImmediate()) {
22117 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22118 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22119 Dt_imm6_2 encoded_dt(dt);
22120 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022121 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022122 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22123 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22124 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22125 uint32_t imm6 = dt.GetSize() / 2 - imm;
22126 EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
22127 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22128 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22129 AdvanceIT();
22130 return;
22131 }
22132 }
22133 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22134 if (encoded_dt_2.IsValid() && (imm == 0)) {
22135 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22136 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22137 rd.Encode(22, 12) | rm.Encode(5, 0));
22138 AdvanceIT();
22139 return;
22140 }
22141 }
22142 } else {
22143 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22144 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22145 if (cond.Is(al)) {
22146 uint32_t imm6 = dt.GetSize() / 2 - imm;
22147 EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
22148 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22149 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22150 return;
22151 }
22152 }
22153 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22154 if (encoded_dt_2.IsValid() && (imm == 0)) {
22155 if (cond.Is(al)) {
22156 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22157 rd.Encode(22, 12) | rm.Encode(5, 0));
22158 return;
22159 }
22160 }
22161 }
22162 }
22163 }
22164 Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
22165}
22166
22167void Assembler::vqshl(Condition cond,
22168 DataType dt,
22169 DRegister rd,
22170 DRegister rm,
22171 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022172 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022173 CheckIT(cond);
22174 if (operand.IsRegister()) {
22175 DRegister rn = operand.GetRegister();
22176 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022177 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022178 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
22179 if (encoded_dt.IsValid()) {
22180 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22181 EmitT32_32(0xef000410U |
22182 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22183 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22184 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22185 AdvanceIT();
22186 return;
22187 }
22188 }
22189 } else {
22190 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
22191 if (encoded_dt.IsValid()) {
22192 if (cond.Is(al)) {
22193 EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22194 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22195 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22196 return;
22197 }
22198 }
22199 }
22200 }
22201 if (operand.IsImmediate()) {
22202 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22203 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22204 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022205 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022206 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
22207 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22208 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22209 uint32_t imm6 = imm;
22210 EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
22211 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22212 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22213 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22214 AdvanceIT();
22215 return;
22216 }
22217 }
22218 } else {
22219 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
22220 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22221 if (cond.Is(al)) {
22222 uint32_t imm6 = imm;
22223 EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
22224 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22225 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22226 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22227 return;
22228 }
22229 }
22230 }
22231 }
22232 }
22233 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
22234}
22235
22236void Assembler::vqshl(Condition cond,
22237 DataType dt,
22238 QRegister rd,
22239 QRegister rm,
22240 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022241 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022242 CheckIT(cond);
22243 if (operand.IsRegister()) {
22244 QRegister rn = operand.GetRegister();
22245 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022246 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022247 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
22248 if (encoded_dt.IsValid()) {
22249 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22250 EmitT32_32(0xef000450U |
22251 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22252 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22253 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22254 AdvanceIT();
22255 return;
22256 }
22257 }
22258 } else {
22259 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
22260 if (encoded_dt.IsValid()) {
22261 if (cond.Is(al)) {
22262 EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22263 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22264 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
22265 return;
22266 }
22267 }
22268 }
22269 }
22270 if (operand.IsImmediate()) {
22271 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22272 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22273 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022274 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022275 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
22276 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22277 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22278 uint32_t imm6 = imm;
22279 EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
22280 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22281 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22282 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22283 AdvanceIT();
22284 return;
22285 }
22286 }
22287 } else {
22288 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
22289 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22290 if (cond.Is(al)) {
22291 uint32_t imm6 = imm;
22292 EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
22293 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22294 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22295 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22296 return;
22297 }
22298 }
22299 }
22300 }
22301 }
22302 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
22303}
22304
22305void Assembler::vqshlu(Condition cond,
22306 DataType dt,
22307 DRegister rd,
22308 DRegister rm,
22309 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022310 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022311 CheckIT(cond);
22312 if (operand.IsImmediate()) {
22313 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22314 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22315 Dt_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022316 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022317 // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
22318 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22319 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22320 uint32_t imm6 = imm;
22321 EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
22322 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22323 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22324 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22325 AdvanceIT();
22326 return;
22327 }
22328 }
22329 } else {
22330 // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
22331 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22332 if (cond.Is(al)) {
22333 uint32_t imm6 = imm;
22334 EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
22335 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22336 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22337 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22338 return;
22339 }
22340 }
22341 }
22342 }
22343 }
22344 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
22345}
22346
22347void Assembler::vqshlu(Condition cond,
22348 DataType dt,
22349 QRegister rd,
22350 QRegister rm,
22351 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022352 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022353 CheckIT(cond);
22354 if (operand.IsImmediate()) {
22355 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22356 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22357 Dt_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022358 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022359 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
22360 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22361 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22362 uint32_t imm6 = imm;
22363 EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
22364 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22365 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22366 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22367 AdvanceIT();
22368 return;
22369 }
22370 }
22371 } else {
22372 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
22373 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
22374 if (cond.Is(al)) {
22375 uint32_t imm6 = imm;
22376 EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
22377 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22378 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
22379 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22380 return;
22381 }
22382 }
22383 }
22384 }
22385 }
22386 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
22387}
22388
22389void Assembler::vqshrn(Condition cond,
22390 DataType dt,
22391 DRegister rd,
22392 QRegister rm,
22393 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022394 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022395 CheckIT(cond);
22396 if (operand.IsImmediate()) {
22397 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22398 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22399 Dt_op_size_3 encoded_dt(dt);
22400 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022401 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022402 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22403 if (encoded_dt.IsValid() && (imm == 0)) {
22404 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22405 EmitT32_32(0xffb20280U |
22406 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22407 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22408 rd.Encode(22, 12) | rm.Encode(5, 0));
22409 AdvanceIT();
22410 return;
22411 }
22412 }
22413 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22414 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22415 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22416 uint32_t imm6 = dt.GetSize() / 2 - imm;
22417 EmitT32_32(0xef800910U |
22418 (encoded_dt_2.GetTypeEncodingValue() << 28) |
22419 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22420 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22421 AdvanceIT();
22422 return;
22423 }
22424 }
22425 } else {
22426 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22427 if (encoded_dt.IsValid() && (imm == 0)) {
22428 if (cond.Is(al)) {
22429 EmitA32(0xf3b20280U |
22430 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22431 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22432 rd.Encode(22, 12) | rm.Encode(5, 0));
22433 return;
22434 }
22435 }
22436 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22437 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22438 if (cond.Is(al)) {
22439 uint32_t imm6 = dt.GetSize() / 2 - imm;
22440 EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
22441 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
22442 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22443 return;
22444 }
22445 }
22446 }
22447 }
22448 }
22449 Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
22450}
22451
22452void Assembler::vqshrun(Condition cond,
22453 DataType dt,
22454 DRegister rd,
22455 QRegister rm,
22456 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022457 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022458 CheckIT(cond);
22459 if (operand.IsImmediate()) {
22460 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
22461 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
22462 Dt_imm6_2 encoded_dt(dt);
22463 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022465 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
22466 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22467 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22468 uint32_t imm6 = dt.GetSize() / 2 - imm;
22469 EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
22470 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22471 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22472 AdvanceIT();
22473 return;
22474 }
22475 }
22476 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
22477 if (encoded_dt_2.IsValid() && (imm == 0)) {
22478 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22479 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22480 rd.Encode(22, 12) | rm.Encode(5, 0));
22481 AdvanceIT();
22482 return;
22483 }
22484 }
22485 } else {
22486 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
22487 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
22488 if (cond.Is(al)) {
22489 uint32_t imm6 = dt.GetSize() / 2 - imm;
22490 EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
22491 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
22492 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
22493 return;
22494 }
22495 }
22496 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
22497 if (encoded_dt_2.IsValid() && (imm == 0)) {
22498 if (cond.Is(al)) {
22499 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
22500 rd.Encode(22, 12) | rm.Encode(5, 0));
22501 return;
22502 }
22503 }
22504 }
22505 }
22506 }
22507 Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
22508}
22509
22510void Assembler::vqsub(
22511 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022512 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022513 CheckIT(cond);
22514 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022515 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022516 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22517 if (encoded_dt.IsValid()) {
22518 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22519 EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22520 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22521 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22522 AdvanceIT();
22523 return;
22524 }
22525 }
22526 } else {
22527 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22528 if (encoded_dt.IsValid()) {
22529 if (cond.Is(al)) {
22530 EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22531 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22532 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22533 return;
22534 }
22535 }
22536 }
22537 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
22538}
22539
22540void Assembler::vqsub(
22541 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022542 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022543 CheckIT(cond);
22544 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022545 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022546 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22547 if (encoded_dt.IsValid()) {
22548 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22549 EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22550 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22551 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22552 AdvanceIT();
22553 return;
22554 }
22555 }
22556 } else {
22557 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22558 if (encoded_dt.IsValid()) {
22559 if (cond.Is(al)) {
22560 EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22561 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22562 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22563 return;
22564 }
22565 }
22566 }
22567 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
22568}
22569
22570void Assembler::vraddhn(
22571 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022572 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022573 CheckIT(cond);
22574 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022575 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022576 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
22577 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
22578 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22579 EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
22580 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22581 AdvanceIT();
22582 return;
22583 }
22584 }
22585 } else {
22586 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
22587 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
22588 if (cond.Is(al)) {
22589 EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
22590 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22591 return;
22592 }
22593 }
22594 }
22595 Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
22596}
22597
22598void Assembler::vrecpe(Condition cond,
22599 DataType dt,
22600 DRegister rd,
22601 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022602 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022603 CheckIT(cond);
22604 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022605 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022606 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22607 if (encoded_dt.IsValid()) {
22608 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22609 EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22610 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22611 rd.Encode(22, 12) | rm.Encode(5, 0));
22612 AdvanceIT();
22613 return;
22614 }
22615 }
22616 } else {
22617 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22618 if (encoded_dt.IsValid()) {
22619 if (cond.Is(al)) {
22620 EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22621 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22622 rd.Encode(22, 12) | rm.Encode(5, 0));
22623 return;
22624 }
22625 }
22626 }
22627 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
22628}
22629
22630void Assembler::vrecpe(Condition cond,
22631 DataType dt,
22632 QRegister rd,
22633 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022634 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022635 CheckIT(cond);
22636 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022637 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022638 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22639 if (encoded_dt.IsValid()) {
22640 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22641 EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22642 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22643 rd.Encode(22, 12) | rm.Encode(5, 0));
22644 AdvanceIT();
22645 return;
22646 }
22647 }
22648 } else {
22649 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22650 if (encoded_dt.IsValid()) {
22651 if (cond.Is(al)) {
22652 EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22653 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
22654 rd.Encode(22, 12) | rm.Encode(5, 0));
22655 return;
22656 }
22657 }
22658 }
22659 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
22660}
22661
22662void Assembler::vrecps(
22663 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022664 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022665 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022666 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022667 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22668 if (dt.Is(F32)) {
22669 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22670 EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22671 rm.Encode(5, 0));
22672 AdvanceIT();
22673 return;
22674 }
22675 }
22676 } else {
22677 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22678 if (dt.Is(F32)) {
22679 if (cond.Is(al)) {
22680 EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22681 rm.Encode(5, 0));
22682 return;
22683 }
22684 }
22685 }
22686 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
22687}
22688
22689void Assembler::vrecps(
22690 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022691 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022692 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022693 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022694 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
22695 if (dt.Is(F32)) {
22696 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22697 EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22698 rm.Encode(5, 0));
22699 AdvanceIT();
22700 return;
22701 }
22702 }
22703 } else {
22704 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
22705 if (dt.Is(F32)) {
22706 if (cond.Is(al)) {
22707 EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22708 rm.Encode(5, 0));
22709 return;
22710 }
22711 }
22712 }
22713 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
22714}
22715
22716void Assembler::vrev16(Condition cond,
22717 DataType dt,
22718 DRegister rd,
22719 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022721 CheckIT(cond);
22722 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022723 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022724 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22725 if (encoded_dt.IsValid()) {
22726 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22727 EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
22728 rd.Encode(22, 12) | rm.Encode(5, 0));
22729 AdvanceIT();
22730 return;
22731 }
22732 }
22733 } else {
22734 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22735 if (encoded_dt.IsValid()) {
22736 if (cond.Is(al)) {
22737 EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
22738 rd.Encode(22, 12) | rm.Encode(5, 0));
22739 return;
22740 }
22741 }
22742 }
22743 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
22744}
22745
22746void Assembler::vrev16(Condition cond,
22747 DataType dt,
22748 QRegister rd,
22749 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022750 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022751 CheckIT(cond);
22752 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022754 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22755 if (encoded_dt.IsValid()) {
22756 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22757 EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
22758 rd.Encode(22, 12) | rm.Encode(5, 0));
22759 AdvanceIT();
22760 return;
22761 }
22762 }
22763 } else {
22764 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22765 if (encoded_dt.IsValid()) {
22766 if (cond.Is(al)) {
22767 EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
22768 rd.Encode(22, 12) | rm.Encode(5, 0));
22769 return;
22770 }
22771 }
22772 }
22773 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
22774}
22775
22776void Assembler::vrev32(Condition cond,
22777 DataType dt,
22778 DRegister rd,
22779 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022780 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022781 CheckIT(cond);
22782 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022783 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022784 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22785 if (encoded_dt.IsValid()) {
22786 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22787 EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
22788 rd.Encode(22, 12) | rm.Encode(5, 0));
22789 AdvanceIT();
22790 return;
22791 }
22792 }
22793 } else {
22794 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22795 if (encoded_dt.IsValid()) {
22796 if (cond.Is(al)) {
22797 EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
22798 rd.Encode(22, 12) | rm.Encode(5, 0));
22799 return;
22800 }
22801 }
22802 }
22803 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
22804}
22805
22806void Assembler::vrev32(Condition cond,
22807 DataType dt,
22808 QRegister rd,
22809 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022810 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022811 CheckIT(cond);
22812 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022813 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022814 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22815 if (encoded_dt.IsValid()) {
22816 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22817 EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
22818 rd.Encode(22, 12) | rm.Encode(5, 0));
22819 AdvanceIT();
22820 return;
22821 }
22822 }
22823 } else {
22824 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22825 if (encoded_dt.IsValid()) {
22826 if (cond.Is(al)) {
22827 EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
22828 rd.Encode(22, 12) | rm.Encode(5, 0));
22829 return;
22830 }
22831 }
22832 }
22833 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
22834}
22835
22836void Assembler::vrev64(Condition cond,
22837 DataType dt,
22838 DRegister rd,
22839 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022840 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022841 CheckIT(cond);
22842 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022844 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22845 if (encoded_dt.IsValid()) {
22846 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22847 EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
22848 rd.Encode(22, 12) | rm.Encode(5, 0));
22849 AdvanceIT();
22850 return;
22851 }
22852 }
22853 } else {
22854 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22855 if (encoded_dt.IsValid()) {
22856 if (cond.Is(al)) {
22857 EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
22858 rd.Encode(22, 12) | rm.Encode(5, 0));
22859 return;
22860 }
22861 }
22862 }
22863 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
22864}
22865
22866void Assembler::vrev64(Condition cond,
22867 DataType dt,
22868 QRegister rd,
22869 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022870 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022871 CheckIT(cond);
22872 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022873 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022874 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22875 if (encoded_dt.IsValid()) {
22876 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22877 EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
22878 rd.Encode(22, 12) | rm.Encode(5, 0));
22879 AdvanceIT();
22880 return;
22881 }
22882 }
22883 } else {
22884 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22885 if (encoded_dt.IsValid()) {
22886 if (cond.Is(al)) {
22887 EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
22888 rd.Encode(22, 12) | rm.Encode(5, 0));
22889 return;
22890 }
22891 }
22892 }
22893 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
22894}
22895
22896void Assembler::vrhadd(
22897 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022898 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022899 CheckIT(cond);
22900 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022901 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022902 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22903 if (encoded_dt.IsValid()) {
22904 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22905 EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22906 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22907 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22908 AdvanceIT();
22909 return;
22910 }
22911 }
22912 } else {
22913 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22914 if (encoded_dt.IsValid()) {
22915 if (cond.Is(al)) {
22916 EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22917 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22918 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22919 return;
22920 }
22921 }
22922 }
22923 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
22924}
22925
22926void Assembler::vrhadd(
22927 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022928 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022929 CheckIT(cond);
22930 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022931 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022932 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22933 if (encoded_dt.IsValid()) {
22934 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22935 EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22936 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22937 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22938 AdvanceIT();
22939 return;
22940 }
22941 }
22942 } else {
22943 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22944 if (encoded_dt.IsValid()) {
22945 if (cond.Is(al)) {
22946 EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22947 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22948 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22949 return;
22950 }
22951 }
22952 }
22953 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
22954}
22955
22956void Assembler::vrinta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022957 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022958 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022959 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022960 // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; T1
22961 if (dt1.Is(F32) && dt2.Is(F32)) {
22962 EmitT32_32(0xffba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
22963 AdvanceIT();
22964 return;
22965 }
22966 // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; T1
22967 if (dt1.Is(F64) && dt2.Is(F64)) {
22968 EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22969 AdvanceIT();
22970 return;
22971 }
22972 } else {
22973 // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; A1
22974 if (dt1.Is(F32) && dt2.Is(F32)) {
22975 EmitA32(0xf3ba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
22976 return;
22977 }
22978 // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; A1
22979 if (dt1.Is(F64) && dt2.Is(F64)) {
22980 EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
22981 return;
22982 }
22983 }
22984 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
22985}
22986
22987void Assembler::vrinta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022988 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022989 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022990 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022991 // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; T1
22992 if (dt1.Is(F32) && dt2.Is(F32)) {
22993 EmitT32_32(0xffba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
22994 AdvanceIT();
22995 return;
22996 }
22997 } else {
22998 // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; A1
22999 if (dt1.Is(F32) && dt2.Is(F32)) {
23000 EmitA32(0xf3ba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
23001 return;
23002 }
23003 }
23004 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
23005}
23006
23007void Assembler::vrinta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023008 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023009 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023010 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023011 // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; T1
23012 if (dt1.Is(F32) && dt2.Is(F32)) {
23013 EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23014 AdvanceIT();
23015 return;
23016 }
23017 } else {
23018 // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; A1
23019 if (dt1.Is(F32) && dt2.Is(F32)) {
23020 EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23021 return;
23022 }
23023 }
23024 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
23025}
23026
23027void Assembler::vrintm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023028 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023029 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023030 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023031 // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; T1
23032 if (dt1.Is(F32) && dt2.Is(F32)) {
23033 EmitT32_32(0xffba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
23034 AdvanceIT();
23035 return;
23036 }
23037 // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; T1
23038 if (dt1.Is(F64) && dt2.Is(F64)) {
23039 EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23040 AdvanceIT();
23041 return;
23042 }
23043 } else {
23044 // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; A1
23045 if (dt1.Is(F32) && dt2.Is(F32)) {
23046 EmitA32(0xf3ba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
23047 return;
23048 }
23049 // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; A1
23050 if (dt1.Is(F64) && dt2.Is(F64)) {
23051 EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23052 return;
23053 }
23054 }
23055 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23056}
23057
23058void Assembler::vrintm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023059 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023060 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023061 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023062 // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; T1
23063 if (dt1.Is(F32) && dt2.Is(F32)) {
23064 EmitT32_32(0xffba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23065 AdvanceIT();
23066 return;
23067 }
23068 } else {
23069 // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; A1
23070 if (dt1.Is(F32) && dt2.Is(F32)) {
23071 EmitA32(0xf3ba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23072 return;
23073 }
23074 }
23075 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23076}
23077
23078void Assembler::vrintm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023079 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023080 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023081 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023082 // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; T1
23083 if (dt1.Is(F32) && dt2.Is(F32)) {
23084 EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23085 AdvanceIT();
23086 return;
23087 }
23088 } else {
23089 // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; A1
23090 if (dt1.Is(F32) && dt2.Is(F32)) {
23091 EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23092 return;
23093 }
23094 }
23095 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
23096}
23097
23098void Assembler::vrintn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023099 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023100 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023101 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023102 // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; T1
23103 if (dt1.Is(F32) && dt2.Is(F32)) {
23104 EmitT32_32(0xffba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
23105 AdvanceIT();
23106 return;
23107 }
23108 // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; T1
23109 if (dt1.Is(F64) && dt2.Is(F64)) {
23110 EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23111 AdvanceIT();
23112 return;
23113 }
23114 } else {
23115 // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; A1
23116 if (dt1.Is(F32) && dt2.Is(F32)) {
23117 EmitA32(0xf3ba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
23118 return;
23119 }
23120 // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; A1
23121 if (dt1.Is(F64) && dt2.Is(F64)) {
23122 EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23123 return;
23124 }
23125 }
23126 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23127}
23128
23129void Assembler::vrintn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023130 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023131 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023132 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023133 // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; T1
23134 if (dt1.Is(F32) && dt2.Is(F32)) {
23135 EmitT32_32(0xffba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
23136 AdvanceIT();
23137 return;
23138 }
23139 } else {
23140 // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; A1
23141 if (dt1.Is(F32) && dt2.Is(F32)) {
23142 EmitA32(0xf3ba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
23143 return;
23144 }
23145 }
23146 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23147}
23148
23149void Assembler::vrintn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023150 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023151 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023152 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023153 // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; T1
23154 if (dt1.Is(F32) && dt2.Is(F32)) {
23155 EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23156 AdvanceIT();
23157 return;
23158 }
23159 } else {
23160 // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; A1
23161 if (dt1.Is(F32) && dt2.Is(F32)) {
23162 EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23163 return;
23164 }
23165 }
23166 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
23167}
23168
23169void Assembler::vrintp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023170 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023171 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023172 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023173 // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; T1
23174 if (dt1.Is(F32) && dt2.Is(F32)) {
23175 EmitT32_32(0xffba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
23176 AdvanceIT();
23177 return;
23178 }
23179 // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; T1
23180 if (dt1.Is(F64) && dt2.Is(F64)) {
23181 EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23182 AdvanceIT();
23183 return;
23184 }
23185 } else {
23186 // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; A1
23187 if (dt1.Is(F32) && dt2.Is(F32)) {
23188 EmitA32(0xf3ba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
23189 return;
23190 }
23191 // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; A1
23192 if (dt1.Is(F64) && dt2.Is(F64)) {
23193 EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23194 return;
23195 }
23196 }
23197 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23198}
23199
23200void Assembler::vrintp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023201 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023202 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023203 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023204 // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; T1
23205 if (dt1.Is(F32) && dt2.Is(F32)) {
23206 EmitT32_32(0xffba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23207 AdvanceIT();
23208 return;
23209 }
23210 } else {
23211 // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; A1
23212 if (dt1.Is(F32) && dt2.Is(F32)) {
23213 EmitA32(0xf3ba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23214 return;
23215 }
23216 }
23217 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23218}
23219
23220void Assembler::vrintp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023221 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023222 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023223 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023224 // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; T1
23225 if (dt1.Is(F32) && dt2.Is(F32)) {
23226 EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23227 AdvanceIT();
23228 return;
23229 }
23230 } else {
23231 // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; A1
23232 if (dt1.Is(F32) && dt2.Is(F32)) {
23233 EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23234 return;
23235 }
23236 }
23237 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
23238}
23239
23240void Assembler::vrintr(
23241 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023243 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023244 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023245 // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23246 if (dt1.Is(F32) && dt2.Is(F32)) {
23247 EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23248 AdvanceIT();
23249 return;
23250 }
23251 } else {
23252 // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23253 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23254 EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23255 rm.Encode(5, 0));
23256 return;
23257 }
23258 }
23259 Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
23260}
23261
23262void Assembler::vrintr(
23263 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023264 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023265 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023266 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023267 // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23268 if (dt1.Is(F64) && dt2.Is(F64)) {
23269 EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23270 AdvanceIT();
23271 return;
23272 }
23273 } else {
23274 // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23275 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23276 EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23277 rm.Encode(5, 0));
23278 return;
23279 }
23280 }
23281 Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
23282}
23283
23284void Assembler::vrintx(
23285 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023286 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023287 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023288 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023289 // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; T1
23290 if (dt1.Is(F32) && dt2.Is(F32)) {
23291 EmitT32_32(0xffba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
23292 AdvanceIT();
23293 return;
23294 }
23295 // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23296 if (dt1.Is(F64) && dt2.Is(F64)) {
23297 EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23298 AdvanceIT();
23299 return;
23300 }
23301 } else {
23302 // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; A1
23303 if (dt1.Is(F32) && dt2.Is(F32)) {
23304 EmitA32(0xf3ba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
23305 return;
23306 }
23307 // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23308 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23309 EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23310 rm.Encode(5, 0));
23311 return;
23312 }
23313 }
23314 Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
23315}
23316
23317void Assembler::vrintx(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023318 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023319 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023320 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023321 // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; T1
23322 if (dt1.Is(F32) && dt2.Is(F32)) {
23323 EmitT32_32(0xffba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23324 AdvanceIT();
23325 return;
23326 }
23327 } else {
23328 // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; A1
23329 if (dt1.Is(F32) && dt2.Is(F32)) {
23330 EmitA32(0xf3ba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23331 return;
23332 }
23333 }
23334 Delegate(kVrintx, &Assembler::vrintx, dt1, dt2, rd, rm);
23335}
23336
23337void Assembler::vrintx(
23338 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023339 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023340 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023341 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023342 // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23343 if (dt1.Is(F32) && dt2.Is(F32)) {
23344 EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
23345 AdvanceIT();
23346 return;
23347 }
23348 } else {
23349 // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23350 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23351 EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23352 rm.Encode(5, 0));
23353 return;
23354 }
23355 }
23356 Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
23357}
23358
23359void Assembler::vrintz(
23360 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023361 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023362 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023363 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023364 // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; T1
23365 if (dt1.Is(F32) && dt2.Is(F32)) {
23366 EmitT32_32(0xffba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
23367 AdvanceIT();
23368 return;
23369 }
23370 // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
23371 if (dt1.Is(F64) && dt2.Is(F64)) {
23372 EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23373 AdvanceIT();
23374 return;
23375 }
23376 } else {
23377 // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; A1
23378 if (dt1.Is(F32) && dt2.Is(F32)) {
23379 EmitA32(0xf3ba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
23380 return;
23381 }
23382 // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
23383 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
23384 EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23385 rm.Encode(5, 0));
23386 return;
23387 }
23388 }
23389 Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
23390}
23391
23392void Assembler::vrintz(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023393 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023394 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023396 // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; T1
23397 if (dt1.Is(F32) && dt2.Is(F32)) {
23398 EmitT32_32(0xffba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23399 AdvanceIT();
23400 return;
23401 }
23402 } else {
23403 // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; A1
23404 if (dt1.Is(F32) && dt2.Is(F32)) {
23405 EmitA32(0xf3ba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23406 return;
23407 }
23408 }
23409 Delegate(kVrintz, &Assembler::vrintz, dt1, dt2, rd, rm);
23410}
23411
23412void Assembler::vrintz(
23413 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023414 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023415 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023416 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023417 // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
23418 if (dt1.Is(F32) && dt2.Is(F32)) {
23419 EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
23420 AdvanceIT();
23421 return;
23422 }
23423 } else {
23424 // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
23425 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
23426 EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
23427 rm.Encode(5, 0));
23428 return;
23429 }
23430 }
23431 Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
23432}
23433
23434void Assembler::vrshl(
23435 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023436 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023437 CheckIT(cond);
23438 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023439 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023440 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23441 if (encoded_dt.IsValid()) {
23442 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23443 EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23444 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23445 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23446 AdvanceIT();
23447 return;
23448 }
23449 }
23450 } else {
23451 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23452 if (encoded_dt.IsValid()) {
23453 if (cond.Is(al)) {
23454 EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23455 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23456 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23457 return;
23458 }
23459 }
23460 }
23461 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
23462}
23463
23464void Assembler::vrshl(
23465 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023466 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023467 CheckIT(cond);
23468 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023469 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023470 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23471 if (encoded_dt.IsValid()) {
23472 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23473 EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23474 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23475 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23476 AdvanceIT();
23477 return;
23478 }
23479 }
23480 } else {
23481 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23482 if (encoded_dt.IsValid()) {
23483 if (cond.Is(al)) {
23484 EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23485 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23486 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23487 return;
23488 }
23489 }
23490 }
23491 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
23492}
23493
23494void Assembler::vrshr(Condition cond,
23495 DataType dt,
23496 DRegister rd,
23497 DRegister rm,
23498 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023499 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023500 CheckIT(cond);
23501 if (operand.IsImmediate()) {
23502 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23503 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23504 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023505 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023506 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23507 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23508 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23509 uint32_t imm6 = dt.GetSize() - imm;
23510 EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
23511 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23512 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23513 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23514 AdvanceIT();
23515 return;
23516 }
23517 }
23518 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
23519 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23520 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23521 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23522 rm.Encode(5, 0));
23523 AdvanceIT();
23524 return;
23525 }
23526 }
23527 } else {
23528 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23529 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23530 if (cond.Is(al)) {
23531 uint32_t imm6 = dt.GetSize() - imm;
23532 EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
23533 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23534 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23535 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23536 return;
23537 }
23538 }
23539 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
23540 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23541 if (cond.Is(al)) {
23542 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23543 rm.Encode(5, 0));
23544 return;
23545 }
23546 }
23547 }
23548 }
23549 }
23550 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
23551}
23552
23553void Assembler::vrshr(Condition cond,
23554 DataType dt,
23555 QRegister rd,
23556 QRegister rm,
23557 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023558 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023559 CheckIT(cond);
23560 if (operand.IsImmediate()) {
23561 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23562 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23563 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023564 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023565 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23566 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23567 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23568 uint32_t imm6 = dt.GetSize() - imm;
23569 EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
23570 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23571 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23572 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23573 AdvanceIT();
23574 return;
23575 }
23576 }
23577 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
23578 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23579 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23580 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23581 rm.Encode(5, 0));
23582 AdvanceIT();
23583 return;
23584 }
23585 }
23586 } else {
23587 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23588 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23589 if (cond.Is(al)) {
23590 uint32_t imm6 = dt.GetSize() - imm;
23591 EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
23592 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23593 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23594 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23595 return;
23596 }
23597 }
23598 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
23599 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
23600 if (cond.Is(al)) {
23601 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
23602 rm.Encode(5, 0));
23603 return;
23604 }
23605 }
23606 }
23607 }
23608 }
23609 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
23610}
23611
23612void Assembler::vrshrn(Condition cond,
23613 DataType dt,
23614 DRegister rd,
23615 QRegister rm,
23616 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023617 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023618 CheckIT(cond);
23619 if (operand.IsImmediate()) {
23620 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23621 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23622 Dt_imm6_3 encoded_dt(dt);
23623 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023624 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023625 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
23626 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23627 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23628 uint32_t imm6 = dt.GetSize() / 2 - imm;
23629 EmitT32_32(0xef800850U |
23630 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23631 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23632 AdvanceIT();
23633 return;
23634 }
23635 }
23636 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23637 if (encoded_dt_2.IsValid() && (imm == 0)) {
23638 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23639 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
23640 rd.Encode(22, 12) | rm.Encode(5, 0));
23641 AdvanceIT();
23642 return;
23643 }
23644 }
23645 } else {
23646 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
23647 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23648 if (cond.Is(al)) {
23649 uint32_t imm6 = dt.GetSize() / 2 - imm;
23650 EmitA32(0xf2800850U |
23651 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23652 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23653 return;
23654 }
23655 }
23656 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23657 if (encoded_dt_2.IsValid() && (imm == 0)) {
23658 if (cond.Is(al)) {
23659 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
23660 rd.Encode(22, 12) | rm.Encode(5, 0));
23661 return;
23662 }
23663 }
23664 }
23665 }
23666 }
23667 Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
23668}
23669
23670void Assembler::vrsqrte(Condition cond,
23671 DataType dt,
23672 DRegister rd,
23673 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023674 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023675 CheckIT(cond);
23676 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023677 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023678 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23679 if (encoded_dt.IsValid()) {
23680 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23681 EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23682 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23683 rd.Encode(22, 12) | rm.Encode(5, 0));
23684 AdvanceIT();
23685 return;
23686 }
23687 }
23688 } else {
23689 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23690 if (encoded_dt.IsValid()) {
23691 if (cond.Is(al)) {
23692 EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23693 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23694 rd.Encode(22, 12) | rm.Encode(5, 0));
23695 return;
23696 }
23697 }
23698 }
23699 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
23700}
23701
23702void Assembler::vrsqrte(Condition cond,
23703 DataType dt,
23704 QRegister rd,
23705 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023706 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023707 CheckIT(cond);
23708 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023709 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023710 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23711 if (encoded_dt.IsValid()) {
23712 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23713 EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23714 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23715 rd.Encode(22, 12) | rm.Encode(5, 0));
23716 AdvanceIT();
23717 return;
23718 }
23719 }
23720 } else {
23721 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23722 if (encoded_dt.IsValid()) {
23723 if (cond.Is(al)) {
23724 EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23725 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23726 rd.Encode(22, 12) | rm.Encode(5, 0));
23727 return;
23728 }
23729 }
23730 }
23731 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
23732}
23733
23734void Assembler::vrsqrts(
23735 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023736 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023737 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023738 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023739 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23740 if (dt.Is(F32)) {
23741 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23742 EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23743 rm.Encode(5, 0));
23744 AdvanceIT();
23745 return;
23746 }
23747 }
23748 } else {
23749 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23750 if (dt.Is(F32)) {
23751 if (cond.Is(al)) {
23752 EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23753 rm.Encode(5, 0));
23754 return;
23755 }
23756 }
23757 }
23758 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
23759}
23760
23761void Assembler::vrsqrts(
23762 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023763 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023764 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023765 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023766 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23767 if (dt.Is(F32)) {
23768 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23769 EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23770 rm.Encode(5, 0));
23771 AdvanceIT();
23772 return;
23773 }
23774 }
23775 } else {
23776 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23777 if (dt.Is(F32)) {
23778 if (cond.Is(al)) {
23779 EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23780 rm.Encode(5, 0));
23781 return;
23782 }
23783 }
23784 }
23785 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
23786}
23787
23788void Assembler::vrsra(Condition cond,
23789 DataType dt,
23790 DRegister rd,
23791 DRegister rm,
23792 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023793 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023794 CheckIT(cond);
23795 if (operand.IsImmediate()) {
23796 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23797 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23798 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023799 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023800 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23801 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23802 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23803 uint32_t imm6 = dt.GetSize() - imm;
23804 EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
23805 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23806 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23807 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23808 AdvanceIT();
23809 return;
23810 }
23811 }
23812 } else {
23813 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23814 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23815 if (cond.Is(al)) {
23816 uint32_t imm6 = dt.GetSize() - imm;
23817 EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
23818 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23819 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23820 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23821 return;
23822 }
23823 }
23824 }
23825 }
23826 }
23827 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
23828}
23829
23830void Assembler::vrsra(Condition cond,
23831 DataType dt,
23832 QRegister rd,
23833 QRegister rm,
23834 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023835 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023836 CheckIT(cond);
23837 if (operand.IsImmediate()) {
23838 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23839 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23840 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023841 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023842 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23843 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23844 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23845 uint32_t imm6 = dt.GetSize() - imm;
23846 EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
23847 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23848 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23849 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23850 AdvanceIT();
23851 return;
23852 }
23853 }
23854 } else {
23855 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23856 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
23857 if (cond.Is(al)) {
23858 uint32_t imm6 = dt.GetSize() - imm;
23859 EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
23860 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23861 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23862 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23863 return;
23864 }
23865 }
23866 }
23867 }
23868 }
23869 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
23870}
23871
23872void Assembler::vrsubhn(
23873 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023874 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023875 CheckIT(cond);
23876 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023877 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023878 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23879 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23880 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23881 EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
23882 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23883 AdvanceIT();
23884 return;
23885 }
23886 }
23887 } else {
23888 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23889 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23890 if (cond.Is(al)) {
23891 EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
23892 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23893 return;
23894 }
23895 }
23896 }
23897 Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
23898}
23899
23900void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023901 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023902 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023903 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023904 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
23905 if (OutsideITBlock() && dt.Is(F64)) {
23906 EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23907 rm.Encode(5, 0));
23908 AdvanceIT();
23909 return;
23910 }
23911 } else {
23912 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
23913 if (dt.Is(F64)) {
23914 EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23915 rm.Encode(5, 0));
23916 return;
23917 }
23918 }
23919 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
23920}
23921
23922void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023923 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023924 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023925 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023926 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
23927 if (OutsideITBlock() && dt.Is(F32)) {
23928 EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23929 rm.Encode(5, 0));
23930 AdvanceIT();
23931 return;
23932 }
23933 } else {
23934 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
23935 if (dt.Is(F32)) {
23936 EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23937 rm.Encode(5, 0));
23938 return;
23939 }
23940 }
23941 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
23942}
23943
23944void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023946 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023947 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023948 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
23949 if (OutsideITBlock() && dt.Is(F64)) {
23950 EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23951 rm.Encode(5, 0));
23952 AdvanceIT();
23953 return;
23954 }
23955 } else {
23956 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
23957 if (dt.Is(F64)) {
23958 EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23959 rm.Encode(5, 0));
23960 return;
23961 }
23962 }
23963 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
23964}
23965
23966void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023967 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023968 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023969 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023970 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
23971 if (OutsideITBlock() && dt.Is(F32)) {
23972 EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23973 rm.Encode(5, 0));
23974 AdvanceIT();
23975 return;
23976 }
23977 } else {
23978 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
23979 if (dt.Is(F32)) {
23980 EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23981 rm.Encode(5, 0));
23982 return;
23983 }
23984 }
23985 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
23986}
23987
23988void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023989 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023990 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023991 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023992 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
23993 if (OutsideITBlock() && dt.Is(F64)) {
23994 EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23995 rm.Encode(5, 0));
23996 AdvanceIT();
23997 return;
23998 }
23999 } else {
24000 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
24001 if (dt.Is(F64)) {
24002 EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24003 rm.Encode(5, 0));
24004 return;
24005 }
24006 }
24007 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
24008}
24009
24010void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024011 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024012 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024013 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024014 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
24015 if (OutsideITBlock() && dt.Is(F32)) {
24016 EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24017 rm.Encode(5, 0));
24018 AdvanceIT();
24019 return;
24020 }
24021 } else {
24022 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
24023 if (dt.Is(F32)) {
24024 EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24025 rm.Encode(5, 0));
24026 return;
24027 }
24028 }
24029 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
24030}
24031
24032void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024033 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024034 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024035 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024036 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
24037 if (OutsideITBlock() && dt.Is(F64)) {
24038 EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24039 rm.Encode(5, 0));
24040 AdvanceIT();
24041 return;
24042 }
24043 } else {
24044 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
24045 if (dt.Is(F64)) {
24046 EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24047 rm.Encode(5, 0));
24048 return;
24049 }
24050 }
24051 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
24052}
24053
24054void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024055 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024056 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024057 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024058 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
24059 if (OutsideITBlock() && dt.Is(F32)) {
24060 EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24061 rm.Encode(5, 0));
24062 AdvanceIT();
24063 return;
24064 }
24065 } else {
24066 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
24067 if (dt.Is(F32)) {
24068 EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24069 rm.Encode(5, 0));
24070 return;
24071 }
24072 }
24073 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
24074}
24075
24076void Assembler::vshl(Condition cond,
24077 DataType dt,
24078 DRegister rd,
24079 DRegister rm,
24080 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024081 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024082 CheckIT(cond);
24083 if (operand.IsImmediate()) {
24084 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24085 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24086 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024087 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024088 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
24089 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24090 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24091 uint32_t imm6 = imm;
24092 EmitT32_32(0xef800510U |
24093 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24094 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24095 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24096 AdvanceIT();
24097 return;
24098 }
24099 }
24100 } else {
24101 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
24102 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24103 if (cond.Is(al)) {
24104 uint32_t imm6 = imm;
24105 EmitA32(0xf2800510U |
24106 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24107 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24108 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24109 return;
24110 }
24111 }
24112 }
24113 }
24114 }
24115 if (operand.IsRegister()) {
24116 DRegister rn = operand.GetRegister();
24117 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024118 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024119 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24120 if (encoded_dt.IsValid()) {
24121 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24122 EmitT32_32(0xef000400U |
24123 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24124 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24125 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24126 AdvanceIT();
24127 return;
24128 }
24129 }
24130 } else {
24131 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24132 if (encoded_dt.IsValid()) {
24133 if (cond.Is(al)) {
24134 EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24135 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24136 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24137 return;
24138 }
24139 }
24140 }
24141 }
24142 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
24143}
24144
24145void Assembler::vshl(Condition cond,
24146 DataType dt,
24147 QRegister rd,
24148 QRegister rm,
24149 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024150 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024151 CheckIT(cond);
24152 if (operand.IsImmediate()) {
24153 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24154 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24155 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024156 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024157 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
24158 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24159 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24160 uint32_t imm6 = imm;
24161 EmitT32_32(0xef800550U |
24162 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24163 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24164 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24165 AdvanceIT();
24166 return;
24167 }
24168 }
24169 } else {
24170 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
24171 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24172 if (cond.Is(al)) {
24173 uint32_t imm6 = imm;
24174 EmitA32(0xf2800550U |
24175 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24176 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24177 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24178 return;
24179 }
24180 }
24181 }
24182 }
24183 }
24184 if (operand.IsRegister()) {
24185 QRegister rn = operand.GetRegister();
24186 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024187 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024188 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24189 if (encoded_dt.IsValid()) {
24190 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24191 EmitT32_32(0xef000440U |
24192 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24193 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24194 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24195 AdvanceIT();
24196 return;
24197 }
24198 }
24199 } else {
24200 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24201 if (encoded_dt.IsValid()) {
24202 if (cond.Is(al)) {
24203 EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24204 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24205 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24206 return;
24207 }
24208 }
24209 }
24210 }
24211 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
24212}
24213
24214void Assembler::vshll(Condition cond,
24215 DataType dt,
24216 QRegister rd,
24217 DRegister rm,
24218 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024219 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024220 CheckIT(cond);
24221 if (operand.IsImmediate()) {
24222 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24223 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24224 Dt_imm6_4 encoded_dt(dt);
24225 Dt_size_16 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024226 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024227 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
24228 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
24229 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24230 uint32_t imm6 = dt.GetSize() + imm;
24231 EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
24232 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24233 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24234 AdvanceIT();
24235 return;
24236 }
24237 }
24238 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
24239 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
24240 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24241 EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
24242 rd.Encode(22, 12) | rm.Encode(5, 0));
24243 AdvanceIT();
24244 return;
24245 }
24246 }
24247 } else {
24248 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
24249 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
24250 if (cond.Is(al)) {
24251 uint32_t imm6 = dt.GetSize() + imm;
24252 EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
24253 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24254 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24255 return;
24256 }
24257 }
24258 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
24259 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
24260 if (cond.Is(al)) {
24261 EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
24262 rd.Encode(22, 12) | rm.Encode(5, 0));
24263 return;
24264 }
24265 }
24266 }
24267 }
24268 }
24269 Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
24270}
24271
24272void Assembler::vshr(Condition cond,
24273 DataType dt,
24274 DRegister rd,
24275 DRegister rm,
24276 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024277 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024278 CheckIT(cond);
24279 if (operand.IsImmediate()) {
24280 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24281 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24282 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024283 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024284 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24285 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24286 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24287 uint32_t imm6 = dt.GetSize() - imm;
24288 EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
24289 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24290 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24291 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24292 AdvanceIT();
24293 return;
24294 }
24295 }
24296 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24297 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24298 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24299 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24300 rm.Encode(5, 0));
24301 AdvanceIT();
24302 return;
24303 }
24304 }
24305 } else {
24306 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24307 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24308 if (cond.Is(al)) {
24309 uint32_t imm6 = dt.GetSize() - imm;
24310 EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
24311 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24312 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24313 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24314 return;
24315 }
24316 }
24317 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24318 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24319 if (cond.Is(al)) {
24320 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24321 rm.Encode(5, 0));
24322 return;
24323 }
24324 }
24325 }
24326 }
24327 }
24328 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
24329}
24330
24331void Assembler::vshr(Condition cond,
24332 DataType dt,
24333 QRegister rd,
24334 QRegister rm,
24335 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024336 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024337 CheckIT(cond);
24338 if (operand.IsImmediate()) {
24339 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24340 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24341 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024342 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024343 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24344 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24345 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24346 uint32_t imm6 = dt.GetSize() - imm;
24347 EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
24348 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24349 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24350 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24351 AdvanceIT();
24352 return;
24353 }
24354 }
24355 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24356 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24357 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24358 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24359 rm.Encode(5, 0));
24360 AdvanceIT();
24361 return;
24362 }
24363 }
24364 } else {
24365 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24366 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24367 if (cond.Is(al)) {
24368 uint32_t imm6 = dt.GetSize() - imm;
24369 EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
24370 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24371 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24372 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24373 return;
24374 }
24375 }
24376 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24377 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24378 if (cond.Is(al)) {
24379 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24380 rm.Encode(5, 0));
24381 return;
24382 }
24383 }
24384 }
24385 }
24386 }
24387 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
24388}
24389
24390void Assembler::vshrn(Condition cond,
24391 DataType dt,
24392 DRegister rd,
24393 QRegister rm,
24394 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024395 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024396 CheckIT(cond);
24397 if (operand.IsImmediate()) {
24398 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24399 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24400 Dt_imm6_3 encoded_dt(dt);
24401 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024402 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024403 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24404 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24405 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24406 uint32_t imm6 = dt.GetSize() / 2 - imm;
24407 EmitT32_32(0xef800810U |
24408 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24409 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24410 AdvanceIT();
24411 return;
24412 }
24413 }
24414 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24415 if (encoded_dt_2.IsValid() && (imm == 0)) {
24416 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24417 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24418 rd.Encode(22, 12) | rm.Encode(5, 0));
24419 AdvanceIT();
24420 return;
24421 }
24422 }
24423 } else {
24424 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24425 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24426 if (cond.Is(al)) {
24427 uint32_t imm6 = dt.GetSize() / 2 - imm;
24428 EmitA32(0xf2800810U |
24429 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24430 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24431 return;
24432 }
24433 }
24434 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24435 if (encoded_dt_2.IsValid() && (imm == 0)) {
24436 if (cond.Is(al)) {
24437 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24438 rd.Encode(22, 12) | rm.Encode(5, 0));
24439 return;
24440 }
24441 }
24442 }
24443 }
24444 }
24445 Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
24446}
24447
24448void Assembler::vsli(Condition cond,
24449 DataType dt,
24450 DRegister rd,
24451 DRegister rm,
24452 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024453 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024454 CheckIT(cond);
24455 if (operand.IsImmediate()) {
24456 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24457 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24458 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024459 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024460 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
24461 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24462 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24463 uint32_t imm6 = imm;
24464 EmitT32_32(0xff800510U |
24465 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24466 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24467 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24468 AdvanceIT();
24469 return;
24470 }
24471 }
24472 } else {
24473 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
24474 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24475 if (cond.Is(al)) {
24476 uint32_t imm6 = imm;
24477 EmitA32(0xf3800510U |
24478 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24479 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24480 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24481 return;
24482 }
24483 }
24484 }
24485 }
24486 }
24487 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
24488}
24489
24490void Assembler::vsli(Condition cond,
24491 DataType dt,
24492 QRegister rd,
24493 QRegister rm,
24494 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024495 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024496 CheckIT(cond);
24497 if (operand.IsImmediate()) {
24498 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24499 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24500 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024501 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024502 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
24503 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24504 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24505 uint32_t imm6 = imm;
24506 EmitT32_32(0xff800550U |
24507 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24508 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24509 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24510 AdvanceIT();
24511 return;
24512 }
24513 }
24514 } else {
24515 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
24516 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
24517 if (cond.Is(al)) {
24518 uint32_t imm6 = imm;
24519 EmitA32(0xf3800550U |
24520 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24521 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24522 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24523 return;
24524 }
24525 }
24526 }
24527 }
24528 }
24529 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
24530}
24531
24532void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024534 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024536 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24537 if (dt.Is(F32)) {
24538 EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24539 AdvanceIT();
24540 return;
24541 }
24542 } else {
24543 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24544 if (dt.Is(F32) && cond.IsNotNever()) {
24545 EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24546 rm.Encode(5, 0));
24547 return;
24548 }
24549 }
24550 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
24551}
24552
24553void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024554 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024555 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024556 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024557 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24558 if (dt.Is(F64)) {
24559 EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24560 AdvanceIT();
24561 return;
24562 }
24563 } else {
24564 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24565 if (dt.Is(F64) && cond.IsNotNever()) {
24566 EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24567 rm.Encode(5, 0));
24568 return;
24569 }
24570 }
24571 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
24572}
24573
24574void Assembler::vsra(Condition cond,
24575 DataType dt,
24576 DRegister rd,
24577 DRegister rm,
24578 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024579 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024580 CheckIT(cond);
24581 if (operand.IsImmediate()) {
24582 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24583 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24584 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024585 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024586 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24587 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24588 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24589 uint32_t imm6 = dt.GetSize() - imm;
24590 EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
24591 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24592 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24593 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24594 AdvanceIT();
24595 return;
24596 }
24597 }
24598 } else {
24599 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24600 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24601 if (cond.Is(al)) {
24602 uint32_t imm6 = dt.GetSize() - imm;
24603 EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
24604 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24605 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24606 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24607 return;
24608 }
24609 }
24610 }
24611 }
24612 }
24613 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
24614}
24615
24616void Assembler::vsra(Condition cond,
24617 DataType dt,
24618 QRegister rd,
24619 QRegister rm,
24620 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024621 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024622 CheckIT(cond);
24623 if (operand.IsImmediate()) {
24624 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24625 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24626 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024627 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024628 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24629 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24630 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24631 uint32_t imm6 = dt.GetSize() - imm;
24632 EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
24633 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24634 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24635 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24636 AdvanceIT();
24637 return;
24638 }
24639 }
24640 } else {
24641 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24642 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24643 if (cond.Is(al)) {
24644 uint32_t imm6 = dt.GetSize() - imm;
24645 EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
24646 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24647 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24648 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24649 return;
24650 }
24651 }
24652 }
24653 }
24654 }
24655 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
24656}
24657
24658void Assembler::vsri(Condition cond,
24659 DataType dt,
24660 DRegister rd,
24661 DRegister rm,
24662 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024663 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024664 CheckIT(cond);
24665 if (operand.IsImmediate()) {
24666 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24667 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24668 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024669 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024670 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
24671 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24672 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24673 uint32_t imm6 = dt.GetSize() - imm;
24674 EmitT32_32(0xff800410U |
24675 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24676 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24677 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24678 AdvanceIT();
24679 return;
24680 }
24681 }
24682 } else {
24683 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
24684 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24685 if (cond.Is(al)) {
24686 uint32_t imm6 = dt.GetSize() - imm;
24687 EmitA32(0xf3800410U |
24688 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24689 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24690 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24691 return;
24692 }
24693 }
24694 }
24695 }
24696 }
24697 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
24698}
24699
24700void Assembler::vsri(Condition cond,
24701 DataType dt,
24702 QRegister rd,
24703 QRegister rm,
24704 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024705 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024706 CheckIT(cond);
24707 if (operand.IsImmediate()) {
24708 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24709 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24710 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024711 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024712 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
24713 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24714 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24715 uint32_t imm6 = dt.GetSize() - imm;
24716 EmitT32_32(0xff800450U |
24717 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24718 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24719 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24720 AdvanceIT();
24721 return;
24722 }
24723 }
24724 } else {
24725 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
24726 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24727 if (cond.Is(al)) {
24728 uint32_t imm6 = dt.GetSize() - imm;
24729 EmitA32(0xf3800450U |
24730 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24731 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24732 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24733 return;
24734 }
24735 }
24736 }
24737 }
24738 }
24739 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
24740}
24741
24742void Assembler::vst1(Condition cond,
24743 DataType dt,
24744 const NeonRegisterList& nreglist,
24745 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024746 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024747 CheckIT(cond);
24748 if (operand.IsImmediateZero()) {
24749 Register rn = operand.GetBaseRegister();
24750 Alignment align = operand.GetAlignment();
24751 Dt_size_6 encoded_dt(dt);
24752 Dt_size_7 encoded_dt_2(dt);
24753 Align_align_5 encoded_align_1(align, nreglist);
24754 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024756 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
24757 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24758 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24759 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
24760 ((!rn.IsPC()) || AllowUnpredictable())) {
24761 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24762 const DRegister& first = nreglist.GetFirstDRegister();
24763 uint32_t len_encoding;
24764 switch (nreglist.GetLength()) {
24765 default:
24766 VIXL_UNREACHABLE_OR_FALLTHROUGH();
24767 case 1:
24768 len_encoding = 0x7;
24769 break;
24770 case 2:
24771 len_encoding = 0xa;
24772 break;
24773 case 3:
24774 len_encoding = 0x6;
24775 break;
24776 case 4:
24777 len_encoding = 0x2;
24778 break;
24779 }
24780 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
24781 (encoded_align_1.GetEncodingValue() << 4) |
24782 first.Encode(22, 12) | (len_encoding << 8) |
24783 (rn.GetCode() << 16));
24784 AdvanceIT();
24785 return;
24786 }
24787 }
24788 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
24789 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24790 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24791 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
24792 ((!rn.IsPC()) || AllowUnpredictable())) {
24793 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24794 const DRegister& first = nreglist.GetFirstDRegister();
24795 uint32_t len_encoding;
24796 switch (nreglist.GetLength()) {
24797 default:
24798 VIXL_UNREACHABLE_OR_FALLTHROUGH();
24799 case 1:
24800 len_encoding = 0x7;
24801 break;
24802 case 2:
24803 len_encoding = 0xa;
24804 break;
24805 case 3:
24806 len_encoding = 0x6;
24807 break;
24808 case 4:
24809 len_encoding = 0x2;
24810 break;
24811 }
24812 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
24813 (encoded_align_1.GetEncodingValue() << 4) |
24814 first.Encode(22, 12) | (len_encoding << 8) |
24815 (rn.GetCode() << 16));
24816 AdvanceIT();
24817 return;
24818 }
24819 }
24820 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
24821 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24822 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
24823 encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24824 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24825 const DRegister& first = nreglist.GetFirstDRegister();
24826 EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
24827 (encoded_align_2.GetEncodingValue() << 4) |
24828 first.Encode(22, 12) | (rn.GetCode() << 16));
24829 AdvanceIT();
24830 return;
24831 }
24832 }
24833 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
24834 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24835 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
24836 encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24837 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24838 const DRegister& first = nreglist.GetFirstDRegister();
24839 EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
24840 (encoded_align_2.GetEncodingValue() << 4) |
24841 first.Encode(22, 12) | (rn.GetCode() << 16));
24842 AdvanceIT();
24843 return;
24844 }
24845 }
24846 } else {
24847 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
24848 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24849 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24850 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
24851 ((!rn.IsPC()) || AllowUnpredictable())) {
24852 if (cond.Is(al)) {
24853 const DRegister& first = nreglist.GetFirstDRegister();
24854 uint32_t len_encoding;
24855 switch (nreglist.GetLength()) {
24856 default:
24857 VIXL_UNREACHABLE_OR_FALLTHROUGH();
24858 case 1:
24859 len_encoding = 0x7;
24860 break;
24861 case 2:
24862 len_encoding = 0xa;
24863 break;
24864 case 3:
24865 len_encoding = 0x6;
24866 break;
24867 case 4:
24868 len_encoding = 0x2;
24869 break;
24870 }
24871 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
24872 (encoded_align_1.GetEncodingValue() << 4) |
24873 first.Encode(22, 12) | (len_encoding << 8) |
24874 (rn.GetCode() << 16));
24875 return;
24876 }
24877 }
24878 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
24879 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24880 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24881 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
24882 ((!rn.IsPC()) || AllowUnpredictable())) {
24883 if (cond.Is(al)) {
24884 const DRegister& first = nreglist.GetFirstDRegister();
24885 uint32_t len_encoding;
24886 switch (nreglist.GetLength()) {
24887 default:
24888 VIXL_UNREACHABLE_OR_FALLTHROUGH();
24889 case 1:
24890 len_encoding = 0x7;
24891 break;
24892 case 2:
24893 len_encoding = 0xa;
24894 break;
24895 case 3:
24896 len_encoding = 0x6;
24897 break;
24898 case 4:
24899 len_encoding = 0x2;
24900 break;
24901 }
24902 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
24903 (encoded_align_1.GetEncodingValue() << 4) |
24904 first.Encode(22, 12) | (len_encoding << 8) |
24905 (rn.GetCode() << 16));
24906 return;
24907 }
24908 }
24909 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
24910 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24911 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == Offset) &&
24912 encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24913 if (cond.Is(al)) {
24914 const DRegister& first = nreglist.GetFirstDRegister();
24915 EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
24916 (encoded_align_2.GetEncodingValue() << 4) |
24917 first.Encode(22, 12) | (rn.GetCode() << 16));
24918 return;
24919 }
24920 }
24921 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
24922 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24923 (nreglist.GetLength() == 1) && (operand.GetAddrMode() == PostIndex) &&
24924 encoded_align_2.IsValid() && ((!rn.IsPC()) || AllowUnpredictable())) {
24925 if (cond.Is(al)) {
24926 const DRegister& first = nreglist.GetFirstDRegister();
24927 EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
24928 (encoded_align_2.GetEncodingValue() << 4) |
24929 first.Encode(22, 12) | (rn.GetCode() << 16));
24930 return;
24931 }
24932 }
24933 }
24934 }
24935 if (operand.IsPlainRegister()) {
24936 Register rn = operand.GetBaseRegister();
24937 Alignment align = operand.GetAlignment();
24938 Register rm = operand.GetOffsetRegister();
24939 Dt_size_6 encoded_dt(dt);
24940 Dt_size_7 encoded_dt_2(dt);
24941 Align_align_5 encoded_align_1(align, nreglist);
24942 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024944 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
24945 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24946 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24947 !rm.IsPC() && !rm.IsSP()) {
24948 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24949 const DRegister& first = nreglist.GetFirstDRegister();
24950 uint32_t len_encoding;
24951 switch (nreglist.GetLength()) {
24952 default:
24953 VIXL_UNREACHABLE_OR_FALLTHROUGH();
24954 case 1:
24955 len_encoding = 0x7;
24956 break;
24957 case 2:
24958 len_encoding = 0xa;
24959 break;
24960 case 3:
24961 len_encoding = 0x6;
24962 break;
24963 case 4:
24964 len_encoding = 0x2;
24965 break;
24966 }
24967 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
24968 (encoded_align_1.GetEncodingValue() << 4) |
24969 first.Encode(22, 12) | (len_encoding << 8) |
24970 (rn.GetCode() << 16) | rm.GetCode());
24971 AdvanceIT();
24972 return;
24973 }
24974 }
24975 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
24976 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
24977 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
24978 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24979 const DRegister& first = nreglist.GetFirstDRegister();
24980 EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
24981 (encoded_align_2.GetEncodingValue() << 4) |
24982 first.Encode(22, 12) | (rn.GetCode() << 16) |
24983 rm.GetCode());
24984 AdvanceIT();
24985 return;
24986 }
24987 }
24988 } else {
24989 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
24990 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
24991 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
24992 !rm.IsPC() && !rm.IsSP()) {
24993 if (cond.Is(al)) {
24994 const DRegister& first = nreglist.GetFirstDRegister();
24995 uint32_t len_encoding;
24996 switch (nreglist.GetLength()) {
24997 default:
24998 VIXL_UNREACHABLE_OR_FALLTHROUGH();
24999 case 1:
25000 len_encoding = 0x7;
25001 break;
25002 case 2:
25003 len_encoding = 0xa;
25004 break;
25005 case 3:
25006 len_encoding = 0x6;
25007 break;
25008 case 4:
25009 len_encoding = 0x2;
25010 break;
25011 }
25012 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25013 (encoded_align_1.GetEncodingValue() << 4) |
25014 first.Encode(22, 12) | (len_encoding << 8) |
25015 (rn.GetCode() << 16) | rm.GetCode());
25016 return;
25017 }
25018 }
25019 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25020 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
25021 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP()) {
25022 if (cond.Is(al)) {
25023 const DRegister& first = nreglist.GetFirstDRegister();
25024 EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
25025 (encoded_align_2.GetEncodingValue() << 4) |
25026 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25027 return;
25028 }
25029 }
25030 }
25031 }
25032 Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
25033}
25034
25035void Assembler::vst2(Condition cond,
25036 DataType dt,
25037 const NeonRegisterList& nreglist,
25038 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025039 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025040 CheckIT(cond);
25041 if (operand.IsImmediateZero()) {
25042 Register rn = operand.GetBaseRegister();
25043 Alignment align = operand.GetAlignment();
25044 Dt_size_7 encoded_dt(dt);
25045 Align_align_2 encoded_align_1(align, nreglist);
25046 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025047 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025048 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25049 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25050 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25051 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25052 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25053 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25054 ((!rn.IsPC()) || AllowUnpredictable())) {
25055 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25056 const DRegister& first = nreglist.GetFirstDRegister();
25057 uint32_t len_encoding;
25058 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25059 len_encoding = 0x8;
25060 }
25061 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25062 len_encoding = 0x9;
25063 }
25064 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25065 len_encoding = 0x3;
25066 }
25067 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25068 (encoded_align_1.GetEncodingValue() << 4) |
25069 first.Encode(22, 12) | (len_encoding << 8) |
25070 (rn.GetCode() << 16));
25071 AdvanceIT();
25072 return;
25073 }
25074 }
25075 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25076 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25077 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25078 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25079 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25080 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25081 ((!rn.IsPC()) || AllowUnpredictable())) {
25082 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25083 const DRegister& first = nreglist.GetFirstDRegister();
25084 uint32_t len_encoding;
25085 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25086 len_encoding = 0x8;
25087 }
25088 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25089 len_encoding = 0x9;
25090 }
25091 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25092 len_encoding = 0x3;
25093 }
25094 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25095 (encoded_align_1.GetEncodingValue() << 4) |
25096 first.Encode(22, 12) | (len_encoding << 8) |
25097 (rn.GetCode() << 16));
25098 AdvanceIT();
25099 return;
25100 }
25101 }
25102 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25103 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25104 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25105 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25106 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25107 ((!rn.IsPC()) || AllowUnpredictable())) {
25108 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25109 const DRegister& first = nreglist.GetFirstDRegister();
25110 EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
25111 (encoded_align_2.GetEncodingValue() << 4) |
25112 first.Encode(22, 12) | (rn.GetCode() << 16));
25113 AdvanceIT();
25114 return;
25115 }
25116 }
25117 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25118 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25119 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25120 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25121 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25122 ((!rn.IsPC()) || AllowUnpredictable())) {
25123 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25124 const DRegister& first = nreglist.GetFirstDRegister();
25125 EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
25126 (encoded_align_2.GetEncodingValue() << 4) |
25127 first.Encode(22, 12) | (rn.GetCode() << 16));
25128 AdvanceIT();
25129 return;
25130 }
25131 }
25132 } else {
25133 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25134 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25135 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25136 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25137 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25138 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25139 ((!rn.IsPC()) || AllowUnpredictable())) {
25140 if (cond.Is(al)) {
25141 const DRegister& first = nreglist.GetFirstDRegister();
25142 uint32_t len_encoding;
25143 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25144 len_encoding = 0x8;
25145 }
25146 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25147 len_encoding = 0x9;
25148 }
25149 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25150 len_encoding = 0x3;
25151 }
25152 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25153 (encoded_align_1.GetEncodingValue() << 4) |
25154 first.Encode(22, 12) | (len_encoding << 8) |
25155 (rn.GetCode() << 16));
25156 return;
25157 }
25158 }
25159 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25160 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25161 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25162 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25163 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25164 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25165 ((!rn.IsPC()) || AllowUnpredictable())) {
25166 if (cond.Is(al)) {
25167 const DRegister& first = nreglist.GetFirstDRegister();
25168 uint32_t len_encoding;
25169 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25170 len_encoding = 0x8;
25171 }
25172 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25173 len_encoding = 0x9;
25174 }
25175 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25176 len_encoding = 0x3;
25177 }
25178 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25179 (encoded_align_1.GetEncodingValue() << 4) |
25180 first.Encode(22, 12) | (len_encoding << 8) |
25181 (rn.GetCode() << 16));
25182 return;
25183 }
25184 }
25185 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25186 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25187 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25188 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25189 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25190 ((!rn.IsPC()) || AllowUnpredictable())) {
25191 if (cond.Is(al)) {
25192 const DRegister& first = nreglist.GetFirstDRegister();
25193 EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
25194 (encoded_align_2.GetEncodingValue() << 4) |
25195 first.Encode(22, 12) | (rn.GetCode() << 16));
25196 return;
25197 }
25198 }
25199 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25200 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25201 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25202 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25203 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25204 ((!rn.IsPC()) || AllowUnpredictable())) {
25205 if (cond.Is(al)) {
25206 const DRegister& first = nreglist.GetFirstDRegister();
25207 EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
25208 (encoded_align_2.GetEncodingValue() << 4) |
25209 first.Encode(22, 12) | (rn.GetCode() << 16));
25210 return;
25211 }
25212 }
25213 }
25214 }
25215 if (operand.IsPlainRegister()) {
25216 Register rn = operand.GetBaseRegister();
25217 Alignment align = operand.GetAlignment();
25218 Register rm = operand.GetOffsetRegister();
25219 Dt_size_7 encoded_dt(dt);
25220 Align_align_2 encoded_align_1(align, nreglist);
25221 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025222 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025223 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25224 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25225 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25226 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25227 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25228 !rm.IsPC() && !rm.IsSP()) {
25229 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25230 const DRegister& first = nreglist.GetFirstDRegister();
25231 uint32_t len_encoding;
25232 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25233 len_encoding = 0x8;
25234 }
25235 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25236 len_encoding = 0x9;
25237 }
25238 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25239 len_encoding = 0x3;
25240 }
25241 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25242 (encoded_align_1.GetEncodingValue() << 4) |
25243 first.Encode(22, 12) | (len_encoding << 8) |
25244 (rn.GetCode() << 16) | rm.GetCode());
25245 AdvanceIT();
25246 return;
25247 }
25248 }
25249 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25250 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25251 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25252 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25253 !rm.IsPC() && !rm.IsSP()) {
25254 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25255 const DRegister& first = nreglist.GetFirstDRegister();
25256 EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
25257 (encoded_align_2.GetEncodingValue() << 4) |
25258 first.Encode(22, 12) | (rn.GetCode() << 16) |
25259 rm.GetCode());
25260 AdvanceIT();
25261 return;
25262 }
25263 }
25264 } else {
25265 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25266 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25267 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25268 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
25269 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
25270 !rm.IsPC() && !rm.IsSP()) {
25271 if (cond.Is(al)) {
25272 const DRegister& first = nreglist.GetFirstDRegister();
25273 uint32_t len_encoding;
25274 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
25275 len_encoding = 0x8;
25276 }
25277 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
25278 len_encoding = 0x9;
25279 }
25280 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
25281 len_encoding = 0x3;
25282 }
25283 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25284 (encoded_align_1.GetEncodingValue() << 4) |
25285 first.Encode(22, 12) | (len_encoding << 8) |
25286 (rn.GetCode() << 16) | rm.GetCode());
25287 return;
25288 }
25289 }
25290 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25291 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25292 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
25293 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
25294 !rm.IsPC() && !rm.IsSP()) {
25295 if (cond.Is(al)) {
25296 const DRegister& first = nreglist.GetFirstDRegister();
25297 EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
25298 (encoded_align_2.GetEncodingValue() << 4) |
25299 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25300 return;
25301 }
25302 }
25303 }
25304 }
25305 Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
25306}
25307
25308void Assembler::vst3(Condition cond,
25309 DataType dt,
25310 const NeonRegisterList& nreglist,
25311 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025312 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025313 CheckIT(cond);
25314 if (operand.IsImmediateZero()) {
25315 Register rn = operand.GetBaseRegister();
25316 Alignment align = operand.GetAlignment();
25317 Dt_size_7 encoded_dt(dt);
25318 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025320 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25321 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25322 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25323 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25324 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25325 ((!rn.IsPC()) || AllowUnpredictable())) {
25326 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25327 const DRegister& first = nreglist.GetFirstDRegister();
25328 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25329 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25330 (encoded_align_1.GetEncodingValue() << 4) |
25331 first.Encode(22, 12) | (len_encoding << 8) |
25332 (rn.GetCode() << 16));
25333 AdvanceIT();
25334 return;
25335 }
25336 }
25337 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25338 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25339 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25340 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25341 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25342 ((!rn.IsPC()) || AllowUnpredictable())) {
25343 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25344 const DRegister& first = nreglist.GetFirstDRegister();
25345 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25346 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25347 (encoded_align_1.GetEncodingValue() << 4) |
25348 first.Encode(22, 12) | (len_encoding << 8) |
25349 (rn.GetCode() << 16));
25350 AdvanceIT();
25351 return;
25352 }
25353 }
25354 } else {
25355 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25356 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25357 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25358 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25359 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25360 ((!rn.IsPC()) || AllowUnpredictable())) {
25361 if (cond.Is(al)) {
25362 const DRegister& first = nreglist.GetFirstDRegister();
25363 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25364 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25365 (encoded_align_1.GetEncodingValue() << 4) |
25366 first.Encode(22, 12) | (len_encoding << 8) |
25367 (rn.GetCode() << 16));
25368 return;
25369 }
25370 }
25371 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25372 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25373 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25374 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25375 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25376 ((!rn.IsPC()) || AllowUnpredictable())) {
25377 if (cond.Is(al)) {
25378 const DRegister& first = nreglist.GetFirstDRegister();
25379 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25380 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25381 (encoded_align_1.GetEncodingValue() << 4) |
25382 first.Encode(22, 12) | (len_encoding << 8) |
25383 (rn.GetCode() << 16));
25384 return;
25385 }
25386 }
25387 }
25388 }
25389 if (operand.IsPlainRegister()) {
25390 Register rn = operand.GetBaseRegister();
25391 Alignment align = operand.GetAlignment();
25392 Register rm = operand.GetOffsetRegister();
25393 Dt_size_7 encoded_dt(dt);
25394 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025396 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25397 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25398 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25399 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25400 !rm.IsPC() && !rm.IsSP()) {
25401 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25402 const DRegister& first = nreglist.GetFirstDRegister();
25403 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25404 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25405 (encoded_align_1.GetEncodingValue() << 4) |
25406 first.Encode(22, 12) | (len_encoding << 8) |
25407 (rn.GetCode() << 16) | rm.GetCode());
25408 AdvanceIT();
25409 return;
25410 }
25411 }
25412 } else {
25413 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25414 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25415 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25416 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25417 !rm.IsPC() && !rm.IsSP()) {
25418 if (cond.Is(al)) {
25419 const DRegister& first = nreglist.GetFirstDRegister();
25420 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
25421 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25422 (encoded_align_1.GetEncodingValue() << 4) |
25423 first.Encode(22, 12) | (len_encoding << 8) |
25424 (rn.GetCode() << 16) | rm.GetCode());
25425 return;
25426 }
25427 }
25428 }
25429 }
25430 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
25431}
25432
25433void Assembler::vst3(Condition cond,
25434 DataType dt,
25435 const NeonRegisterList& nreglist,
25436 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025437 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025438 CheckIT(cond);
25439 if (operand.IsImmediateZero()) {
25440 Register rn = operand.GetBaseRegister();
25441 Dt_size_7 encoded_dt(dt);
25442 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025443 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025444 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
25445 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25446 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25447 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25448 (operand.GetAddrMode() == Offset) &&
25449 ((!rn.IsPC()) || AllowUnpredictable())) {
25450 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25451 const DRegister& first = nreglist.GetFirstDRegister();
25452 EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
25453 (encoded_align_1.GetEncodingValue() << 4) |
25454 first.Encode(22, 12) | (rn.GetCode() << 16));
25455 AdvanceIT();
25456 return;
25457 }
25458 }
25459 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
25460 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25461 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25462 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25463 (operand.GetAddrMode() == PreIndex) &&
25464 ((!rn.IsPC()) || AllowUnpredictable())) {
25465 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25466 const DRegister& first = nreglist.GetFirstDRegister();
25467 EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
25468 (encoded_align_1.GetEncodingValue() << 4) |
25469 first.Encode(22, 12) | (rn.GetCode() << 16));
25470 AdvanceIT();
25471 return;
25472 }
25473 }
25474 } else {
25475 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
25476 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25477 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25478 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25479 (operand.GetAddrMode() == Offset) &&
25480 ((!rn.IsPC()) || AllowUnpredictable())) {
25481 if (cond.Is(al)) {
25482 const DRegister& first = nreglist.GetFirstDRegister();
25483 EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
25484 (encoded_align_1.GetEncodingValue() << 4) |
25485 first.Encode(22, 12) | (rn.GetCode() << 16));
25486 return;
25487 }
25488 }
25489 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
25490 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25491 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25492 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25493 (operand.GetAddrMode() == PreIndex) &&
25494 ((!rn.IsPC()) || AllowUnpredictable())) {
25495 if (cond.Is(al)) {
25496 const DRegister& first = nreglist.GetFirstDRegister();
25497 EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
25498 (encoded_align_1.GetEncodingValue() << 4) |
25499 first.Encode(22, 12) | (rn.GetCode() << 16));
25500 return;
25501 }
25502 }
25503 }
25504 }
25505 if (operand.IsPlainRegister()) {
25506 Register rn = operand.GetBaseRegister();
25507 Sign sign = operand.GetSign();
25508 Register rm = operand.GetOffsetRegister();
25509 Dt_size_7 encoded_dt(dt);
25510 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025511 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025512 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
25513 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25514 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25515 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25516 sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
25517 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25518 const DRegister& first = nreglist.GetFirstDRegister();
25519 EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
25520 (encoded_align_1.GetEncodingValue() << 4) |
25521 first.Encode(22, 12) | (rn.GetCode() << 16) |
25522 rm.GetCode());
25523 AdvanceIT();
25524 return;
25525 }
25526 }
25527 } else {
25528 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
25529 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25530 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
25531 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
25532 sign.IsPlus() && (operand.GetAddrMode() == PostIndex)) {
25533 if (cond.Is(al)) {
25534 const DRegister& first = nreglist.GetFirstDRegister();
25535 EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
25536 (encoded_align_1.GetEncodingValue() << 4) |
25537 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25538 return;
25539 }
25540 }
25541 }
25542 }
25543 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
25544}
25545
25546void Assembler::vst4(Condition cond,
25547 DataType dt,
25548 const NeonRegisterList& nreglist,
25549 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025550 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025551 CheckIT(cond);
25552 if (operand.IsImmediateZero()) {
25553 Register rn = operand.GetBaseRegister();
25554 Alignment align = operand.GetAlignment();
25555 Dt_size_7 encoded_dt(dt);
25556 Align_align_4 encoded_align_1(align);
25557 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025558 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025559 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25560 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25561 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25562 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25563 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25564 ((!rn.IsPC()) || AllowUnpredictable())) {
25565 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25566 const DRegister& first = nreglist.GetFirstDRegister();
25567 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25568 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25569 (encoded_align_1.GetEncodingValue() << 4) |
25570 first.Encode(22, 12) | (len_encoding << 8) |
25571 (rn.GetCode() << 16));
25572 AdvanceIT();
25573 return;
25574 }
25575 }
25576 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25577 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25578 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25579 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25580 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25581 ((!rn.IsPC()) || AllowUnpredictable())) {
25582 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25583 const DRegister& first = nreglist.GetFirstDRegister();
25584 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25585 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
25586 (encoded_align_1.GetEncodingValue() << 4) |
25587 first.Encode(22, 12) | (len_encoding << 8) |
25588 (rn.GetCode() << 16));
25589 AdvanceIT();
25590 return;
25591 }
25592 }
25593 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25594 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25595 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25596 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25597 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25598 ((!rn.IsPC()) || AllowUnpredictable())) {
25599 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25600 const DRegister& first = nreglist.GetFirstDRegister();
25601 EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
25602 (encoded_align_2.GetEncodingValue() << 4) |
25603 first.Encode(22, 12) | (rn.GetCode() << 16));
25604 AdvanceIT();
25605 return;
25606 }
25607 }
25608 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25609 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25610 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25611 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25612 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25613 ((!rn.IsPC()) || AllowUnpredictable())) {
25614 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25615 const DRegister& first = nreglist.GetFirstDRegister();
25616 EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
25617 (encoded_align_2.GetEncodingValue() << 4) |
25618 first.Encode(22, 12) | (rn.GetCode() << 16));
25619 AdvanceIT();
25620 return;
25621 }
25622 }
25623 } else {
25624 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25625 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25626 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25627 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25628 (operand.GetAddrMode() == Offset) && encoded_align_1.IsValid() &&
25629 ((!rn.IsPC()) || AllowUnpredictable())) {
25630 if (cond.Is(al)) {
25631 const DRegister& first = nreglist.GetFirstDRegister();
25632 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25633 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
25634 (encoded_align_1.GetEncodingValue() << 4) |
25635 first.Encode(22, 12) | (len_encoding << 8) |
25636 (rn.GetCode() << 16));
25637 return;
25638 }
25639 }
25640 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25641 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25642 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25643 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25644 (operand.GetAddrMode() == PostIndex) && encoded_align_1.IsValid() &&
25645 ((!rn.IsPC()) || AllowUnpredictable())) {
25646 if (cond.Is(al)) {
25647 const DRegister& first = nreglist.GetFirstDRegister();
25648 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25649 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
25650 (encoded_align_1.GetEncodingValue() << 4) |
25651 first.Encode(22, 12) | (len_encoding << 8) |
25652 (rn.GetCode() << 16));
25653 return;
25654 }
25655 }
25656 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
25657 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25658 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25659 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25660 (operand.GetAddrMode() == Offset) && encoded_align_2.IsValid() &&
25661 ((!rn.IsPC()) || AllowUnpredictable())) {
25662 if (cond.Is(al)) {
25663 const DRegister& first = nreglist.GetFirstDRegister();
25664 EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
25665 (encoded_align_2.GetEncodingValue() << 4) |
25666 first.Encode(22, 12) | (rn.GetCode() << 16));
25667 return;
25668 }
25669 }
25670 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
25671 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25672 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25673 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25674 (operand.GetAddrMode() == PostIndex) && encoded_align_2.IsValid() &&
25675 ((!rn.IsPC()) || AllowUnpredictable())) {
25676 if (cond.Is(al)) {
25677 const DRegister& first = nreglist.GetFirstDRegister();
25678 EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
25679 (encoded_align_2.GetEncodingValue() << 4) |
25680 first.Encode(22, 12) | (rn.GetCode() << 16));
25681 return;
25682 }
25683 }
25684 }
25685 }
25686 if (operand.IsPlainRegister()) {
25687 Register rn = operand.GetBaseRegister();
25688 Alignment align = operand.GetAlignment();
25689 Register rm = operand.GetOffsetRegister();
25690 Dt_size_7 encoded_dt(dt);
25691 Align_align_4 encoded_align_1(align);
25692 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025693 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025694 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25695 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25696 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25697 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25698 !rm.IsPC() && !rm.IsSP()) {
25699 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25700 const DRegister& first = nreglist.GetFirstDRegister();
25701 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25702 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
25703 (encoded_align_1.GetEncodingValue() << 4) |
25704 first.Encode(22, 12) | (len_encoding << 8) |
25705 (rn.GetCode() << 16) | rm.GetCode());
25706 AdvanceIT();
25707 return;
25708 }
25709 }
25710 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
25711 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25712 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25713 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25714 !rm.IsPC() && !rm.IsSP()) {
25715 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25716 const DRegister& first = nreglist.GetFirstDRegister();
25717 EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
25718 (encoded_align_2.GetEncodingValue() << 4) |
25719 first.Encode(22, 12) | (rn.GetCode() << 16) |
25720 rm.GetCode());
25721 AdvanceIT();
25722 return;
25723 }
25724 }
25725 } else {
25726 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25727 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25728 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25729 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25730 !rm.IsPC() && !rm.IsSP()) {
25731 if (cond.Is(al)) {
25732 const DRegister& first = nreglist.GetFirstDRegister();
25733 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
25734 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
25735 (encoded_align_1.GetEncodingValue() << 4) |
25736 first.Encode(22, 12) | (len_encoding << 8) |
25737 (rn.GetCode() << 16) | rm.GetCode());
25738 return;
25739 }
25740 }
25741 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
25742 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
25743 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
25744 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
25745 !rm.IsPC() && !rm.IsSP()) {
25746 if (cond.Is(al)) {
25747 const DRegister& first = nreglist.GetFirstDRegister();
25748 EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
25749 (encoded_align_2.GetEncodingValue() << 4) |
25750 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
25751 return;
25752 }
25753 }
25754 }
25755 }
25756 Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
25757}
25758
25759void Assembler::vstm(Condition cond,
25760 DataType dt,
25761 Register rn,
25762 WriteBack write_back,
25763 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025764 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025765 CheckIT(cond);
25766 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025767 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025768 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
25769 if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25770 const DRegister& dreg = dreglist.GetFirstDRegister();
25771 unsigned len = dreglist.GetLength() * 2;
25772 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
25773 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25774 (len & 0xff));
25775 AdvanceIT();
25776 return;
25777 }
25778 } else {
25779 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
25780 if (cond.IsNotNever() &&
25781 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25782 const DRegister& dreg = dreglist.GetFirstDRegister();
25783 unsigned len = dreglist.GetLength() * 2;
25784 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25785 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25786 (len & 0xff));
25787 return;
25788 }
25789 }
25790 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
25791}
25792
25793void Assembler::vstm(Condition cond,
25794 DataType dt,
25795 Register rn,
25796 WriteBack write_back,
25797 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025798 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025799 CheckIT(cond);
25800 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025801 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025802 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
25803 const SRegister& sreg = sreglist.GetFirstSRegister();
25804 unsigned len = sreglist.GetLength();
25805 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
25806 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25807 (len & 0xff));
25808 AdvanceIT();
25809 return;
25810 } else {
25811 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
25812 if (cond.IsNotNever()) {
25813 const SRegister& sreg = sreglist.GetFirstSRegister();
25814 unsigned len = sreglist.GetLength();
25815 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25816 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25817 (len & 0xff));
25818 return;
25819 }
25820 }
25821 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
25822}
25823
25824void Assembler::vstmdb(Condition cond,
25825 DataType dt,
25826 Register rn,
25827 WriteBack write_back,
25828 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025829 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025830 CheckIT(cond);
25831 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025833 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
25834 if (write_back.DoesWriteBack() &&
25835 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25836 const DRegister& dreg = dreglist.GetFirstDRegister();
25837 unsigned len = dreglist.GetLength() * 2;
25838 EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
25839 (len & 0xff));
25840 AdvanceIT();
25841 return;
25842 }
25843 } else {
25844 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
25845 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
25846 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25847 const DRegister& dreg = dreglist.GetFirstDRegister();
25848 unsigned len = dreglist.GetLength() * 2;
25849 EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25850 dreg.Encode(22, 12) | (len & 0xff));
25851 return;
25852 }
25853 }
25854 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
25855}
25856
25857void Assembler::vstmdb(Condition cond,
25858 DataType dt,
25859 Register rn,
25860 WriteBack write_back,
25861 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025863 CheckIT(cond);
25864 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025865 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025866 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
25867 if (write_back.DoesWriteBack()) {
25868 const SRegister& sreg = sreglist.GetFirstSRegister();
25869 unsigned len = sreglist.GetLength();
25870 EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
25871 (len & 0xff));
25872 AdvanceIT();
25873 return;
25874 }
25875 } else {
25876 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
25877 if (write_back.DoesWriteBack() && cond.IsNotNever()) {
25878 const SRegister& sreg = sreglist.GetFirstSRegister();
25879 unsigned len = sreglist.GetLength();
25880 EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25881 sreg.Encode(22, 12) | (len & 0xff));
25882 return;
25883 }
25884 }
25885 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
25886}
25887
25888void Assembler::vstmia(Condition cond,
25889 DataType dt,
25890 Register rn,
25891 WriteBack write_back,
25892 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025893 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025894 CheckIT(cond);
25895 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025896 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025897 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
25898 if ((((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25899 const DRegister& dreg = dreglist.GetFirstDRegister();
25900 unsigned len = dreglist.GetLength() * 2;
25901 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
25902 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25903 (len & 0xff));
25904 AdvanceIT();
25905 return;
25906 }
25907 } else {
25908 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
25909 if (cond.IsNotNever() &&
25910 (((dreglist.GetLength() <= 16)) || AllowUnpredictable())) {
25911 const DRegister& dreg = dreglist.GetFirstDRegister();
25912 unsigned len = dreglist.GetLength() * 2;
25913 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25914 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
25915 (len & 0xff));
25916 return;
25917 }
25918 }
25919 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
25920}
25921
25922void Assembler::vstmia(Condition cond,
25923 DataType dt,
25924 Register rn,
25925 WriteBack write_back,
25926 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025927 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025928 CheckIT(cond);
25929 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025930 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025931 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
25932 const SRegister& sreg = sreglist.GetFirstSRegister();
25933 unsigned len = sreglist.GetLength();
25934 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
25935 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25936 (len & 0xff));
25937 AdvanceIT();
25938 return;
25939 } else {
25940 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
25941 if (cond.IsNotNever()) {
25942 const SRegister& sreg = sreglist.GetFirstSRegister();
25943 unsigned len = sreglist.GetLength();
25944 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
25945 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
25946 (len & 0xff));
25947 return;
25948 }
25949 }
25950 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
25951}
25952
25953void Assembler::vstr(Condition cond,
25954 DataType dt,
25955 DRegister rd,
25956 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025957 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025958 CheckIT(cond);
25959 if (operand.IsImmediate()) {
25960 Register rn = operand.GetBaseRegister();
25961 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025962 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025963 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
25964 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
25965 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset)) {
25966 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25967 uint32_t offset_ = abs(offset) >> 2;
25968 EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
25969 offset_ | (sign << 23));
25970 AdvanceIT();
25971 return;
25972 }
25973 } else {
25974 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
25975 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
25976 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
25977 cond.IsNotNever()) {
25978 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
25979 uint32_t offset_ = abs(offset) >> 2;
25980 EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25981 (rn.GetCode() << 16) | offset_ | (sign << 23));
25982 return;
25983 }
25984 }
25985 }
25986 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
25987}
25988
25989void Assembler::vstr(Condition cond,
25990 DataType dt,
25991 SRegister rd,
25992 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025993 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025994 CheckIT(cond);
25995 if (operand.IsImmediate()) {
25996 Register rn = operand.GetBaseRegister();
25997 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025998 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025999 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
26000 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
26001 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset)) {
26002 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
26003 uint32_t offset_ = abs(offset) >> 2;
26004 EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
26005 offset_ | (sign << 23));
26006 AdvanceIT();
26007 return;
26008 }
26009 } else {
26010 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
26011 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
26012 ((offset % 4) == 0) && (operand.GetAddrMode() == Offset) &&
26013 cond.IsNotNever()) {
26014 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
26015 uint32_t offset_ = abs(offset) >> 2;
26016 EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26017 (rn.GetCode() << 16) | offset_ | (sign << 23));
26018 return;
26019 }
26020 }
26021 }
26022 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
26023}
26024
26025void Assembler::vsub(
26026 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026027 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026028 CheckIT(cond);
26029 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026030 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026031 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
26032 if (dt.Is(F32)) {
26033 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26034 EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26035 rm.Encode(5, 0));
26036 AdvanceIT();
26037 return;
26038 }
26039 }
26040 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
26041 if (dt.Is(F64)) {
26042 EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26043 rm.Encode(5, 0));
26044 AdvanceIT();
26045 return;
26046 }
26047 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
26048 if (encoded_dt.IsValid()) {
26049 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26050 EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
26051 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26052 AdvanceIT();
26053 return;
26054 }
26055 }
26056 } else {
26057 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
26058 if (dt.Is(F32)) {
26059 if (cond.Is(al)) {
26060 EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26061 rm.Encode(5, 0));
26062 return;
26063 }
26064 }
26065 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
26066 if (dt.Is(F64) && cond.IsNotNever()) {
26067 EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26068 rn.Encode(7, 16) | rm.Encode(5, 0));
26069 return;
26070 }
26071 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
26072 if (encoded_dt.IsValid()) {
26073 if (cond.Is(al)) {
26074 EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
26075 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26076 return;
26077 }
26078 }
26079 }
26080 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26081}
26082
26083void Assembler::vsub(
26084 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026085 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026086 CheckIT(cond);
26087 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026088 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026089 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
26090 if (dt.Is(F32)) {
26091 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26092 EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26093 rm.Encode(5, 0));
26094 AdvanceIT();
26095 return;
26096 }
26097 }
26098 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
26099 if (encoded_dt.IsValid()) {
26100 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26101 EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
26102 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26103 AdvanceIT();
26104 return;
26105 }
26106 }
26107 } else {
26108 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
26109 if (dt.Is(F32)) {
26110 if (cond.Is(al)) {
26111 EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26112 rm.Encode(5, 0));
26113 return;
26114 }
26115 }
26116 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
26117 if (encoded_dt.IsValid()) {
26118 if (cond.Is(al)) {
26119 EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
26120 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26121 return;
26122 }
26123 }
26124 }
26125 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26126}
26127
26128void Assembler::vsub(
26129 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026130 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026131 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026132 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026133 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
26134 if (dt.Is(F32)) {
26135 EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
26136 rm.Encode(5, 0));
26137 AdvanceIT();
26138 return;
26139 }
26140 } else {
26141 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
26142 if (dt.Is(F32) && cond.IsNotNever()) {
26143 EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
26144 rn.Encode(7, 16) | rm.Encode(5, 0));
26145 return;
26146 }
26147 }
26148 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
26149}
26150
26151void Assembler::vsubhn(
26152 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026153 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026154 CheckIT(cond);
26155 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026156 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026157 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
26158 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
26159 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26160 EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
26161 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26162 AdvanceIT();
26163 return;
26164 }
26165 }
26166 } else {
26167 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
26168 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
26169 if (cond.Is(al)) {
26170 EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
26171 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26172 return;
26173 }
26174 }
26175 }
26176 Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
26177}
26178
26179void Assembler::vsubl(
26180 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026181 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026182 CheckIT(cond);
26183 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026184 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026185 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
26186 if (encoded_dt.IsValid()) {
26187 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26188 EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26189 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
26190 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26191 AdvanceIT();
26192 return;
26193 }
26194 }
26195 } else {
26196 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
26197 if (encoded_dt.IsValid()) {
26198 if (cond.Is(al)) {
26199 EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26200 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
26201 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26202 return;
26203 }
26204 }
26205 }
26206 Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
26207}
26208
26209void Assembler::vsubw(
26210 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026211 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026212 CheckIT(cond);
26213 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026214 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026215 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
26216 if (encoded_dt.IsValid()) {
26217 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26218 EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26219 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
26220 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26221 AdvanceIT();
26222 return;
26223 }
26224 }
26225 } else {
26226 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
26227 if (encoded_dt.IsValid()) {
26228 if (cond.Is(al)) {
26229 EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
26230 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
26231 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26232 return;
26233 }
26234 }
26235 }
26236 Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
26237}
26238
26239void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026240 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026241 CheckIT(cond);
26242 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026243 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026244 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
26245 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26246 EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
26247 AdvanceIT();
26248 return;
26249 }
26250 } else {
26251 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
26252 if (cond.Is(al)) {
26253 EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
26254 return;
26255 }
26256 }
26257 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
26258}
26259
26260void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026261 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026262 CheckIT(cond);
26263 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026264 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026265 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
26266 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26267 EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
26268 AdvanceIT();
26269 return;
26270 }
26271 } else {
26272 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
26273 if (cond.Is(al)) {
26274 EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
26275 return;
26276 }
26277 }
26278 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
26279}
26280
26281void Assembler::vtbl(Condition cond,
26282 DataType dt,
26283 DRegister rd,
26284 const NeonRegisterList& nreglist,
26285 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026286 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026287 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026288 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026289 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
26290 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26291 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26292 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26293 const DRegister& first = nreglist.GetFirstDRegister();
26294 uint32_t len_encoding = nreglist.GetLength() - 1;
26295 EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
26296 (len_encoding << 8) | rm.Encode(5, 0));
26297 AdvanceIT();
26298 return;
26299 }
26300 }
26301 } else {
26302 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
26303 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26304 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26305 if (cond.Is(al)) {
26306 const DRegister& first = nreglist.GetFirstDRegister();
26307 uint32_t len_encoding = nreglist.GetLength() - 1;
26308 EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
26309 (len_encoding << 8) | rm.Encode(5, 0));
26310 return;
26311 }
26312 }
26313 }
26314 Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
26315}
26316
26317void Assembler::vtbx(Condition cond,
26318 DataType dt,
26319 DRegister rd,
26320 const NeonRegisterList& nreglist,
26321 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026322 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026323 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026324 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026325 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
26326 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26327 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26328 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26329 const DRegister& first = nreglist.GetFirstDRegister();
26330 uint32_t len_encoding = nreglist.GetLength() - 1;
26331 EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
26332 (len_encoding << 8) | rm.Encode(5, 0));
26333 AdvanceIT();
26334 return;
26335 }
26336 }
26337 } else {
26338 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
26339 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
26340 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
26341 if (cond.Is(al)) {
26342 const DRegister& first = nreglist.GetFirstDRegister();
26343 uint32_t len_encoding = nreglist.GetLength() - 1;
26344 EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
26345 (len_encoding << 8) | rm.Encode(5, 0));
26346 return;
26347 }
26348 }
26349 }
26350 Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
26351}
26352
26353void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026354 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026355 CheckIT(cond);
26356 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026357 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026358 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26359 if (encoded_dt.IsValid()) {
26360 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26361 EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
26362 rd.Encode(22, 12) | rm.Encode(5, 0));
26363 AdvanceIT();
26364 return;
26365 }
26366 }
26367 } else {
26368 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26369 if (encoded_dt.IsValid()) {
26370 if (cond.Is(al)) {
26371 EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
26372 rd.Encode(22, 12) | rm.Encode(5, 0));
26373 return;
26374 }
26375 }
26376 }
26377 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
26378}
26379
26380void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026381 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026382 CheckIT(cond);
26383 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026384 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026385 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26386 if (encoded_dt.IsValid()) {
26387 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26388 EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
26389 rd.Encode(22, 12) | rm.Encode(5, 0));
26390 AdvanceIT();
26391 return;
26392 }
26393 }
26394 } else {
26395 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26396 if (encoded_dt.IsValid()) {
26397 if (cond.Is(al)) {
26398 EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
26399 rd.Encode(22, 12) | rm.Encode(5, 0));
26400 return;
26401 }
26402 }
26403 }
26404 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
26405}
26406
26407void Assembler::vtst(
26408 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026409 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026410 CheckIT(cond);
26411 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026412 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026413 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
26414 if (encoded_dt.IsValid()) {
26415 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26416 EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
26417 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26418 AdvanceIT();
26419 return;
26420 }
26421 }
26422 } else {
26423 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
26424 if (encoded_dt.IsValid()) {
26425 if (cond.Is(al)) {
26426 EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
26427 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26428 return;
26429 }
26430 }
26431 }
26432 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
26433}
26434
26435void Assembler::vtst(
26436 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026437 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026438 CheckIT(cond);
26439 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026440 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026441 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
26442 if (encoded_dt.IsValid()) {
26443 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26444 EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
26445 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26446 AdvanceIT();
26447 return;
26448 }
26449 }
26450 } else {
26451 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
26452 if (encoded_dt.IsValid()) {
26453 if (cond.Is(al)) {
26454 EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
26455 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
26456 return;
26457 }
26458 }
26459 }
26460 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
26461}
26462
26463void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026464 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026465 CheckIT(cond);
26466 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026467 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026468 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26469 if (encoded_dt.IsValid()) {
26470 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26471 EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
26472 rd.Encode(22, 12) | rm.Encode(5, 0));
26473 AdvanceIT();
26474 return;
26475 }
26476 }
26477 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
26478 if (dt.Is(Untyped32)) {
26479 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26480 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26481 AdvanceIT();
26482 return;
26483 }
26484 }
26485 } else {
26486 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26487 if (encoded_dt.IsValid()) {
26488 if (cond.Is(al)) {
26489 EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
26490 rd.Encode(22, 12) | rm.Encode(5, 0));
26491 return;
26492 }
26493 }
26494 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
26495 if (dt.Is(Untyped32)) {
26496 if (cond.Is(al)) {
26497 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26498 return;
26499 }
26500 }
26501 }
26502 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
26503}
26504
26505void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026506 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026507 CheckIT(cond);
26508 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026509 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026510 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26511 if (encoded_dt.IsValid()) {
26512 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26513 EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
26514 rd.Encode(22, 12) | rm.Encode(5, 0));
26515 AdvanceIT();
26516 return;
26517 }
26518 }
26519 } else {
26520 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26521 if (encoded_dt.IsValid()) {
26522 if (cond.Is(al)) {
26523 EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
26524 rd.Encode(22, 12) | rm.Encode(5, 0));
26525 return;
26526 }
26527 }
26528 }
26529 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
26530}
26531
26532void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026534 CheckIT(cond);
26535 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026536 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026537 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
26538 if (encoded_dt.IsValid()) {
26539 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26540 EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
26541 rd.Encode(22, 12) | rm.Encode(5, 0));
26542 AdvanceIT();
26543 return;
26544 }
26545 }
26546 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
26547 if (dt.Is(Untyped32)) {
26548 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26549 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26550 AdvanceIT();
26551 return;
26552 }
26553 }
26554 } else {
26555 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
26556 if (encoded_dt.IsValid()) {
26557 if (cond.Is(al)) {
26558 EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
26559 rd.Encode(22, 12) | rm.Encode(5, 0));
26560 return;
26561 }
26562 }
26563 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
26564 if (dt.Is(Untyped32)) {
26565 if (cond.Is(al)) {
26566 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
26567 return;
26568 }
26569 }
26570 }
26571 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
26572}
26573
26574void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026575 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026576 CheckIT(cond);
26577 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026578 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026579 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
26580 if (encoded_dt.IsValid()) {
26581 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26582 EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
26583 rd.Encode(22, 12) | rm.Encode(5, 0));
26584 AdvanceIT();
26585 return;
26586 }
26587 }
26588 } else {
26589 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
26590 if (encoded_dt.IsValid()) {
26591 if (cond.Is(al)) {
26592 EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
26593 rd.Encode(22, 12) | rm.Encode(5, 0));
26594 return;
26595 }
26596 }
26597 }
26598 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
26599}
26600
26601void Assembler::yield(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026602 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026603 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026604 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026605 // YIELD{<c>}{<q>} ; T1
26606 if (!size.IsWide()) {
26607 EmitT32_16(0xbf10);
26608 AdvanceIT();
26609 return;
26610 }
26611 // YIELD{<c>}.W ; T2
26612 if (!size.IsNarrow()) {
26613 EmitT32_32(0xf3af8001U);
26614 AdvanceIT();
26615 return;
26616 }
26617 } else {
26618 // YIELD{<c>}{<q>} ; A1
26619 if (cond.IsNotNever()) {
26620 EmitA32(0x0320f001U | (cond.GetCondition() << 28));
26621 return;
26622 }
26623 }
26624 Delegate(kYield, &Assembler::yield, cond, size);
26625}
26626// End of generated code.
26627
26628} // namespace aarch32
26629} // namespace vixl