blob: 138a3c29a5c1ee8bad3e77dfb8027f0d5604df7a [file] [log] [blame]
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001// Copyright 2017, VIXL authors
Alexandre Ramesd3832962016-07-04 15:03:43 +01002// 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>
Vincent Belliard60241a52016-11-10 12:41:11 -080035#include <iostream>
Pierre Langlois78973f22016-08-10 14:35:56 +010036
Alexandre Ramesd3832962016-07-04 15:03:43 +010037#include "utils-vixl.h"
Pierre Langlois1bce0072017-06-06 17:58:58 +010038#include "aarch32/assembler-aarch32.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010039#include "aarch32/constants-aarch32.h"
40#include "aarch32/instructions-aarch32.h"
Pierre Langlois989663e2016-11-24 13:11:08 +000041#include "aarch32/operands-aarch32.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010042
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_));
Alexandre Ramesd3832962016-07-04 15:03:43 +010071 // For A32, AdavanceIT() is not called by the assembler. We must call it
72 // in order to check that IT instructions are used consistently with
73 // the following conditional instructions.
Jacob Bramley10dae1a2016-07-27 09:45:13 +010074 if (IsUsingA32()) AdvanceIT();
Alexandre Ramesd3832962016-07-04 15:03:43 +010075 }
76}
77#endif
78
79
Vincent Belliarde42218c2016-10-19 13:24:28 -070080void Assembler::BindHelper(Label* label) {
Georgia Kouveli8b57c862017-03-02 15:18:58 +000081 VIXL_ASSERT(!label->IsBound());
82 label->SetLocation(this, GetCursorOffset());
83 label->MarkBound();
Vincent Belliarde42218c2016-10-19 13:24:28 -070084}
85
Georgia Kouveli275c9d42017-05-12 18:07:45 +010086uint32_t Assembler::Link(uint32_t instr,
87 Location* location,
88 const Location::EmitOperator& op,
Georgia Kouveli8b57c862017-03-02 15:18:58 +000089 const ReferenceInfo* info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010090 location->SetReferenced();
91 if (location->IsBound()) {
92 return op.Encode(instr, GetCursorOffset(), location);
93 }
Georgia Kouveli8b57c862017-03-02 15:18:58 +000094 location->AddForwardRef(GetCursorOffset(), op, info);
Alexandre Ramesd3832962016-07-04 15:03:43 +010095 return instr;
96}
97
98
Alexandre Ramesd3832962016-07-04 15:03:43 +010099// Start of generated code.
100class Dt_L_imm6_1 : public EncodingValue {
101 uint32_t type_;
102
103 public:
104 explicit Dt_L_imm6_1(DataType dt);
105 uint32_t GetTypeEncodingValue() const { return type_; }
106};
107
108Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
109 switch (dt.GetValue()) {
110 case S8:
111 type_ = 0x0;
112 SetEncodingValue(0x1);
113 break;
114 case U8:
115 type_ = 0x1;
116 SetEncodingValue(0x1);
117 break;
118 case S16:
119 type_ = 0x0;
120 SetEncodingValue(0x2);
121 break;
122 case U16:
123 type_ = 0x1;
124 SetEncodingValue(0x2);
125 break;
126 case S32:
127 type_ = 0x0;
128 SetEncodingValue(0x4);
129 break;
130 case U32:
131 type_ = 0x1;
132 SetEncodingValue(0x4);
133 break;
134 case S64:
135 type_ = 0x0;
136 SetEncodingValue(0x8);
137 break;
138 case U64:
139 type_ = 0x1;
140 SetEncodingValue(0x8);
141 break;
142 default:
143 VIXL_UNREACHABLE();
144 type_ = 0x0;
145 break;
146 }
147}
148
149class Dt_L_imm6_2 : public EncodingValue {
150 uint32_t type_;
151
152 public:
153 explicit Dt_L_imm6_2(DataType dt);
154 uint32_t GetTypeEncodingValue() const { return type_; }
155};
156
157Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
158 switch (dt.GetValue()) {
159 case S8:
160 type_ = 0x1;
161 SetEncodingValue(0x1);
162 break;
163 case S16:
164 type_ = 0x1;
165 SetEncodingValue(0x2);
166 break;
167 case S32:
168 type_ = 0x1;
169 SetEncodingValue(0x4);
170 break;
171 case S64:
172 type_ = 0x1;
173 SetEncodingValue(0x8);
174 break;
175 default:
176 VIXL_UNREACHABLE();
177 type_ = 0x0;
178 break;
179 }
180}
181
182class Dt_L_imm6_3 : public EncodingValue {
183 public:
184 explicit Dt_L_imm6_3(DataType dt);
185};
186
187Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
188 switch (dt.GetValue()) {
189 case I8:
190 SetEncodingValue(0x1);
191 break;
192 case I16:
193 SetEncodingValue(0x2);
194 break;
195 case I32:
196 SetEncodingValue(0x4);
197 break;
198 case I64:
199 SetEncodingValue(0x8);
200 break;
201 default:
202 break;
203 }
204}
205
206class Dt_L_imm6_4 : public EncodingValue {
207 public:
208 explicit Dt_L_imm6_4(DataType dt);
209};
210
211Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
212 switch (dt.GetValue()) {
213 case Untyped8:
214 SetEncodingValue(0x1);
215 break;
216 case Untyped16:
217 SetEncodingValue(0x2);
218 break;
219 case Untyped32:
220 SetEncodingValue(0x4);
221 break;
222 case Untyped64:
223 SetEncodingValue(0x8);
224 break;
225 default:
226 break;
227 }
228}
229
230class Dt_imm6_1 : public EncodingValue {
231 uint32_t type_;
232
233 public:
234 explicit Dt_imm6_1(DataType dt);
235 uint32_t GetTypeEncodingValue() const { return type_; }
236};
237
238Dt_imm6_1::Dt_imm6_1(DataType dt) {
239 switch (dt.GetValue()) {
240 case S16:
241 type_ = 0x0;
242 SetEncodingValue(0x1);
243 break;
244 case U16:
245 type_ = 0x1;
246 SetEncodingValue(0x1);
247 break;
248 case S32:
249 type_ = 0x0;
250 SetEncodingValue(0x2);
251 break;
252 case U32:
253 type_ = 0x1;
254 SetEncodingValue(0x2);
255 break;
256 case S64:
257 type_ = 0x0;
258 SetEncodingValue(0x4);
259 break;
260 case U64:
261 type_ = 0x1;
262 SetEncodingValue(0x4);
263 break;
264 default:
265 VIXL_UNREACHABLE();
266 type_ = 0x0;
267 break;
268 }
269}
270
271class Dt_imm6_2 : public EncodingValue {
272 uint32_t type_;
273
274 public:
275 explicit Dt_imm6_2(DataType dt);
276 uint32_t GetTypeEncodingValue() const { return type_; }
277};
278
279Dt_imm6_2::Dt_imm6_2(DataType dt) {
280 switch (dt.GetValue()) {
281 case S16:
282 type_ = 0x1;
283 SetEncodingValue(0x1);
284 break;
285 case S32:
286 type_ = 0x1;
287 SetEncodingValue(0x2);
288 break;
289 case S64:
290 type_ = 0x1;
291 SetEncodingValue(0x4);
292 break;
293 default:
294 VIXL_UNREACHABLE();
295 type_ = 0x0;
296 break;
297 }
298}
299
300class Dt_imm6_3 : public EncodingValue {
301 public:
302 explicit Dt_imm6_3(DataType dt);
303};
304
305Dt_imm6_3::Dt_imm6_3(DataType dt) {
306 switch (dt.GetValue()) {
307 case I16:
308 SetEncodingValue(0x1);
309 break;
310 case I32:
311 SetEncodingValue(0x2);
312 break;
313 case I64:
314 SetEncodingValue(0x4);
315 break;
316 default:
317 break;
318 }
319}
320
321class Dt_imm6_4 : public EncodingValue {
322 uint32_t type_;
323
324 public:
325 explicit Dt_imm6_4(DataType dt);
326 uint32_t GetTypeEncodingValue() const { return type_; }
327};
328
329Dt_imm6_4::Dt_imm6_4(DataType dt) {
330 switch (dt.GetValue()) {
331 case S8:
332 type_ = 0x0;
333 SetEncodingValue(0x1);
334 break;
335 case U8:
336 type_ = 0x1;
337 SetEncodingValue(0x1);
338 break;
339 case S16:
340 type_ = 0x0;
341 SetEncodingValue(0x2);
342 break;
343 case U16:
344 type_ = 0x1;
345 SetEncodingValue(0x2);
346 break;
347 case S32:
348 type_ = 0x0;
349 SetEncodingValue(0x4);
350 break;
351 case U32:
352 type_ = 0x1;
353 SetEncodingValue(0x4);
354 break;
355 default:
356 VIXL_UNREACHABLE();
357 type_ = 0x0;
358 break;
359 }
360}
361
362class Dt_op_U_size_1 : public EncodingValue {
363 public:
364 explicit Dt_op_U_size_1(DataType dt);
365};
366
367Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
368 switch (dt.GetValue()) {
369 case S8:
370 SetEncodingValue(0x0);
371 break;
372 case S16:
373 SetEncodingValue(0x1);
374 break;
375 case S32:
376 SetEncodingValue(0x2);
377 break;
378 case U8:
379 SetEncodingValue(0x4);
380 break;
381 case U16:
382 SetEncodingValue(0x5);
383 break;
384 case U32:
385 SetEncodingValue(0x6);
386 break;
387 case P8:
388 SetEncodingValue(0x8);
389 break;
390 case P64:
391 SetEncodingValue(0xa);
392 break;
393 default:
394 break;
395 }
396}
397
398class Dt_op_size_1 : public EncodingValue {
399 public:
400 explicit Dt_op_size_1(DataType dt);
401};
402
403Dt_op_size_1::Dt_op_size_1(DataType dt) {
404 switch (dt.GetValue()) {
405 case I8:
406 SetEncodingValue(0x0);
407 break;
408 case I16:
409 SetEncodingValue(0x1);
410 break;
411 case I32:
412 SetEncodingValue(0x2);
413 break;
414 case P8:
415 SetEncodingValue(0x4);
416 break;
417 default:
418 break;
419 }
420}
421
422class Dt_op_size_2 : public EncodingValue {
423 public:
424 explicit Dt_op_size_2(DataType dt);
425};
426
427Dt_op_size_2::Dt_op_size_2(DataType dt) {
428 switch (dt.GetValue()) {
429 case S8:
430 SetEncodingValue(0x0);
431 break;
432 case S16:
433 SetEncodingValue(0x1);
434 break;
435 case S32:
436 SetEncodingValue(0x2);
437 break;
438 case U8:
439 SetEncodingValue(0x4);
440 break;
441 case U16:
442 SetEncodingValue(0x5);
443 break;
444 case U32:
445 SetEncodingValue(0x6);
446 break;
447 default:
448 break;
449 }
450}
451
452class Dt_op_size_3 : public EncodingValue {
453 public:
454 explicit Dt_op_size_3(DataType dt);
455};
456
457Dt_op_size_3::Dt_op_size_3(DataType dt) {
458 switch (dt.GetValue()) {
459 case S16:
460 SetEncodingValue(0x0);
461 break;
462 case S32:
463 SetEncodingValue(0x1);
464 break;
465 case S64:
466 SetEncodingValue(0x2);
467 break;
468 case U16:
469 SetEncodingValue(0x4);
470 break;
471 case U32:
472 SetEncodingValue(0x5);
473 break;
474 case U64:
475 SetEncodingValue(0x6);
476 break;
477 default:
478 break;
479 }
480}
481
482class Dt_U_imm3H_1 : public EncodingValue {
483 public:
484 explicit Dt_U_imm3H_1(DataType dt);
485};
486
487Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
488 switch (dt.GetValue()) {
489 case S8:
490 SetEncodingValue(0x1);
491 break;
492 case S16:
493 SetEncodingValue(0x2);
494 break;
495 case S32:
496 SetEncodingValue(0x4);
497 break;
498 case U8:
499 SetEncodingValue(0x9);
500 break;
501 case U16:
502 SetEncodingValue(0xa);
503 break;
504 case U32:
505 SetEncodingValue(0xc);
506 break;
507 default:
508 break;
509 }
510}
511
512class Dt_U_opc1_opc2_1 : public EncodingValue {
513 public:
514 explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
515};
516
517Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
518 switch (dt.GetValue()) {
519 case S8:
520 if ((lane.GetLane() & 7) != lane.GetLane()) {
521 return;
522 }
523 SetEncodingValue(0x8 | lane.GetLane());
524 break;
525 case S16:
526 if ((lane.GetLane() & 3) != lane.GetLane()) {
527 return;
528 }
529 SetEncodingValue(0x1 | (lane.GetLane() << 1));
530 break;
531 case U8:
532 if ((lane.GetLane() & 7) != lane.GetLane()) {
533 return;
534 }
535 SetEncodingValue(0x18 | lane.GetLane());
536 break;
537 case U16:
538 if ((lane.GetLane() & 3) != lane.GetLane()) {
539 return;
540 }
541 SetEncodingValue(0x11 | (lane.GetLane() << 1));
542 break;
543 case Untyped32:
544 if ((lane.GetLane() & 1) != lane.GetLane()) {
545 return;
546 }
547 SetEncodingValue(0x0 | (lane.GetLane() << 2));
548 break;
549 case kDataTypeValueNone:
550 if ((lane.GetLane() & 1) != lane.GetLane()) {
551 return;
552 }
553 SetEncodingValue(0x0 | (lane.GetLane() << 2));
554 break;
555 default:
556 break;
557 }
558}
559
560class Dt_opc1_opc2_1 : public EncodingValue {
561 public:
562 explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
563};
564
565Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
566 switch (dt.GetValue()) {
567 case Untyped8:
568 if ((lane.GetLane() & 7) != lane.GetLane()) {
569 return;
570 }
571 SetEncodingValue(0x8 | lane.GetLane());
572 break;
573 case Untyped16:
574 if ((lane.GetLane() & 3) != lane.GetLane()) {
575 return;
576 }
577 SetEncodingValue(0x1 | (lane.GetLane() << 1));
578 break;
579 case Untyped32:
580 if ((lane.GetLane() & 1) != lane.GetLane()) {
581 return;
582 }
583 SetEncodingValue(0x0 | (lane.GetLane() << 2));
584 break;
585 case kDataTypeValueNone:
586 if ((lane.GetLane() & 1) != lane.GetLane()) {
587 return;
588 }
589 SetEncodingValue(0x0 | (lane.GetLane() << 2));
590 break;
591 default:
592 break;
593 }
594}
595
596class Dt_imm4_1 : public EncodingValue {
597 public:
598 explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
599};
600
601Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
602 switch (dt.GetValue()) {
603 case Untyped8:
604 if ((lane.GetLane() & 7) != lane.GetLane()) {
605 return;
606 }
607 SetEncodingValue(0x1 | (lane.GetLane() << 1));
608 break;
609 case Untyped16:
610 if ((lane.GetLane() & 3) != lane.GetLane()) {
611 return;
612 }
613 SetEncodingValue(0x2 | (lane.GetLane() << 2));
614 break;
615 case Untyped32:
616 if ((lane.GetLane() & 1) != lane.GetLane()) {
617 return;
618 }
619 SetEncodingValue(0x4 | (lane.GetLane() << 3));
620 break;
621 default:
622 break;
623 }
624}
625
626class Dt_B_E_1 : public EncodingValue {
627 public:
628 explicit Dt_B_E_1(DataType dt);
629};
630
631Dt_B_E_1::Dt_B_E_1(DataType dt) {
632 switch (dt.GetValue()) {
633 case Untyped8:
634 SetEncodingValue(0x2);
635 break;
636 case Untyped16:
637 SetEncodingValue(0x1);
638 break;
639 case Untyped32:
640 SetEncodingValue(0x0);
641 break;
642 default:
643 break;
644 }
645}
646
647class Dt_op_1 : public EncodingValue {
648 public:
649 Dt_op_1(DataType dt1, DataType dt2);
650};
651
652Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
653 if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
654 SetEncodingValue(0x0);
655 return;
656 }
657 if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
658 SetEncodingValue(0x1);
659 return;
660 }
661 if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
662 SetEncodingValue(0x2);
663 return;
664 }
665 if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
666 SetEncodingValue(0x3);
667 return;
668 }
669}
670
671class Dt_op_2 : public EncodingValue {
672 public:
673 explicit Dt_op_2(DataType dt);
674};
675
676Dt_op_2::Dt_op_2(DataType dt) {
677 switch (dt.GetValue()) {
678 case U32:
679 SetEncodingValue(0x0);
680 break;
681 case S32:
682 SetEncodingValue(0x1);
683 break;
684 default:
685 break;
686 }
687}
688
689class Dt_op_3 : public EncodingValue {
690 public:
691 explicit Dt_op_3(DataType dt);
692};
693
694Dt_op_3::Dt_op_3(DataType dt) {
695 switch (dt.GetValue()) {
696 case S32:
697 SetEncodingValue(0x0);
698 break;
699 case U32:
700 SetEncodingValue(0x1);
701 break;
702 default:
703 break;
704 }
705}
706
707class Dt_U_sx_1 : public EncodingValue {
708 public:
709 explicit Dt_U_sx_1(DataType dt);
710};
711
712Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
713 switch (dt.GetValue()) {
714 case S16:
715 SetEncodingValue(0x0);
716 break;
717 case S32:
718 SetEncodingValue(0x1);
719 break;
720 case U16:
721 SetEncodingValue(0x2);
722 break;
723 case U32:
724 SetEncodingValue(0x3);
725 break;
726 default:
727 break;
728 }
729}
730
731class Dt_op_U_1 : public EncodingValue {
732 public:
733 Dt_op_U_1(DataType dt1, DataType dt2);
734};
735
736Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
737 if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
738 SetEncodingValue(0x0);
739 return;
740 }
741 if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
742 SetEncodingValue(0x1);
743 return;
744 }
745 if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
746 SetEncodingValue(0x2);
747 return;
748 }
749 if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
750 SetEncodingValue(0x3);
751 return;
752 }
753}
754
755class Dt_sz_1 : public EncodingValue {
756 public:
757 explicit Dt_sz_1(DataType dt);
758};
759
760Dt_sz_1::Dt_sz_1(DataType dt) {
761 switch (dt.GetValue()) {
762 case F32:
763 SetEncodingValue(0x0);
764 break;
765 default:
766 break;
767 }
768}
769
770class Dt_F_size_1 : public EncodingValue {
771 public:
772 explicit Dt_F_size_1(DataType dt);
773};
774
775Dt_F_size_1::Dt_F_size_1(DataType dt) {
776 switch (dt.GetValue()) {
777 case S8:
778 SetEncodingValue(0x0);
779 break;
780 case S16:
781 SetEncodingValue(0x1);
782 break;
783 case S32:
784 SetEncodingValue(0x2);
785 break;
786 case F32:
787 SetEncodingValue(0x6);
788 break;
789 default:
790 break;
791 }
792}
793
794class Dt_F_size_2 : public EncodingValue {
795 public:
796 explicit Dt_F_size_2(DataType dt);
797};
798
799Dt_F_size_2::Dt_F_size_2(DataType dt) {
800 switch (dt.GetValue()) {
801 case I8:
802 SetEncodingValue(0x0);
803 break;
804 case I16:
805 SetEncodingValue(0x1);
806 break;
807 case I32:
808 SetEncodingValue(0x2);
809 break;
810 case F32:
811 SetEncodingValue(0x6);
812 break;
813 default:
814 break;
815 }
816}
817
818class Dt_F_size_3 : public EncodingValue {
819 public:
820 explicit Dt_F_size_3(DataType dt);
821};
822
823Dt_F_size_3::Dt_F_size_3(DataType dt) {
824 switch (dt.GetValue()) {
825 case I16:
826 SetEncodingValue(0x1);
827 break;
828 case I32:
829 SetEncodingValue(0x2);
830 break;
831 case F32:
832 SetEncodingValue(0x6);
833 break;
834 default:
835 break;
836 }
837}
838
839class Dt_F_size_4 : public EncodingValue {
840 public:
841 explicit Dt_F_size_4(DataType dt);
842};
843
844Dt_F_size_4::Dt_F_size_4(DataType dt) {
845 switch (dt.GetValue()) {
846 case U32:
847 SetEncodingValue(0x2);
848 break;
849 case F32:
850 SetEncodingValue(0x6);
851 break;
852 default:
853 break;
854 }
855}
856
857class Dt_U_size_1 : public EncodingValue {
858 public:
859 explicit Dt_U_size_1(DataType dt);
860};
861
862Dt_U_size_1::Dt_U_size_1(DataType dt) {
863 switch (dt.GetValue()) {
864 case S8:
865 SetEncodingValue(0x0);
866 break;
867 case S16:
868 SetEncodingValue(0x1);
869 break;
870 case S32:
871 SetEncodingValue(0x2);
872 break;
873 case U8:
874 SetEncodingValue(0x4);
875 break;
876 case U16:
877 SetEncodingValue(0x5);
878 break;
879 case U32:
880 SetEncodingValue(0x6);
881 break;
882 default:
883 break;
884 }
885}
886
887class Dt_U_size_2 : public EncodingValue {
888 public:
889 explicit Dt_U_size_2(DataType dt);
890};
891
892Dt_U_size_2::Dt_U_size_2(DataType dt) {
893 switch (dt.GetValue()) {
894 case S16:
895 SetEncodingValue(0x1);
896 break;
897 case S32:
898 SetEncodingValue(0x2);
899 break;
900 case U16:
901 SetEncodingValue(0x5);
902 break;
903 case U32:
904 SetEncodingValue(0x6);
905 break;
906 default:
907 break;
908 }
909}
910
911class Dt_U_size_3 : public EncodingValue {
912 public:
913 explicit Dt_U_size_3(DataType dt);
914};
915
916Dt_U_size_3::Dt_U_size_3(DataType dt) {
917 switch (dt.GetValue()) {
918 case S8:
919 SetEncodingValue(0x0);
920 break;
921 case S16:
922 SetEncodingValue(0x1);
923 break;
924 case S32:
925 SetEncodingValue(0x2);
926 break;
927 case S64:
928 SetEncodingValue(0x3);
929 break;
930 case U8:
931 SetEncodingValue(0x4);
932 break;
933 case U16:
934 SetEncodingValue(0x5);
935 break;
936 case U32:
937 SetEncodingValue(0x6);
938 break;
939 case U64:
940 SetEncodingValue(0x7);
941 break;
942 default:
943 break;
944 }
945}
946
947class Dt_size_1 : public EncodingValue {
948 public:
949 explicit Dt_size_1(DataType dt);
950};
951
952Dt_size_1::Dt_size_1(DataType dt) {
953 switch (dt.GetValue()) {
954 case Untyped8:
955 SetEncodingValue(0x0);
956 break;
957 default:
958 break;
959 }
960}
961
962class Dt_size_2 : public EncodingValue {
963 public:
964 explicit Dt_size_2(DataType dt);
965};
966
967Dt_size_2::Dt_size_2(DataType dt) {
968 switch (dt.GetValue()) {
969 case I8:
970 SetEncodingValue(0x0);
971 break;
972 case I16:
973 SetEncodingValue(0x1);
974 break;
975 case I32:
976 SetEncodingValue(0x2);
977 break;
978 case I64:
979 SetEncodingValue(0x3);
980 break;
981 default:
982 break;
983 }
984}
985
986class Dt_size_3 : public EncodingValue {
987 public:
988 explicit Dt_size_3(DataType dt);
989};
990
991Dt_size_3::Dt_size_3(DataType dt) {
992 switch (dt.GetValue()) {
993 case I16:
994 SetEncodingValue(0x0);
995 break;
996 case I32:
997 SetEncodingValue(0x1);
998 break;
999 case I64:
1000 SetEncodingValue(0x2);
1001 break;
1002 default:
1003 break;
1004 }
1005}
1006
1007class Dt_size_4 : public EncodingValue {
1008 public:
1009 explicit Dt_size_4(DataType dt);
1010};
1011
1012Dt_size_4::Dt_size_4(DataType dt) {
1013 switch (dt.GetValue()) {
1014 case I8:
1015 SetEncodingValue(0x0);
1016 break;
1017 case I16:
1018 SetEncodingValue(0x1);
1019 break;
1020 case I32:
1021 SetEncodingValue(0x2);
1022 break;
1023 default:
1024 break;
1025 }
1026}
1027
1028class Dt_size_5 : public EncodingValue {
1029 public:
1030 explicit Dt_size_5(DataType dt);
1031};
1032
1033Dt_size_5::Dt_size_5(DataType dt) {
1034 switch (dt.GetValue()) {
1035 case S8:
1036 SetEncodingValue(0x0);
1037 break;
1038 case S16:
1039 SetEncodingValue(0x1);
1040 break;
1041 case S32:
1042 SetEncodingValue(0x2);
1043 break;
1044 default:
1045 break;
1046 }
1047}
1048
1049class Dt_size_6 : public EncodingValue {
1050 public:
1051 explicit Dt_size_6(DataType dt);
1052};
1053
1054Dt_size_6::Dt_size_6(DataType dt) {
1055 switch (dt.GetValue()) {
1056 case Untyped8:
1057 SetEncodingValue(0x0);
1058 break;
1059 case Untyped16:
1060 SetEncodingValue(0x1);
1061 break;
1062 case Untyped32:
1063 SetEncodingValue(0x2);
1064 break;
1065 case Untyped64:
1066 SetEncodingValue(0x3);
1067 break;
1068 default:
1069 break;
1070 }
1071}
1072
1073class Dt_size_7 : public EncodingValue {
1074 public:
1075 explicit Dt_size_7(DataType dt);
1076};
1077
1078Dt_size_7::Dt_size_7(DataType dt) {
1079 switch (dt.GetValue()) {
1080 case Untyped8:
1081 SetEncodingValue(0x0);
1082 break;
1083 case Untyped16:
1084 SetEncodingValue(0x1);
1085 break;
1086 case Untyped32:
1087 SetEncodingValue(0x2);
1088 break;
1089 default:
1090 break;
1091 }
1092}
1093
1094class Dt_size_8 : public EncodingValue {
1095 public:
1096 Dt_size_8(DataType dt, Alignment align);
1097};
1098
1099Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
1100 switch (dt.GetValue()) {
1101 case Untyped8:
1102 SetEncodingValue(0x0);
1103 break;
1104 case Untyped16:
1105 SetEncodingValue(0x1);
1106 break;
1107 case Untyped32:
1108 if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
1109 SetEncodingValue(0x2);
1110 } else if (align.Is(k128BitAlign)) {
1111 SetEncodingValue(0x3);
1112 }
1113 break;
1114 default:
1115 break;
1116 }
1117}
1118
1119class Dt_size_9 : public EncodingValue {
1120 uint32_t type_;
1121
1122 public:
1123 explicit Dt_size_9(DataType dt);
1124 uint32_t GetTypeEncodingValue() const { return type_; }
1125};
1126
1127Dt_size_9::Dt_size_9(DataType dt) {
1128 switch (dt.GetValue()) {
1129 case I16:
1130 type_ = 0x0;
1131 SetEncodingValue(0x1);
1132 break;
1133 case I32:
1134 type_ = 0x0;
1135 SetEncodingValue(0x2);
1136 break;
1137 case F32:
1138 type_ = 0x1;
1139 SetEncodingValue(0x2);
1140 break;
1141 default:
1142 VIXL_UNREACHABLE();
1143 type_ = 0x0;
1144 break;
1145 }
1146}
1147
1148class Dt_size_10 : public EncodingValue {
1149 public:
1150 explicit Dt_size_10(DataType dt);
1151};
1152
1153Dt_size_10::Dt_size_10(DataType dt) {
1154 switch (dt.GetValue()) {
1155 case S8:
1156 case U8:
1157 case I8:
1158 SetEncodingValue(0x0);
1159 break;
1160 case S16:
1161 case U16:
1162 case I16:
1163 SetEncodingValue(0x1);
1164 break;
1165 case S32:
1166 case U32:
1167 case I32:
1168 SetEncodingValue(0x2);
1169 break;
1170 default:
1171 break;
1172 }
1173}
1174
1175class Dt_size_11 : public EncodingValue {
1176 uint32_t type_;
1177
1178 public:
1179 explicit Dt_size_11(DataType dt);
1180 uint32_t GetTypeEncodingValue() const { return type_; }
1181};
1182
1183Dt_size_11::Dt_size_11(DataType dt) {
1184 switch (dt.GetValue()) {
1185 case S16:
1186 type_ = 0x0;
1187 SetEncodingValue(0x1);
1188 break;
1189 case U16:
1190 type_ = 0x1;
1191 SetEncodingValue(0x1);
1192 break;
1193 case S32:
1194 type_ = 0x0;
1195 SetEncodingValue(0x2);
1196 break;
1197 case U32:
1198 type_ = 0x1;
1199 SetEncodingValue(0x2);
1200 break;
1201 default:
1202 VIXL_UNREACHABLE();
1203 type_ = 0x0;
1204 break;
1205 }
1206}
1207
1208class Dt_size_12 : public EncodingValue {
1209 uint32_t type_;
1210
1211 public:
1212 explicit Dt_size_12(DataType dt);
1213 uint32_t GetTypeEncodingValue() const { return type_; }
1214};
1215
1216Dt_size_12::Dt_size_12(DataType dt) {
1217 switch (dt.GetValue()) {
1218 case S8:
1219 type_ = 0x0;
1220 SetEncodingValue(0x0);
1221 break;
1222 case U8:
1223 type_ = 0x1;
1224 SetEncodingValue(0x0);
1225 break;
1226 case S16:
1227 type_ = 0x0;
1228 SetEncodingValue(0x1);
1229 break;
1230 case U16:
1231 type_ = 0x1;
1232 SetEncodingValue(0x1);
1233 break;
1234 case S32:
1235 type_ = 0x0;
1236 SetEncodingValue(0x2);
1237 break;
1238 case U32:
1239 type_ = 0x1;
1240 SetEncodingValue(0x2);
1241 break;
1242 default:
1243 VIXL_UNREACHABLE();
1244 type_ = 0x0;
1245 break;
1246 }
1247}
1248
1249class Dt_size_13 : public EncodingValue {
1250 public:
1251 explicit Dt_size_13(DataType dt);
1252};
1253
1254Dt_size_13::Dt_size_13(DataType dt) {
1255 switch (dt.GetValue()) {
1256 case S16:
1257 SetEncodingValue(0x1);
1258 break;
1259 case S32:
1260 SetEncodingValue(0x2);
1261 break;
1262 default:
1263 break;
1264 }
1265}
1266
1267class Dt_size_14 : public EncodingValue {
1268 public:
1269 explicit Dt_size_14(DataType dt);
1270};
1271
1272Dt_size_14::Dt_size_14(DataType dt) {
1273 switch (dt.GetValue()) {
1274 case S16:
1275 SetEncodingValue(0x0);
1276 break;
1277 case S32:
1278 SetEncodingValue(0x1);
1279 break;
1280 case S64:
1281 SetEncodingValue(0x2);
1282 break;
1283 default:
1284 break;
1285 }
1286}
1287
1288class Dt_size_15 : public EncodingValue {
1289 public:
1290 explicit Dt_size_15(DataType dt);
1291};
1292
1293Dt_size_15::Dt_size_15(DataType dt) {
1294 switch (dt.GetValue()) {
1295 case Untyped8:
1296 SetEncodingValue(0x0);
1297 break;
1298 case Untyped16:
1299 SetEncodingValue(0x1);
1300 break;
1301 default:
1302 break;
1303 }
1304}
1305
1306class Dt_size_16 : public EncodingValue {
1307 public:
1308 explicit Dt_size_16(DataType dt);
1309};
1310
1311Dt_size_16::Dt_size_16(DataType dt) {
1312 switch (dt.GetValue()) {
1313 case I8:
1314 SetEncodingValue(0x0);
1315 break;
1316 case I16:
1317 SetEncodingValue(0x1);
1318 break;
1319 case I32:
1320 SetEncodingValue(0x2);
1321 break;
1322 default:
1323 break;
1324 }
1325}
1326
1327class Index_1 : public EncodingValue {
1328 public:
1329 Index_1(const NeonRegisterList& nreglist, DataType dt);
1330};
1331
1332Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1333 switch (dt.GetValue()) {
1334 case Untyped8: {
1335 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1336 return;
1337 }
1338 uint32_t value = nreglist.GetTransferLane() << 1;
1339 if (!nreglist.IsSingleSpaced()) return;
1340 SetEncodingValue(value);
1341 break;
1342 }
1343 case Untyped16: {
1344 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1345 return;
1346 }
1347 uint32_t value = nreglist.GetTransferLane() << 2;
1348 if (nreglist.IsDoubleSpaced()) value |= 2;
1349 SetEncodingValue(value);
1350 break;
1351 }
1352 case Untyped32: {
1353 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1354 return;
1355 }
1356 uint32_t value = nreglist.GetTransferLane() << 3;
1357 if (nreglist.IsDoubleSpaced()) value |= 4;
1358 SetEncodingValue(value);
1359 break;
1360 }
1361 default:
1362 break;
1363 }
1364}
1365
1366class Align_index_align_1 : public EncodingValue {
1367 public:
1368 Align_index_align_1(Alignment align,
1369 const NeonRegisterList& nreglist,
1370 DataType dt);
1371};
1372
1373Align_index_align_1::Align_index_align_1(Alignment align,
1374 const NeonRegisterList& nreglist,
1375 DataType dt) {
1376 switch (dt.GetValue()) {
1377 case Untyped8: {
1378 uint32_t value;
1379 if (align.GetType() == kNoAlignment) {
1380 value = 0;
1381 } else {
1382 return;
1383 }
1384 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1385 return;
1386 }
1387 value |= nreglist.GetTransferLane() << 1;
1388 SetEncodingValue(value);
1389 break;
1390 }
1391 case Untyped16: {
1392 uint32_t value;
1393 if (align.GetType() == k16BitAlign) {
1394 value = 1;
1395 } else if (align.GetType() == kNoAlignment) {
1396 value = 0;
1397 } else {
1398 return;
1399 }
1400 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1401 return;
1402 }
1403 value |= nreglist.GetTransferLane() << 2;
1404 SetEncodingValue(value);
1405 break;
1406 }
1407 case Untyped32: {
1408 uint32_t value;
1409 if (align.GetType() == k32BitAlign) {
1410 value = 3;
1411 } else if (align.GetType() == kNoAlignment) {
1412 value = 0;
1413 } else {
1414 return;
1415 }
1416 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1417 return;
1418 }
1419 value |= nreglist.GetTransferLane() << 3;
1420 SetEncodingValue(value);
1421 break;
1422 }
1423 default:
1424 break;
1425 }
1426}
1427
1428class Align_index_align_2 : public EncodingValue {
1429 public:
1430 Align_index_align_2(Alignment align,
1431 const NeonRegisterList& nreglist,
1432 DataType dt);
1433};
1434
1435Align_index_align_2::Align_index_align_2(Alignment align,
1436 const NeonRegisterList& nreglist,
1437 DataType dt) {
1438 switch (dt.GetValue()) {
1439 case Untyped8: {
1440 uint32_t value;
1441 if (align.GetType() == k16BitAlign) {
1442 value = 1;
1443 } else if (align.GetType() == kNoAlignment) {
1444 value = 0;
1445 } else {
1446 return;
1447 }
1448 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1449 return;
1450 }
1451 value |= nreglist.GetTransferLane() << 1;
1452 if (!nreglist.IsSingleSpaced()) return;
1453 SetEncodingValue(value);
1454 break;
1455 }
1456 case Untyped16: {
1457 uint32_t value;
1458 if (align.GetType() == k32BitAlign) {
1459 value = 1;
1460 } else if (align.GetType() == kNoAlignment) {
1461 value = 0;
1462 } else {
1463 return;
1464 }
1465 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1466 return;
1467 }
1468 value |= nreglist.GetTransferLane() << 2;
1469 if (nreglist.IsDoubleSpaced()) value |= 2;
1470 SetEncodingValue(value);
1471 break;
1472 }
1473 case Untyped32: {
1474 uint32_t value;
1475 if (align.GetType() == k64BitAlign) {
1476 value = 1;
1477 } else if (align.GetType() == kNoAlignment) {
1478 value = 0;
1479 } else {
1480 return;
1481 }
1482 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1483 return;
1484 }
1485 value |= nreglist.GetTransferLane() << 3;
1486 if (nreglist.IsDoubleSpaced()) value |= 4;
1487 SetEncodingValue(value);
1488 break;
1489 }
1490 default:
1491 break;
1492 }
1493}
1494
1495class Align_index_align_3 : public EncodingValue {
1496 public:
1497 Align_index_align_3(Alignment align,
1498 const NeonRegisterList& nreglist,
1499 DataType dt);
1500};
1501
1502Align_index_align_3::Align_index_align_3(Alignment align,
1503 const NeonRegisterList& nreglist,
1504 DataType dt) {
1505 switch (dt.GetValue()) {
1506 case Untyped8: {
1507 uint32_t value;
1508 if (align.GetType() == k32BitAlign) {
1509 value = 1;
1510 } else if (align.GetType() == kNoAlignment) {
1511 value = 0;
1512 } else {
1513 return;
1514 }
1515 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1516 return;
1517 }
1518 value |= nreglist.GetTransferLane() << 1;
1519 if (!nreglist.IsSingleSpaced()) return;
1520 SetEncodingValue(value);
1521 break;
1522 }
1523 case Untyped16: {
1524 uint32_t value;
1525 if (align.GetType() == k64BitAlign) {
1526 value = 1;
1527 } else if (align.GetType() == kNoAlignment) {
1528 value = 0;
1529 } else {
1530 return;
1531 }
1532 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1533 return;
1534 }
1535 value |= nreglist.GetTransferLane() << 2;
1536 if (nreglist.IsDoubleSpaced()) value |= 2;
1537 SetEncodingValue(value);
1538 break;
1539 }
1540 case Untyped32: {
1541 uint32_t value;
1542 if (align.GetType() == k64BitAlign) {
1543 value = 1;
1544 } else if (align.GetType() == k128BitAlign) {
1545 value = 2;
1546 } else if (align.GetType() == kNoAlignment) {
1547 value = 0;
1548 } else {
1549 return;
1550 }
1551 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1552 return;
1553 }
1554 value |= nreglist.GetTransferLane() << 3;
1555 if (nreglist.IsDoubleSpaced()) value |= 4;
1556 SetEncodingValue(value);
1557 break;
1558 }
1559 default:
1560 break;
1561 }
1562}
1563
1564class Align_a_1 : public EncodingValue {
1565 public:
1566 Align_a_1(Alignment align, DataType dt);
1567};
1568
1569Align_a_1::Align_a_1(Alignment align, DataType dt) {
1570 switch (align.GetType()) {
1571 case k16BitAlign:
1572 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1573 break;
1574 case k32BitAlign:
1575 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1576 break;
1577 case kNoAlignment:
1578 SetEncodingValue(0x0);
1579 break;
1580 default:
1581 break;
1582 }
1583}
1584
1585class Align_a_2 : public EncodingValue {
1586 public:
1587 Align_a_2(Alignment align, DataType dt);
1588};
1589
1590Align_a_2::Align_a_2(Alignment align, DataType dt) {
1591 switch (align.GetType()) {
1592 case k16BitAlign:
1593 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1594 break;
1595 case k32BitAlign:
1596 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1597 break;
1598 case k64BitAlign:
1599 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1600 break;
1601 case kNoAlignment:
1602 SetEncodingValue(0x0);
1603 break;
1604 default:
1605 break;
1606 }
1607}
1608
1609class Align_a_3 : public EncodingValue {
1610 public:
1611 Align_a_3(Alignment align, DataType dt);
1612};
1613
1614Align_a_3::Align_a_3(Alignment align, DataType dt) {
1615 switch (align.GetType()) {
1616 case k32BitAlign:
1617 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1618 break;
1619 case k64BitAlign:
1620 if (dt.Is(Untyped16))
1621 SetEncodingValue(0x1);
1622 else if (dt.Is(Untyped32))
1623 SetEncodingValue(0x1);
1624 break;
1625 case k128BitAlign:
1626 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1627 break;
1628 case kNoAlignment:
1629 SetEncodingValue(0x0);
1630 break;
1631 default:
1632 break;
1633 }
1634}
1635
1636class Align_align_1 : public EncodingValue {
1637 public:
1638 Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1639};
1640
1641Align_align_1::Align_align_1(Alignment align,
1642 const NeonRegisterList& nreglist) {
1643 switch (align.GetType()) {
1644 case k64BitAlign:
1645 SetEncodingValue(0x1);
1646 break;
1647 case k128BitAlign:
1648 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1649 SetEncodingValue(0x2);
1650 break;
1651 case k256BitAlign:
1652 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1653 SetEncodingValue(0x3);
1654 break;
1655 case kNoAlignment:
1656 SetEncodingValue(0x0);
1657 break;
1658 default:
1659 break;
1660 }
1661}
1662
1663class Align_align_2 : public EncodingValue {
1664 public:
1665 Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1666};
1667
1668Align_align_2::Align_align_2(Alignment align,
1669 const NeonRegisterList& nreglist) {
1670 switch (align.GetType()) {
1671 case k64BitAlign:
1672 SetEncodingValue(0x1);
1673 break;
1674 case k128BitAlign:
1675 SetEncodingValue(0x2);
1676 break;
1677 case k256BitAlign:
1678 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1679 break;
1680 case kNoAlignment:
1681 SetEncodingValue(0x0);
1682 break;
1683 default:
1684 break;
1685 }
1686}
1687
1688class Align_align_3 : public EncodingValue {
1689 public:
1690 explicit Align_align_3(Alignment align);
1691};
1692
1693Align_align_3::Align_align_3(Alignment align) {
1694 switch (align.GetType()) {
1695 case k64BitAlign:
1696 SetEncodingValue(0x1);
1697 break;
1698 case kNoAlignment:
1699 SetEncodingValue(0x0);
1700 break;
1701 default:
1702 break;
1703 }
1704}
1705
1706class Align_align_4 : public EncodingValue {
1707 public:
1708 explicit Align_align_4(Alignment align);
1709};
1710
1711Align_align_4::Align_align_4(Alignment align) {
1712 switch (align.GetType()) {
1713 case k64BitAlign:
1714 SetEncodingValue(0x1);
1715 break;
1716 case k128BitAlign:
1717 SetEncodingValue(0x2);
1718 break;
1719 case k256BitAlign:
1720 SetEncodingValue(0x3);
1721 break;
1722 case kNoAlignment:
1723 SetEncodingValue(0x0);
1724 break;
1725 default:
1726 break;
1727 }
1728}
1729
1730class Align_align_5 : public EncodingValue {
1731 public:
1732 Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1733};
1734
1735Align_align_5::Align_align_5(Alignment align,
1736 const NeonRegisterList& nreglist) {
1737 switch (align.GetType()) {
1738 case k64BitAlign:
1739 SetEncodingValue(0x1);
1740 break;
1741 case k128BitAlign:
1742 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1743 SetEncodingValue(0x2);
1744 break;
1745 case k256BitAlign:
1746 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1747 break;
1748 case kNoAlignment:
1749 SetEncodingValue(0x0);
1750 break;
1751 default:
1752 break;
1753 }
1754}
1755
Vincent Belliardac285442017-05-16 09:26:45 -07001756
1757// CBNZ{<q>} <Rn>, <label> ; T1
1758// CBZ{<q>} <Rn>, <label> ; T1
1759static const struct ReferenceInfo kT16CbzInfo =
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001760 {k16BitT32InstructionSizeInBytes,
1761 0, // Min offset.
1762 126, // Max offset.
1763 2, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001764 ReferenceInfo::kDontAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001765
1766
1767// B<c>{<q>} <label> ; T1
1768static const struct ReferenceInfo kT16ConditionalBranchInfo =
1769 {k16BitT32InstructionSizeInBytes,
1770 -256, // Min offset.
1771 254, // Max offset.
1772 2, // Alignment.
1773 ReferenceInfo::kDontAlignPc};
1774
1775
1776// ADR{<c>}{<q>} <Rd>, <label> ; T1
1777// LDR{<c>}{<q>} <Rt>, <label> ; T1
1778static const struct ReferenceInfo kT16DataInfo =
1779 {k16BitT32InstructionSizeInBytes,
1780 0, // Min offset.
1781 1020, // Max offset.
1782 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001783 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001784
1785
1786// B{<c>}{<q>} <label> ; T2
1787static const struct ReferenceInfo kT16BranchInfo =
1788 {k16BitT32InstructionSizeInBytes,
1789 -2048, // Min offset.
1790 2046, // Max offset.
1791 2, // Alignment.
1792 ReferenceInfo::kDontAlignPc};
1793
1794
1795// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
1796// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
1797// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
1798static const struct ReferenceInfo kT32DataInfo =
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001799 {k32BitT32InstructionSizeInBytes,
1800 -1020, // Min offset.
1801 1020, // Max offset.
1802 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001803 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001804
1805
1806// ADR{<c>}{<q>} <Rd>, <label> ; T3
1807// LDR{<c>}{<q>} <Rt>, <label> ; T2
1808// LDRB{<c>}{<q>} <Rt>, <label> ; T1
1809// LDRH{<c>}{<q>} <Rt>, <label> ; T1
1810// LDRSB{<c>}{<q>} <Rt>, <label> ; T1
1811// LDRSH{<c>}{<q>} <Rt>, <label> ; T1
1812// PLD{<c>}{<q>} <label> ; T1
1813// PLI{<c>}{<q>} <label> ; T3
1814static const struct ReferenceInfo kT32FarDataInfo =
1815 {k32BitT32InstructionSizeInBytes,
1816 -4095, // Min offset.
1817 4095, // Max offset.
1818 1, // Alignment.
1819 ReferenceInfo::kAlignPc};
1820
1821
1822// B<c>{<q>} <label> ; T3
1823static const struct ReferenceInfo kT32ConditionalBranchInfo =
1824 {k32BitT32InstructionSizeInBytes,
1825 -1048576, // Min offset.
1826 1048574, // Max offset.
1827 2, // Alignment.
1828 ReferenceInfo::kDontAlignPc};
1829
1830
1831// B{<c>}{<q>} <label> ; T4
1832// BL{<c>}{<q>} <label> ; T1
1833static const struct ReferenceInfo kT32BranchInfo =
1834 {k32BitT32InstructionSizeInBytes,
1835 -16777216, // Min offset.
1836 16777214, // Max offset.
1837 2, // Alignment.
1838 ReferenceInfo::kDontAlignPc};
1839
1840
1841// BLX{<c>}{<q>} <label> ; T2
1842static const struct ReferenceInfo kT32BlxInfo =
1843 {k32BitT32InstructionSizeInBytes,
1844 -16777216, // Min offset.
1845 16777212, // Max offset.
1846 4, // Alignment.
1847 ReferenceInfo::kAlignPc};
1848
1849
1850// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
1851// LDRH{<c>}{<q>} <Rt>, <label> ; A1
1852// LDRSB{<c>}{<q>} <Rt>, <label> ; A1
1853// LDRSH{<c>}{<q>} <Rt>, <label> ; A1
1854static const struct ReferenceInfo kA32VeryNearDataInfo =
1855 {kA32InstructionSizeInBytes,
1856 -255, // Min offset.
1857 255, // Max offset.
1858 1, // Alignment.
1859 ReferenceInfo::kAlignPc};
1860
1861
1862// ADR{<c>}{<q>} <Rd>, <label> ; A1
1863static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes,
1864 -256, // Min offset.
1865 256, // Max offset.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001866 1, // Alignment.
1867 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001868
1869
1870// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
1871// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
1872static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes,
1873 -1020, // Min offset.
1874 1020, // Max offset.
1875 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001876 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001877
1878
1879// LDR{<c>}{<q>} <Rt>, <label> ; A1
1880// LDRB{<c>}{<q>} <Rt>, <label> ; A1
1881// PLD{<c>}{<q>} <label> ; A1
1882// PLI{<c>}{<q>} <label> ; A1
1883static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes,
1884 -4095, // Min offset.
1885 4095, // Max offset.
1886 1, // Alignment.
1887 ReferenceInfo::kAlignPc};
1888
1889
1890// B{<c>}{<q>} <label> ; A1
1891// BL{<c>}{<q>} <label> ; A1
1892static const struct ReferenceInfo kA32BranchInfo =
1893 {kA32InstructionSizeInBytes,
1894 -33554432, // Min offset.
1895 33554428, // Max offset.
1896 4, // Alignment.
1897 ReferenceInfo::kDontAlignPc};
1898
1899
1900// BLX{<c>}{<q>} <label> ; A2
1901static const struct ReferenceInfo kA32BlxInfo = {kA32InstructionSizeInBytes,
1902 -33554432, // Min offset.
1903 33554430, // Max offset.
1904 2, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001905 ReferenceInfo::kAlignPc};
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001906
Alexandre Ramesd3832962016-07-04 15:03:43 +01001907
1908void Assembler::adc(Condition cond,
1909 EncodingSize size,
1910 Register rd,
1911 Register rn,
1912 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07001913 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01001914 CheckIT(cond);
1915 if (operand.IsImmediate()) {
1916 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001917 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001918 ImmediateT32 immediate_t32(imm);
1919 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08001920 if (!size.IsNarrow() && immediate_t32.IsValid() &&
1921 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001922 EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1923 (immediate_t32.GetEncodingValue() & 0xff) |
1924 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1925 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1926 AdvanceIT();
1927 return;
1928 }
1929 } else {
1930 ImmediateA32 immediate_a32(imm);
1931 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1932 if (immediate_a32.IsValid() && cond.IsNotNever()) {
1933 EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1934 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1935 immediate_a32.GetEncodingValue());
1936 return;
1937 }
1938 }
1939 }
1940 if (operand.IsImmediateShiftedRegister()) {
1941 Register rm = operand.GetBaseRegister();
1942 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001944 // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1945 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1946 rm.IsLow()) {
1947 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1948 AdvanceIT();
1949 return;
1950 }
1951 }
1952 }
1953 Shift shift = operand.GetShift();
1954 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001955 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001956 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08001957 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1958 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001959 uint32_t amount_ = amount % 32;
1960 EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1961 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1962 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1963 AdvanceIT();
1964 return;
1965 }
1966 } else {
1967 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1968 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1969 uint32_t amount_ = amount % 32;
1970 EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1971 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1972 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1973 return;
1974 }
1975 }
1976 }
1977 if (operand.IsRegisterShiftedRegister()) {
1978 Register rm = operand.GetBaseRegister();
1979 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00001980 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001981 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001982 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00001983 if (cond.IsNotNever() &&
1984 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
1985 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001986 EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
1987 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00001988 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001989 return;
1990 }
1991 }
1992 }
1993 Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
1994}
1995
1996void Assembler::adcs(Condition cond,
1997 EncodingSize size,
1998 Register rd,
1999 Register rn,
2000 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002001 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002002 CheckIT(cond);
2003 if (operand.IsImmediate()) {
2004 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002005 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002006 ImmediateT32 immediate_t32(imm);
2007 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08002008 if (!size.IsNarrow() && immediate_t32.IsValid() &&
2009 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002010 EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2011 (immediate_t32.GetEncodingValue() & 0xff) |
2012 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2013 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2014 AdvanceIT();
2015 return;
2016 }
2017 } else {
2018 ImmediateA32 immediate_a32(imm);
2019 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2020 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2021 EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
2022 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2023 immediate_a32.GetEncodingValue());
2024 return;
2025 }
2026 }
2027 }
2028 if (operand.IsImmediateShiftedRegister()) {
2029 Register rm = operand.GetBaseRegister();
2030 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002031 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002032 // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2033 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2034 rm.IsLow()) {
2035 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
2036 AdvanceIT();
2037 return;
2038 }
2039 }
2040 }
2041 Shift shift = operand.GetShift();
2042 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002043 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002044 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002045 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2046 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002047 uint32_t amount_ = amount % 32;
2048 EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2049 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2050 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2051 AdvanceIT();
2052 return;
2053 }
2054 } else {
2055 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2056 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2057 uint32_t amount_ = amount % 32;
2058 EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
2059 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2060 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2061 return;
2062 }
2063 }
2064 }
2065 if (operand.IsRegisterShiftedRegister()) {
2066 Register rm = operand.GetBaseRegister();
2067 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002068 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002069 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002070 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002071 if (cond.IsNotNever() &&
2072 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2073 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002074 EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
2075 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002076 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002077 return;
2078 }
2079 }
2080 }
2081 Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
2082}
2083
2084void Assembler::add(Condition cond,
2085 EncodingSize size,
2086 Register rd,
2087 Register rn,
2088 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002089 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002090 CheckIT(cond);
2091 if (operand.IsImmediate()) {
2092 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002093 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002094 ImmediateT32 immediate_t32(imm);
2095 // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
2096 if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
2097 ((imm % 4) == 0)) {
2098 uint32_t imm_ = imm >> 2;
2099 EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
2100 AdvanceIT();
2101 return;
2102 }
2103 // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
2104 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2105 (imm <= 7)) {
2106 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2107 AdvanceIT();
2108 return;
2109 }
2110 // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2111 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2112 (imm <= 255)) {
2113 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2114 AdvanceIT();
2115 return;
2116 }
2117 // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
2118 if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
2119 ((imm % 4) == 0)) {
2120 uint32_t imm_ = imm >> 2;
2121 EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2122 AdvanceIT();
2123 return;
2124 }
2125 // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2126 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2127 ((imm % 4) == 0)) {
2128 uint32_t imm_ = imm >> 2;
2129 EmitT32_16(0xb000 | imm_);
2130 AdvanceIT();
2131 return;
2132 }
2133 // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002134 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002135 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002136 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2137 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2138 AdvanceIT();
2139 return;
2140 }
2141 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002142 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2143 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002144 EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2145 (immediate_t32.GetEncodingValue() & 0xff) |
2146 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2147 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2148 AdvanceIT();
2149 return;
2150 }
2151 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002152 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002153 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002154 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2155 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2156 AdvanceIT();
2157 return;
2158 }
2159 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002160 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002161 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002162 EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2163 (immediate_t32.GetEncodingValue() & 0xff) |
2164 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2165 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2166 AdvanceIT();
2167 return;
2168 }
2169 // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002170 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002171 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002172 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2173 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2174 AdvanceIT();
2175 return;
2176 }
2177 } else {
2178 ImmediateA32 immediate_a32(imm);
2179 // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2180 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2181 EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2182 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2183 return;
2184 }
2185 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2186 if (immediate_a32.IsValid() && cond.IsNotNever() &&
2187 ((rn.GetCode() & 0xd) != 0xd)) {
2188 EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2189 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2190 immediate_a32.GetEncodingValue());
2191 return;
2192 }
2193 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2194 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2195 EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2196 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2197 return;
2198 }
2199 }
2200 }
2201 if (operand.IsImmediateShiftedRegister()) {
2202 Register rm = operand.GetBaseRegister();
2203 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002204 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002205 // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2206 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2207 rm.IsLow()) {
2208 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2209 (rm.GetCode() << 6));
2210 AdvanceIT();
2211 return;
2212 }
2213 // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002214 if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
2215 (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2216 (!rd.IsPC() || !rm.IsPC())) ||
2217 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002218 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2219 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2220 AdvanceIT();
2221 return;
2222 }
2223 // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08002224 if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002225 ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
Vincent Belliardd17e3482016-11-22 15:46:43 -08002226 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002227 EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2228 ((rd.GetCode() & 0x8) << 4));
2229 AdvanceIT();
2230 return;
2231 }
2232 // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2233 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2234 EmitT32_16(0x4485 | (rm.GetCode() << 3));
2235 AdvanceIT();
2236 return;
2237 }
2238 }
2239 }
2240 Shift shift = operand.GetShift();
2241 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002242 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002243 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002244 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2245 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002246 uint32_t amount_ = amount % 32;
2247 EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2248 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2249 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2250 AdvanceIT();
2251 return;
2252 }
2253 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002254 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2255 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002256 uint32_t amount_ = amount % 32;
2257 EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2258 (operand.GetTypeEncodingValue() << 4) |
2259 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2260 AdvanceIT();
2261 return;
2262 }
2263 } else {
2264 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2265 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2266 uint32_t amount_ = amount % 32;
2267 EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2268 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2269 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2270 return;
2271 }
2272 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2273 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2274 uint32_t amount_ = amount % 32;
2275 EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2276 (rd.GetCode() << 12) | rm.GetCode() |
2277 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2278 return;
2279 }
2280 }
2281 }
2282 if (operand.IsRegisterShiftedRegister()) {
2283 Register rm = operand.GetBaseRegister();
2284 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002285 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002286 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002287 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002288 if (cond.IsNotNever() &&
2289 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2290 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002291 EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2292 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002293 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002294 return;
2295 }
2296 }
2297 }
2298 Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2299}
2300
2301void Assembler::add(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002302 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002303 CheckIT(cond);
2304 if (operand.IsImmediate()) {
2305 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002306 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002307 // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2308 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2309 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2310 AdvanceIT();
2311 return;
2312 }
2313 }
2314 }
2315 if (operand.IsPlainRegister()) {
2316 Register rm = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002317 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002318 // ADD<c>{<q>} <Rdn>, <Rm> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002319 if (InITBlock() && !rm.Is(sp) &&
2320 (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2321 (!rd.IsPC() || !rm.IsPC())) ||
2322 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002323 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2324 (rm.GetCode() << 3));
2325 AdvanceIT();
2326 return;
2327 }
2328 }
2329 }
2330 Delegate(kAdd, &Assembler::add, cond, rd, operand);
2331}
2332
2333void Assembler::adds(Condition cond,
2334 EncodingSize size,
2335 Register rd,
2336 Register rn,
2337 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002338 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002339 CheckIT(cond);
2340 if (operand.IsImmediate()) {
2341 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002342 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002343 ImmediateT32 immediate_t32(imm);
2344 // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2345 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2346 (imm <= 7)) {
2347 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2348 AdvanceIT();
2349 return;
2350 }
2351 // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2352 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2353 (imm <= 255)) {
2354 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2355 AdvanceIT();
2356 return;
2357 }
2358 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2359 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002360 !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002361 EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2362 (immediate_t32.GetEncodingValue() & 0xff) |
2363 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2364 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2365 AdvanceIT();
2366 return;
2367 }
2368 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2369 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2370 !rd.Is(pc)) {
2371 EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2372 (immediate_t32.GetEncodingValue() & 0xff) |
2373 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2374 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2375 AdvanceIT();
2376 return;
2377 }
2378 } else {
2379 ImmediateA32 immediate_a32(imm);
2380 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2381 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2382 EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2383 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2384 immediate_a32.GetEncodingValue());
2385 return;
2386 }
2387 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2388 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2389 EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2390 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2391 return;
2392 }
2393 }
2394 }
2395 if (operand.IsImmediateShiftedRegister()) {
2396 Register rm = operand.GetBaseRegister();
2397 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002398 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002399 // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2400 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2401 rm.IsLow()) {
2402 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2403 (rm.GetCode() << 6));
2404 AdvanceIT();
2405 return;
2406 }
2407 }
2408 }
2409 Shift shift = operand.GetShift();
2410 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002411 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002412 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2413 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
Vincent Belliardd17e3482016-11-22 15:46:43 -08002414 !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002415 uint32_t amount_ = amount % 32;
2416 EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2417 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2418 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2419 AdvanceIT();
2420 return;
2421 }
2422 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2423 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002424 !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002425 uint32_t amount_ = amount % 32;
2426 EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2427 (operand.GetTypeEncodingValue() << 4) |
2428 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2429 AdvanceIT();
2430 return;
2431 }
2432 } else {
2433 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2434 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2435 uint32_t amount_ = amount % 32;
2436 EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2437 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2438 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2439 return;
2440 }
2441 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2442 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2443 uint32_t amount_ = amount % 32;
2444 EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2445 (rd.GetCode() << 12) | rm.GetCode() |
2446 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2447 return;
2448 }
2449 }
2450 }
2451 if (operand.IsRegisterShiftedRegister()) {
2452 Register rm = operand.GetBaseRegister();
2453 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002454 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002455 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002456 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002457 if (cond.IsNotNever() &&
2458 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2459 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002460 EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2461 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002462 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002463 return;
2464 }
2465 }
2466 }
2467 Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2468}
2469
2470void Assembler::adds(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002471 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002472 CheckIT(al);
2473 if (operand.IsImmediate()) {
2474 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002475 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002476 // ADDS{<q>} <Rdn>, #<imm8> ; T2
2477 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2478 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2479 AdvanceIT();
2480 return;
2481 }
2482 }
2483 }
2484 Delegate(kAdds, &Assembler::adds, rd, operand);
2485}
2486
2487void Assembler::addw(Condition cond,
2488 Register rd,
2489 Register rn,
2490 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002491 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002492 CheckIT(cond);
2493 if (operand.IsImmediate()) {
2494 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002495 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002496 // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08002497 if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002498 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2499 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2500 AdvanceIT();
2501 return;
2502 }
2503 // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002504 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002505 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002506 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2507 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2508 AdvanceIT();
2509 return;
2510 }
2511 // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
Vincent Belliard942e3b72016-11-29 15:50:14 -08002512 if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002513 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2514 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2515 AdvanceIT();
2516 return;
2517 }
2518 }
2519 }
2520 Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2521}
2522
2523void Assembler::adr(Condition cond,
2524 EncodingSize size,
2525 Register rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002526 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002527 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002528 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002529 Location::Offset offset =
2530 location->IsBound()
2531 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01002532 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2533 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002534 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002535 int32_t neg_offset = -offset;
2536 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2537 if (!size.IsWide() && rd.IsLow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002538 ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002539 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002540 (!location->IsBound() && size.IsNarrow()))) {
2541 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002542 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002543 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002544 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002545 Location::Offset pc,
2546 const Location* location) const VIXL_OVERRIDE {
2547 pc += kT32PcDelta;
2548 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002549 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2550 ((offset & 0x3) == 0));
2551 const int32_t target = offset >> 2;
2552 return instr | (target & 0xff);
2553 }
2554 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002555 EmitT32_16(
Vincent Belliardac285442017-05-16 09:26:45 -07002556 Link(0xa000 | (rd.GetCode() << 8), location, immop, &kT16DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002557 AdvanceIT();
2558 return;
2559 }
2560 // ADR{<c>}{<q>} <Rd>, <label> ; T2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002561 if (!size.IsNarrow() && location->IsBound() && (neg_offset > 0) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002562 (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002563 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2564 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2565 AdvanceIT();
2566 return;
2567 }
2568 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2569 if (!size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002570 (!location->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002571 (!rd.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002572 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002573 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002574 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002575 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002576 Location::Offset pc,
2577 const Location* location) const VIXL_OVERRIDE {
2578 pc += kT32PcDelta;
2579 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002580 int32_t target;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00002581 if ((offset >= 0) && (offset <= 4095)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002582 target = offset;
2583 } else {
2584 target = -offset;
2585 VIXL_ASSERT((target >= 0) && (target <= 4095));
2586 // Emit the T2 encoding.
2587 instr |= 0x00a00000;
2588 }
2589 return instr | (target & 0xff) | ((target & 0x700) << 4) |
2590 ((target & 0x800) << 15);
2591 }
2592 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002593 EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8),
2594 location,
2595 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07002596 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002597 AdvanceIT();
2598 return;
2599 }
2600 } else {
2601 ImmediateA32 positive_immediate_a32(offset);
2602 ImmediateA32 negative_immediate_a32(-offset);
2603 // ADR{<c>}{<q>} <Rd>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002604 if ((!location->IsBound() || positive_immediate_a32.IsValid()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002605 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002606 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002607 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002608 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002609 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002610 Location::Offset pc,
2611 const Location* location) const VIXL_OVERRIDE {
2612 pc += kA32PcDelta;
2613 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002614 int32_t target;
2615 ImmediateA32 positive_immediate_a32(offset);
2616 if (positive_immediate_a32.IsValid()) {
2617 target = positive_immediate_a32.GetEncodingValue();
2618 } else {
2619 ImmediateA32 negative_immediate_a32(-offset);
2620 VIXL_ASSERT(negative_immediate_a32.IsValid());
2621 // Emit the A2 encoding.
2622 target = negative_immediate_a32.GetEncodingValue();
2623 instr = (instr & ~0x00f00000) | 0x00400000;
2624 }
2625 return instr | (target & 0xfff);
2626 }
2627 } immop;
2628 EmitA32(
2629 Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002630 location,
2631 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07002632 &kA32AdrInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002633 return;
2634 }
2635 // ADR{<c>}{<q>} <Rd>, <label> ; A2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002636 if (location->IsBound() && negative_immediate_a32.IsValid() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002637 cond.IsNotNever()) {
2638 EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2639 negative_immediate_a32.GetEncodingValue());
2640 return;
2641 }
2642 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002643 Delegate(kAdr, &Assembler::adr, cond, size, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002644}
2645
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002646bool Assembler::adr_info(Condition cond,
2647 EncodingSize size,
2648 Register rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002649 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002650 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002651 VIXL_ASSERT(!location->IsBound());
2652 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002653 if (IsUsingT32()) {
2654 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2655 if (!size.IsWide() && rd.IsLow() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002656 *info = &kT16DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002657 return true;
2658 }
2659 // Skipped T2, as it is a negative offset variant.
2660 // The minimum offset is included in the corresponding
2661 // positive variant.
2662 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2663 if (!size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002664 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002665 return true;
2666 }
2667 } else {
2668 // ADR{<c>}{<q>} <Rd>, <label> ; A1
2669 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002670 *info = &kA32AdrInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002671 return true;
2672 }
2673 // Skipped A2, as it is a negative offset variant.
2674 // The minimum offset is included in the corresponding
2675 // positive variant.
2676 }
2677 return false;
2678}
2679
Alexandre Ramesd3832962016-07-04 15:03:43 +01002680void Assembler::and_(Condition cond,
2681 EncodingSize size,
2682 Register rd,
2683 Register rn,
2684 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002685 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002686 CheckIT(cond);
2687 if (operand.IsImmediate()) {
2688 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002689 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002690 ImmediateT32 immediate_t32(imm);
2691 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00002692 if (!size.IsNarrow() && immediate_t32.IsValid() &&
2693 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002694 EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2695 (immediate_t32.GetEncodingValue() & 0xff) |
2696 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2697 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2698 AdvanceIT();
2699 return;
2700 }
2701 } else {
2702 ImmediateA32 immediate_a32(imm);
2703 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2704 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2705 EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2706 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2707 immediate_a32.GetEncodingValue());
2708 return;
2709 }
2710 }
2711 }
2712 if (operand.IsImmediateShiftedRegister()) {
2713 Register rm = operand.GetBaseRegister();
2714 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002715 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002716 // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2717 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2718 rm.IsLow()) {
2719 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2720 AdvanceIT();
2721 return;
2722 }
2723 }
2724 }
2725 Shift shift = operand.GetShift();
2726 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002727 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002728 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00002729 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2730 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002731 uint32_t amount_ = amount % 32;
2732 EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2733 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2734 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2735 AdvanceIT();
2736 return;
2737 }
2738 } else {
2739 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2740 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2741 uint32_t amount_ = amount % 32;
2742 EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2743 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2744 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2745 return;
2746 }
2747 }
2748 }
2749 if (operand.IsRegisterShiftedRegister()) {
2750 Register rm = operand.GetBaseRegister();
2751 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002752 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002753 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002754 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002755 if (cond.IsNotNever() &&
2756 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2757 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002758 EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2759 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002760 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002761 return;
2762 }
2763 }
2764 }
2765 Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2766}
2767
2768void Assembler::ands(Condition cond,
2769 EncodingSize size,
2770 Register rd,
2771 Register rn,
2772 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002773 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002774 CheckIT(cond);
2775 if (operand.IsImmediate()) {
2776 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002777 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002778 ImmediateT32 immediate_t32(imm);
2779 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00002780 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
2781 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002782 EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2783 (immediate_t32.GetEncodingValue() & 0xff) |
2784 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2785 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2786 AdvanceIT();
2787 return;
2788 }
2789 } else {
2790 ImmediateA32 immediate_a32(imm);
2791 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2792 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2793 EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2794 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2795 immediate_a32.GetEncodingValue());
2796 return;
2797 }
2798 }
2799 }
2800 if (operand.IsImmediateShiftedRegister()) {
2801 Register rm = operand.GetBaseRegister();
2802 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002803 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002804 // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2805 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2806 rm.IsLow()) {
2807 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2808 AdvanceIT();
2809 return;
2810 }
2811 }
2812 }
2813 Shift shift = operand.GetShift();
2814 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002815 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002816 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00002817 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
2818 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002819 uint32_t amount_ = amount % 32;
2820 EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2821 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2822 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2823 AdvanceIT();
2824 return;
2825 }
2826 } else {
2827 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2828 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2829 uint32_t amount_ = amount % 32;
2830 EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2831 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2832 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2833 return;
2834 }
2835 }
2836 }
2837 if (operand.IsRegisterShiftedRegister()) {
2838 Register rm = operand.GetBaseRegister();
2839 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002840 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002841 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002842 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002843 if (cond.IsNotNever() &&
2844 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2845 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002846 EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2847 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002848 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002849 return;
2850 }
2851 }
2852 }
2853 Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2854}
2855
2856void Assembler::asr(Condition cond,
2857 EncodingSize size,
2858 Register rd,
2859 Register rm,
2860 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002861 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002862 CheckIT(cond);
2863 if (operand.IsImmediate()) {
2864 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002865 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002866 // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2867 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2868 (imm >= 1) && (imm <= 32)) {
2869 uint32_t amount_ = imm % 32;
2870 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2871 (amount_ << 6));
2872 AdvanceIT();
2873 return;
2874 }
2875 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002876 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2877 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002878 uint32_t amount_ = imm % 32;
2879 EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2880 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2881 AdvanceIT();
2882 return;
2883 }
2884 } else {
2885 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2886 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2887 uint32_t amount_ = imm % 32;
2888 EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2889 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2890 return;
2891 }
2892 }
2893 }
2894 if (operand.IsPlainRegister()) {
2895 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002896 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002897 // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2898 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2899 rs.IsLow()) {
2900 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2901 AdvanceIT();
2902 return;
2903 }
2904 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002905 if (!size.IsNarrow() &&
2906 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002907 EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2908 rs.GetCode());
2909 AdvanceIT();
2910 return;
2911 }
2912 } else {
2913 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002914 if (cond.IsNotNever() &&
2915 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002916 EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2917 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2918 return;
2919 }
2920 }
2921 }
2922 Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2923}
2924
2925void Assembler::asrs(Condition cond,
2926 EncodingSize size,
2927 Register rd,
2928 Register rm,
2929 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002930 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002931 CheckIT(cond);
2932 if (operand.IsImmediate()) {
2933 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002934 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002935 // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2936 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2937 (imm >= 1) && (imm <= 32)) {
2938 uint32_t amount_ = imm % 32;
2939 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2940 (amount_ << 6));
2941 AdvanceIT();
2942 return;
2943 }
2944 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002945 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2946 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002947 uint32_t amount_ = imm % 32;
2948 EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2949 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2950 AdvanceIT();
2951 return;
2952 }
2953 } else {
2954 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2955 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2956 uint32_t amount_ = imm % 32;
2957 EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2958 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2959 return;
2960 }
2961 }
2962 }
2963 if (operand.IsPlainRegister()) {
2964 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002965 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002966 // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2967 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2968 rs.IsLow()) {
2969 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2970 AdvanceIT();
2971 return;
2972 }
2973 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002974 if (!size.IsNarrow() &&
2975 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002976 EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2977 rs.GetCode());
2978 AdvanceIT();
2979 return;
2980 }
2981 } else {
2982 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002983 if (cond.IsNotNever() &&
2984 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002985 EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
2986 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2987 return;
2988 }
2989 }
2990 }
2991 Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
2992}
2993
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002994void Assembler::b(Condition cond, EncodingSize size, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002995 VIXL_ASSERT(AllowAssembler());
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002996 Location::Offset offset =
2997 location->IsBound()
2998 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01002999 (GetCursorOffset() + GetArchitectureStatePCOffset())
3000 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003001 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003002 // B<c>{<q>} <label> ; T1
3003 if (OutsideITBlock() && !size.IsWide() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003004 ((location->IsBound() && (offset >= -256) && (offset <= 254) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003005 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003006 (!location->IsBound() && size.IsNarrow())) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003007 !cond.Is(al) && cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003008 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003009 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003010 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003011 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003012 Location::Offset pc,
3013 const Location* location) const VIXL_OVERRIDE {
3014 pc += kT32PcDelta;
3015 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003016 VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
3017 ((offset & 0x1) == 0));
3018 const int32_t target = offset >> 1;
3019 return instr | (target & 0xff);
3020 }
3021 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003022 EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8),
3023 location,
3024 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003025 &kT16ConditionalBranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003026 AdvanceIT();
3027 return;
3028 }
3029 // B{<c>}{<q>} <label> ; T2
3030 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003031 ((location->IsBound() && (offset >= -2048) && (offset <= 2046) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003032 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003033 (!location->IsBound() && size.IsNarrow()))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003034 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003035 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003036 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003037 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003038 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003039 Location::Offset pc,
3040 const Location* location) const VIXL_OVERRIDE {
3041 pc += kT32PcDelta;
3042 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003043 VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
3044 ((offset & 0x1) == 0));
3045 const int32_t target = offset >> 1;
3046 return instr | (target & 0x7ff);
3047 }
3048 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003049 EmitT32_16(Link(0xe000, location, immop, &kT16BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003050 AdvanceIT();
3051 return;
3052 }
3053 // B<c>{<q>} <label> ; T3
3054 if (OutsideITBlock() && !size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003055 ((location->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003056 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003057 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003058 !cond.Is(al) && cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003059 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003060 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003061 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003062 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003063 Location::Offset pc,
3064 const Location* location) const VIXL_OVERRIDE {
3065 pc += kT32PcDelta;
3066 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003067 VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
3068 ((offset & 0x1) == 0));
3069 const int32_t target = offset >> 1;
3070 return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
3071 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
3072 ((target & 0x80000) << 7);
3073 }
3074 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003075 EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22),
3076 location,
3077 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003078 &kT32ConditionalBranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003079 AdvanceIT();
3080 return;
3081 }
3082 // B{<c>}{<q>} <label> ; T4
3083 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003084 ((location->IsBound() && (offset >= -16777216) &&
3085 (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3086 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003087 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003088 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003089 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003090 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003091 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003092 Location::Offset pc,
3093 const Location* location) const VIXL_OVERRIDE {
3094 pc += kT32PcDelta;
3095 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003096 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3097 ((offset & 0x1) == 0));
3098 int32_t target = offset >> 1;
3099 uint32_t S = target & (1 << 23);
3100 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3101 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3102 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3103 ((target & 0x800000) << 3);
3104 }
3105 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003106 EmitT32_32(Link(0xf0009000U, location, immop, &kT32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003107 AdvanceIT();
3108 return;
3109 }
3110 } else {
3111 // B{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003112 if (((location->IsBound() && (offset >= -33554432) &&
3113 (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3114 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003115 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003116 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003117 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003118 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003119 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003120 Location::Offset pc,
3121 const Location* location) const VIXL_OVERRIDE {
3122 pc += kA32PcDelta;
3123 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003124 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3125 ((offset & 0x3) == 0));
3126 const int32_t target = offset >> 2;
3127 return instr | (target & 0xffffff);
3128 }
3129 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003130 EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28),
3131 location,
3132 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003133 &kA32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003134 return;
3135 }
3136 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003137 Delegate(kB, &Assembler::b, cond, size, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003138}
3139
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003140bool Assembler::b_info(Condition cond,
3141 EncodingSize size,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003142 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003143 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003144 VIXL_ASSERT(!location->IsBound());
3145 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003146 if (IsUsingT32()) {
3147 // B<c>{<q>} <label> ; T1
3148 if (OutsideITBlock() && !size.IsWide() && size.IsNarrow() && !cond.Is(al) &&
3149 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003150 *info = &kT16ConditionalBranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003151 return true;
3152 }
3153 // B{<c>}{<q>} <label> ; T2
3154 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003155 *info = &kT16BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003156 return true;
3157 }
3158 // B<c>{<q>} <label> ; T3
3159 if (OutsideITBlock() && !size.IsNarrow() && !cond.Is(al) &&
3160 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003161 *info = &kT32ConditionalBranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003162 return true;
3163 }
3164 // B{<c>}{<q>} <label> ; T4
3165 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003166 *info = &kT32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003167 return true;
3168 }
3169 } else {
3170 // B{<c>}{<q>} <label> ; A1
3171 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003172 *info = &kA32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003173 return true;
3174 }
3175 }
3176 return false;
3177}
3178
Vincent Belliard609821f2017-02-08 14:17:25 -08003179void Assembler::bfc(Condition cond, Register rd, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003180 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003181 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08003182 if (IsUsingT32()) {
3183 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003184 if ((lsb <= 31) && (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3185 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003186 uint32_t msb = lsb + width - 1;
3187 EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
3188 ((lsb & 0x1c) << 10) | msb);
3189 AdvanceIT();
3190 return;
3191 }
3192 } else {
3193 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
3194 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003195 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3196 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003197 uint32_t msb = lsb + width - 1;
3198 EmitA32(0x07c0001fU | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3199 (lsb << 7) | (msb << 16));
3200 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003201 }
3202 }
Vincent Belliard609821f2017-02-08 14:17:25 -08003203 Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003204}
3205
Vincent Belliard609821f2017-02-08 14:17:25 -08003206void Assembler::bfi(
3207 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003208 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003209 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08003210 if (IsUsingT32()) {
3211 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
3212 if ((lsb <= 31) && !rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003213 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3214 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003215 uint32_t msb = lsb + width - 1;
3216 EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3217 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
3218 AdvanceIT();
3219 return;
3220 }
3221 } else {
3222 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
3223 if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003224 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3225 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003226 uint32_t msb = lsb + width - 1;
3227 EmitA32(0x07c00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3228 rn.GetCode() | (lsb << 7) | (msb << 16));
3229 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003230 }
3231 }
Vincent Belliard609821f2017-02-08 14:17:25 -08003232 Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003233}
3234
3235void Assembler::bic(Condition cond,
3236 EncodingSize size,
3237 Register rd,
3238 Register rn,
3239 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003240 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003241 CheckIT(cond);
3242 if (operand.IsImmediate()) {
3243 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003244 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003245 ImmediateT32 immediate_t32(imm);
3246 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003247 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3248 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003249 EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3250 (immediate_t32.GetEncodingValue() & 0xff) |
3251 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3252 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3253 AdvanceIT();
3254 return;
3255 }
3256 } else {
3257 ImmediateA32 immediate_a32(imm);
3258 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3259 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3260 EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3261 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3262 immediate_a32.GetEncodingValue());
3263 return;
3264 }
3265 }
3266 }
3267 if (operand.IsImmediateShiftedRegister()) {
3268 Register rm = operand.GetBaseRegister();
3269 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003270 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003271 // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3272 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3273 rm.IsLow()) {
3274 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3275 AdvanceIT();
3276 return;
3277 }
3278 }
3279 }
3280 Shift shift = operand.GetShift();
3281 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003282 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003283 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003284 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3285 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003286 uint32_t amount_ = amount % 32;
3287 EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3288 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3289 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3290 AdvanceIT();
3291 return;
3292 }
3293 } else {
3294 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3295 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3296 uint32_t amount_ = amount % 32;
3297 EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3298 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3299 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3300 return;
3301 }
3302 }
3303 }
3304 if (operand.IsRegisterShiftedRegister()) {
3305 Register rm = operand.GetBaseRegister();
3306 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003307 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003308 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003309 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00003310 if (cond.IsNotNever() &&
3311 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3312 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003313 EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3314 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003315 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003316 return;
3317 }
3318 }
3319 }
3320 Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3321}
3322
3323void Assembler::bics(Condition cond,
3324 EncodingSize size,
3325 Register rd,
3326 Register rn,
3327 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003328 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003329 CheckIT(cond);
3330 if (operand.IsImmediate()) {
3331 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003332 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003333 ImmediateT32 immediate_t32(imm);
3334 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003335 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3336 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003337 EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3338 (immediate_t32.GetEncodingValue() & 0xff) |
3339 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3340 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3341 AdvanceIT();
3342 return;
3343 }
3344 } else {
3345 ImmediateA32 immediate_a32(imm);
3346 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3347 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3348 EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3349 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3350 immediate_a32.GetEncodingValue());
3351 return;
3352 }
3353 }
3354 }
3355 if (operand.IsImmediateShiftedRegister()) {
3356 Register rm = operand.GetBaseRegister();
3357 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003358 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003359 // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3360 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3361 rm.IsLow()) {
3362 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3363 AdvanceIT();
3364 return;
3365 }
3366 }
3367 }
3368 Shift shift = operand.GetShift();
3369 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003370 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003371 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003372 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3373 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003374 uint32_t amount_ = amount % 32;
3375 EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3376 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3377 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3378 AdvanceIT();
3379 return;
3380 }
3381 } else {
3382 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3383 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3384 uint32_t amount_ = amount % 32;
3385 EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3386 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3387 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3388 return;
3389 }
3390 }
3391 }
3392 if (operand.IsRegisterShiftedRegister()) {
3393 Register rm = operand.GetBaseRegister();
3394 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003395 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003396 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003397 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00003398 if (cond.IsNotNever() &&
3399 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3400 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003401 EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3402 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003403 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003404 return;
3405 }
3406 }
3407 }
3408 Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3409}
3410
3411void Assembler::bkpt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003412 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003413 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003414 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003415 // BKPT{<q>} {#}<imm> ; T1
3416 if ((imm <= 255)) {
3417 EmitT32_16(0xbe00 | imm);
3418 AdvanceIT();
3419 return;
3420 }
3421 } else {
3422 // BKPT{<q>} {#}<imm> ; A1
3423 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3424 EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3425 ((imm & 0xfff0) << 4));
3426 return;
3427 }
3428 }
3429 Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3430}
3431
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003432void Assembler::bl(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003433 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003434 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003435 Location::Offset offset =
3436 location->IsBound()
3437 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003438 (GetCursorOffset() + GetArchitectureStatePCOffset())
3439 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003440 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003441 // BL{<c>}{<q>} <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003442 if (((location->IsBound() && (offset >= -16777216) &&
3443 (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3444 !location->IsBound()) &&
Pierre Langloisdc626f32017-02-15 13:31:28 +00003445 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003446 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003447 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003448 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003449 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003450 Location::Offset pc,
3451 const Location* location) const VIXL_OVERRIDE {
3452 pc += kT32PcDelta;
3453 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003454 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3455 ((offset & 0x1) == 0));
3456 int32_t target = offset >> 1;
3457 uint32_t S = target & (1 << 23);
3458 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3459 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3460 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3461 ((target & 0x800000) << 3);
3462 }
3463 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003464 EmitT32_32(Link(0xf000d000U, location, immop, &kT32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003465 AdvanceIT();
3466 return;
3467 }
3468 } else {
3469 // BL{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003470 if (((location->IsBound() && (offset >= -33554432) &&
3471 (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3472 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003473 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003474 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003475 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003476 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003477 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003478 Location::Offset pc,
3479 const Location* location) const VIXL_OVERRIDE {
3480 pc += kA32PcDelta;
3481 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003482 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3483 ((offset & 0x3) == 0));
3484 const int32_t target = offset >> 2;
3485 return instr | (target & 0xffffff);
3486 }
3487 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003488 EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28),
3489 location,
3490 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003491 &kA32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003492 return;
3493 }
3494 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003495 Delegate(kBl, &Assembler::bl, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003496}
3497
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003498bool Assembler::bl_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003499 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003500 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003501 VIXL_ASSERT(!location->IsBound());
3502 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003503 if (IsUsingT32()) {
3504 // BL{<c>}{<q>} <label> ; T1
3505 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003506 *info = &kT32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003507 return true;
3508 }
3509 } else {
3510 // BL{<c>}{<q>} <label> ; A1
3511 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003512 *info = &kA32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003513 return true;
3514 }
3515 }
3516 return false;
3517}
3518
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003519void Assembler::blx(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003520 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003521 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003522 Location::Offset offset =
3523 location->IsBound()
3524 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003525 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3526 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003527 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003528 // BLX{<c>}{<q>} <label> ; T2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003529 if (((location->IsBound() && (offset >= -16777216) &&
3530 (offset <= 16777212) && ((offset & 0x3) == 0)) ||
3531 !location->IsBound()) &&
Pierre Langloisdc626f32017-02-15 13:31:28 +00003532 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003533 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003534 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003535 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003536 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003537 Location::Offset pc,
3538 const Location* location) const VIXL_OVERRIDE {
3539 pc += kT32PcDelta;
3540 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003541 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3542 ((offset & 0x3) == 0));
3543 int32_t target = offset >> 2;
3544 uint32_t S = target & (1 << 22);
3545 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3546 return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3547 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3548 ((target & 0x400000) << 4);
3549 }
3550 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003551 EmitT32_32(Link(0xf000c000U, location, immop, &kT32BlxInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003552 AdvanceIT();
3553 return;
3554 }
3555 } else {
3556 // BLX{<c>}{<q>} <label> ; A2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003557 if (((location->IsBound() && (offset >= -33554432) &&
3558 (offset <= 33554430) && ((offset & 0x1) == 0)) ||
3559 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003560 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003561 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003562 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003563 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003564 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003565 Location::Offset pc,
3566 const Location* location) const
3567 VIXL_OVERRIDE {
3568 pc += kA32PcDelta;
3569 Location::Offset offset =
3570 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003571 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3572 ((offset & 0x1) == 0));
3573 const int32_t target = offset >> 1;
3574 return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3575 }
3576 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003577 EmitA32(Link(0xfa000000U, location, immop, &kA32BlxInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003578 return;
3579 }
3580 }
3581 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003582 Delegate(kBlx, &Assembler::blx, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003583}
3584
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003585bool Assembler::blx_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003586 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003587 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003588 VIXL_ASSERT(!location->IsBound());
3589 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003590 USE(cond);
3591 if (IsUsingT32()) {
3592 // BLX{<c>}{<q>} <label> ; T2
3593 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003594 *info = &kT32BlxInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003595 return true;
3596 }
3597 } else {
3598 // BLX{<c>}{<q>} <label> ; A2
3599 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003600 *info = &kA32BlxInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003601 return true;
3602 }
3603 }
3604 return false;
3605}
3606
Alexandre Ramesd3832962016-07-04 15:03:43 +01003607void Assembler::blx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003608 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003609 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003610 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003611 // BLX{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003612 if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3613 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003614 EmitT32_16(0x4780 | (rm.GetCode() << 3));
3615 AdvanceIT();
3616 return;
3617 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003618 } else {
3619 // BLX{<c>}{<q>} <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003620 if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003621 EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3622 return;
3623 }
3624 }
3625 Delegate(kBlx, &Assembler::blx, cond, rm);
3626}
3627
3628void Assembler::bx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003629 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003630 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003631 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003632 // BX{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003633 if ((OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3634 EmitT32_16(0x4700 | (rm.GetCode() << 3));
3635 AdvanceIT();
3636 return;
3637 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003638 } else {
3639 // BX{<c>}{<q>} <Rm> ; A1
3640 if (cond.IsNotNever()) {
3641 EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3642 return;
3643 }
3644 }
3645 Delegate(kBx, &Assembler::bx, cond, rm);
3646}
3647
3648void Assembler::bxj(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003649 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003650 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003652 // BXJ{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003653 if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3654 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003655 EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3656 AdvanceIT();
3657 return;
3658 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003659 } else {
3660 // BXJ{<c>}{<q>} <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003661 if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003662 EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3663 return;
3664 }
3665 }
3666 Delegate(kBxj, &Assembler::bxj, cond, rm);
3667}
3668
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003669void Assembler::cbnz(Register rn, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003670 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003671 CheckIT(al);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003672 Location::Offset offset =
3673 location->IsBound()
3674 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003675 (GetCursorOffset() + GetArchitectureStatePCOffset())
3676 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003677 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003678 // CBNZ{<q>} <Rn>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003679 if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3680 (offset <= 126) && ((offset & 0x1) == 0)) ||
3681 !location->IsBound())) {
3682 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003683 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003684 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003685 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003686 Location::Offset pc,
3687 const Location* location) const VIXL_OVERRIDE {
3688 pc += kT32PcDelta;
3689 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003690 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3691 ((offset & 0x1) == 0));
3692 const int32_t target = offset >> 1;
3693 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3694 }
3695 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003696 EmitT32_16(Link(0xb900 | rn.GetCode(), location, immop, &kT16CbzInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003697 AdvanceIT();
3698 return;
3699 }
3700 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003701 Delegate(kCbnz, &Assembler::cbnz, rn, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003702}
3703
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003704bool Assembler::cbnz_info(Register rn,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003705 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003706 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003707 VIXL_ASSERT(!location->IsBound());
3708 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003709 if (IsUsingT32()) {
3710 // CBNZ{<q>} <Rn>, <label> ; T1
3711 if (rn.IsLow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003712 *info = &kT16CbzInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003713 return true;
3714 }
3715 }
3716 return false;
3717}
3718
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003719void Assembler::cbz(Register rn, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003721 CheckIT(al);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003722 Location::Offset offset =
3723 location->IsBound()
3724 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003725 (GetCursorOffset() + GetArchitectureStatePCOffset())
3726 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003727 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003728 // CBZ{<q>} <Rn>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003729 if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3730 (offset <= 126) && ((offset & 0x1) == 0)) ||
3731 !location->IsBound())) {
3732 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003733 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003734 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003735 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003736 Location::Offset pc,
3737 const Location* location) const VIXL_OVERRIDE {
3738 pc += kT32PcDelta;
3739 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003740 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3741 ((offset & 0x1) == 0));
3742 const int32_t target = offset >> 1;
3743 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3744 }
3745 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003746 EmitT32_16(Link(0xb100 | rn.GetCode(), location, immop, &kT16CbzInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003747 AdvanceIT();
3748 return;
3749 }
3750 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003751 Delegate(kCbz, &Assembler::cbz, rn, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003752}
3753
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003754bool Assembler::cbz_info(Register rn,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003755 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003756 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003757 VIXL_ASSERT(!location->IsBound());
3758 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003759 if (IsUsingT32()) {
3760 // CBZ{<q>} <Rn>, <label> ; T1
3761 if (rn.IsLow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003762 *info = &kT16CbzInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003763 return true;
3764 }
3765 }
3766 return false;
3767}
3768
Alexandre Ramesd3832962016-07-04 15:03:43 +01003769void Assembler::clrex(Condition cond) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003770 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003771 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003772 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003773 // CLREX{<c>}{<q>} ; T1
3774 EmitT32_32(0xf3bf8f2fU);
3775 AdvanceIT();
3776 return;
3777 } else {
3778 // CLREX{<c>}{<q>} ; A1
3779 if (cond.Is(al)) {
3780 EmitA32(0xf57ff01fU);
3781 return;
3782 }
3783 }
3784 Delegate(kClrex, &Assembler::clrex, cond);
3785}
3786
3787void Assembler::clz(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003788 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003789 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003790 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003791 // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
Georgia Kouvelie99f34d2016-12-21 17:00:29 +00003792 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3793 EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3794 (rm.GetCode() << 16));
3795 AdvanceIT();
3796 return;
3797 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003798 } else {
3799 // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
Georgia Kouvelie99f34d2016-12-21 17:00:29 +00003800 if (cond.IsNotNever() &&
3801 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003802 EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3803 rm.GetCode());
3804 return;
3805 }
3806 }
3807 Delegate(kClz, &Assembler::clz, cond, rd, rm);
3808}
3809
3810void Assembler::cmn(Condition cond,
3811 EncodingSize size,
3812 Register rn,
3813 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003814 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003815 CheckIT(cond);
3816 if (operand.IsImmediate()) {
3817 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003818 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003819 ImmediateT32 immediate_t32(imm);
3820 // CMN{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003821 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3822 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003823 EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3824 (immediate_t32.GetEncodingValue() & 0xff) |
3825 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3826 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3827 AdvanceIT();
3828 return;
3829 }
3830 } else {
3831 ImmediateA32 immediate_a32(imm);
3832 // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3833 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3834 EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3835 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3836 return;
3837 }
3838 }
3839 }
3840 if (operand.IsImmediateShiftedRegister()) {
3841 Register rm = operand.GetBaseRegister();
3842 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003844 // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3845 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3846 EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3847 AdvanceIT();
3848 return;
3849 }
3850 }
3851 }
3852 Shift shift = operand.GetShift();
3853 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003854 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003855 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003856 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3857 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003858 uint32_t amount_ = amount % 32;
3859 EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3860 (operand.GetTypeEncodingValue() << 4) |
3861 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3862 AdvanceIT();
3863 return;
3864 }
3865 } else {
3866 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3867 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3868 uint32_t amount_ = amount % 32;
3869 EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3870 (rn.GetCode() << 16) | rm.GetCode() |
3871 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3872 return;
3873 }
3874 }
3875 }
3876 if (operand.IsRegisterShiftedRegister()) {
3877 Register rm = operand.GetBaseRegister();
3878 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003879 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003880 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003881 // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003882 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00003883 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003884 EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3885 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003886 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003887 return;
3888 }
3889 }
3890 }
3891 Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3892}
3893
3894void Assembler::cmp(Condition cond,
3895 EncodingSize size,
3896 Register rn,
3897 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003898 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003899 CheckIT(cond);
3900 if (operand.IsImmediate()) {
3901 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003902 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003903 ImmediateT32 immediate_t32(imm);
3904 // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3905 if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3906 EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3907 AdvanceIT();
3908 return;
3909 }
3910 // CMP{<c>}{<q>} <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003911 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3912 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003913 EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3914 (immediate_t32.GetEncodingValue() & 0xff) |
3915 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3916 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3917 AdvanceIT();
3918 return;
3919 }
3920 } else {
3921 ImmediateA32 immediate_a32(imm);
3922 // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3923 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3924 EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3925 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3926 return;
3927 }
3928 }
3929 }
3930 if (operand.IsImmediateShiftedRegister()) {
3931 Register rm = operand.GetBaseRegister();
3932 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003933 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003934 // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3935 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3936 EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3937 AdvanceIT();
3938 return;
3939 }
3940 // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003941 if (!size.IsWide() &&
3942 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003943 EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3944 ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3945 AdvanceIT();
3946 return;
3947 }
3948 }
3949 }
3950 Shift shift = operand.GetShift();
3951 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003952 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003953 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +00003954 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3955 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003956 uint32_t amount_ = amount % 32;
3957 EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3958 (operand.GetTypeEncodingValue() << 4) |
3959 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3960 AdvanceIT();
3961 return;
3962 }
3963 } else {
3964 // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3965 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3966 uint32_t amount_ = amount % 32;
3967 EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3968 (rn.GetCode() << 16) | rm.GetCode() |
3969 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3970 return;
3971 }
3972 }
3973 }
3974 if (operand.IsRegisterShiftedRegister()) {
3975 Register rm = operand.GetBaseRegister();
3976 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003977 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003978 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003979 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003980 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00003981 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003982 EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3983 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003984 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003985 return;
3986 }
3987 }
3988 }
3989 Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
3990}
3991
3992void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003993 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003994 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003995 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003996 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07003997 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
3998 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003999 EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4000 rm.GetCode());
4001 AdvanceIT();
4002 return;
4003 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004004 } else {
4005 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004006 if ((cond.Is(al) || AllowUnpredictable()) &&
4007 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004008 EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4009 (rn.GetCode() << 16) | rm.GetCode());
4010 return;
4011 }
4012 }
4013 Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
4014}
4015
4016void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004017 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004018 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004019 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004020 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004021 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4022 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004023 EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4024 rm.GetCode());
4025 AdvanceIT();
4026 return;
4027 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004028 } else {
4029 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004030 if ((cond.Is(al) || AllowUnpredictable()) &&
4031 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004032 EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4033 (rn.GetCode() << 16) | rm.GetCode());
4034 return;
4035 }
4036 }
4037 Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
4038}
4039
4040void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004041 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004042 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004043 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004044 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004045 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4046 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004047 EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4048 rm.GetCode());
4049 AdvanceIT();
4050 return;
4051 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004052 } else {
4053 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004054 if ((cond.Is(al) || AllowUnpredictable()) &&
4055 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004056 EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4057 (rn.GetCode() << 16) | rm.GetCode());
4058 return;
4059 }
4060 }
4061 Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
4062}
4063
4064void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004065 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004066 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004067 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004068 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004069 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4070 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004071 EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4072 rm.GetCode());
4073 AdvanceIT();
4074 return;
4075 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004076 } else {
4077 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004078 if ((cond.Is(al) || AllowUnpredictable()) &&
4079 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004080 EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4081 (rn.GetCode() << 16) | rm.GetCode());
4082 return;
4083 }
4084 }
4085 Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
4086}
4087
4088void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004089 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004090 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004091 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004092 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004093 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4094 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004095 EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4096 rm.GetCode());
4097 AdvanceIT();
4098 return;
4099 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004100 } else {
4101 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004102 if ((cond.Is(al) || AllowUnpredictable()) &&
4103 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004104 EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4105 (rn.GetCode() << 16) | rm.GetCode());
4106 return;
4107 }
4108 }
4109 Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
4110}
4111
4112void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004113 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004114 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004115 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004116 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004117 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4118 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004119 EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4120 rm.GetCode());
4121 AdvanceIT();
4122 return;
4123 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004124 } else {
4125 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004126 if ((cond.Is(al) || AllowUnpredictable()) &&
4127 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004128 EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4129 (rn.GetCode() << 16) | rm.GetCode());
4130 return;
4131 }
4132 }
4133 Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
4134}
4135
4136void Assembler::dmb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004137 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004138 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004139 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004140 // DMB{<c>}{<q>} {<option>} ; T1
4141 EmitT32_32(0xf3bf8f50U | option.GetType());
4142 AdvanceIT();
4143 return;
4144 } else {
4145 // DMB{<c>}{<q>} {<option>} ; A1
4146 if (cond.Is(al)) {
4147 EmitA32(0xf57ff050U | option.GetType());
4148 return;
4149 }
4150 }
4151 Delegate(kDmb, &Assembler::dmb, cond, option);
4152}
4153
4154void Assembler::dsb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004155 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004156 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004157 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004158 // DSB{<c>}{<q>} {<option>} ; T1
4159 EmitT32_32(0xf3bf8f40U | option.GetType());
4160 AdvanceIT();
4161 return;
4162 } else {
4163 // DSB{<c>}{<q>} {<option>} ; A1
4164 if (cond.Is(al)) {
4165 EmitA32(0xf57ff040U | option.GetType());
4166 return;
4167 }
4168 }
4169 Delegate(kDsb, &Assembler::dsb, cond, option);
4170}
4171
4172void Assembler::eor(Condition cond,
4173 EncodingSize size,
4174 Register rd,
4175 Register rn,
4176 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004177 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004178 CheckIT(cond);
4179 if (operand.IsImmediate()) {
4180 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004181 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004182 ImmediateT32 immediate_t32(imm);
4183 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004184 if (!size.IsNarrow() && immediate_t32.IsValid() &&
4185 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004186 EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4187 (immediate_t32.GetEncodingValue() & 0xff) |
4188 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4189 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4190 AdvanceIT();
4191 return;
4192 }
4193 } else {
4194 ImmediateA32 immediate_a32(imm);
4195 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4196 if (immediate_a32.IsValid() && cond.IsNotNever()) {
4197 EmitA32(0x02200000U | (cond.GetCondition() << 28) |
4198 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4199 immediate_a32.GetEncodingValue());
4200 return;
4201 }
4202 }
4203 }
4204 if (operand.IsImmediateShiftedRegister()) {
4205 Register rm = operand.GetBaseRegister();
4206 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004207 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004208 // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4209 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4210 rm.IsLow()) {
4211 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4212 AdvanceIT();
4213 return;
4214 }
4215 }
4216 }
4217 Shift shift = operand.GetShift();
4218 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004219 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004220 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004221 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
4222 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004223 uint32_t amount_ = amount % 32;
4224 EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4225 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4226 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4227 AdvanceIT();
4228 return;
4229 }
4230 } else {
4231 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4232 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4233 uint32_t amount_ = amount % 32;
4234 EmitA32(0x00200000U | (cond.GetCondition() << 28) |
4235 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4236 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4237 return;
4238 }
4239 }
4240 }
4241 if (operand.IsRegisterShiftedRegister()) {
4242 Register rm = operand.GetBaseRegister();
4243 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00004244 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004245 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004246 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00004247 if (cond.IsNotNever() &&
4248 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4249 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004250 EmitA32(0x00200010U | (cond.GetCondition() << 28) |
4251 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00004252 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004253 return;
4254 }
4255 }
4256 }
4257 Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
4258}
4259
4260void Assembler::eors(Condition cond,
4261 EncodingSize size,
4262 Register rd,
4263 Register rn,
4264 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004265 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004266 CheckIT(cond);
4267 if (operand.IsImmediate()) {
4268 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004269 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004270 ImmediateT32 immediate_t32(imm);
4271 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004272 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
4273 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004274 EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4275 (immediate_t32.GetEncodingValue() & 0xff) |
4276 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4277 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4278 AdvanceIT();
4279 return;
4280 }
4281 } else {
4282 ImmediateA32 immediate_a32(imm);
4283 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4284 if (immediate_a32.IsValid() && cond.IsNotNever()) {
4285 EmitA32(0x02300000U | (cond.GetCondition() << 28) |
4286 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4287 immediate_a32.GetEncodingValue());
4288 return;
4289 }
4290 }
4291 }
4292 if (operand.IsImmediateShiftedRegister()) {
4293 Register rm = operand.GetBaseRegister();
4294 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004295 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004296 // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4297 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4298 rm.IsLow()) {
4299 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4300 AdvanceIT();
4301 return;
4302 }
4303 }
4304 }
4305 Shift shift = operand.GetShift();
4306 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004307 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004308 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004309 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
4310 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004311 uint32_t amount_ = amount % 32;
4312 EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4313 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4314 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4315 AdvanceIT();
4316 return;
4317 }
4318 } else {
4319 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4320 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4321 uint32_t amount_ = amount % 32;
4322 EmitA32(0x00300000U | (cond.GetCondition() << 28) |
4323 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4324 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4325 return;
4326 }
4327 }
4328 }
4329 if (operand.IsRegisterShiftedRegister()) {
4330 Register rm = operand.GetBaseRegister();
4331 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00004332 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004333 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004334 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00004335 if (cond.IsNotNever() &&
4336 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4337 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004338 EmitA32(0x00300010U | (cond.GetCondition() << 28) |
4339 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00004340 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004341 return;
4342 }
4343 }
4344 }
4345 Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
4346}
4347
4348void Assembler::fldmdbx(Condition cond,
4349 Register rn,
4350 WriteBack write_back,
4351 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004352 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004353 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004354 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004355 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4356 if (write_back.DoesWriteBack() &&
4357 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004358 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004359 AllowUnpredictable())) {
4360 const DRegister& dreg = dreglist.GetFirstDRegister();
4361 unsigned len = dreglist.GetLength() * 2;
4362 EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4363 (len & 0xff));
4364 AdvanceIT();
4365 return;
4366 }
4367 } else {
4368 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4369 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4370 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004371 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004372 AllowUnpredictable())) {
4373 const DRegister& dreg = dreglist.GetFirstDRegister();
4374 unsigned len = dreglist.GetLength() * 2;
4375 EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4376 dreg.Encode(22, 12) | (len & 0xff));
4377 return;
4378 }
4379 }
4380 Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
4381}
4382
4383void Assembler::fldmiax(Condition cond,
4384 Register rn,
4385 WriteBack write_back,
4386 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004387 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004388 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004389 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004390 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4391 if ((((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004392 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004393 AllowUnpredictable())) {
4394 const DRegister& dreg = dreglist.GetFirstDRegister();
4395 unsigned len = dreglist.GetLength() * 2;
4396 EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4397 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4398 (len & 0xff));
4399 AdvanceIT();
4400 return;
4401 }
4402 } else {
4403 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4404 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004405 (dreglist.GetLastDRegister().GetCode() < 16) &&
4406 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004407 AllowUnpredictable())) {
4408 const DRegister& dreg = dreglist.GetFirstDRegister();
4409 unsigned len = dreglist.GetLength() * 2;
4410 EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4411 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4412 (len & 0xff));
4413 return;
4414 }
4415 }
4416 Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4417}
4418
4419void Assembler::fstmdbx(Condition cond,
4420 Register rn,
4421 WriteBack write_back,
4422 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004423 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004424 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004425 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004426 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4427 if (write_back.DoesWriteBack() &&
4428 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004429 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004430 AllowUnpredictable())) {
4431 const DRegister& dreg = dreglist.GetFirstDRegister();
4432 unsigned len = dreglist.GetLength() * 2;
4433 EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4434 (len & 0xff));
4435 AdvanceIT();
4436 return;
4437 }
4438 } else {
4439 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4440 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4441 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004442 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004443 AllowUnpredictable())) {
4444 const DRegister& dreg = dreglist.GetFirstDRegister();
4445 unsigned len = dreglist.GetLength() * 2;
4446 EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4447 dreg.Encode(22, 12) | (len & 0xff));
4448 return;
4449 }
4450 }
4451 Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4452}
4453
4454void Assembler::fstmiax(Condition cond,
4455 Register rn,
4456 WriteBack write_back,
4457 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004458 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004459 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004460 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004461 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4462 if ((((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004463 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004464 AllowUnpredictable())) {
4465 const DRegister& dreg = dreglist.GetFirstDRegister();
4466 unsigned len = dreglist.GetLength() * 2;
4467 EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4468 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4469 (len & 0xff));
4470 AdvanceIT();
4471 return;
4472 }
4473 } else {
4474 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4475 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004476 (dreglist.GetLastDRegister().GetCode() < 16) &&
4477 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004478 AllowUnpredictable())) {
4479 const DRegister& dreg = dreglist.GetFirstDRegister();
4480 unsigned len = dreglist.GetLength() * 2;
4481 EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4482 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4483 (len & 0xff));
4484 return;
4485 }
4486 }
4487 Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4488}
4489
4490void Assembler::hlt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004491 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004492 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004493 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004494 // HLT{<q>} {#}<imm> ; T1
4495 if ((imm <= 63)) {
4496 EmitT32_16(0xba80 | imm);
4497 AdvanceIT();
4498 return;
4499 }
4500 } else {
4501 // HLT{<q>} {#}<imm> ; A1
4502 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4503 EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4504 ((imm & 0xfff0) << 4));
4505 return;
4506 }
4507 }
4508 Delegate(kHlt, &Assembler::hlt, cond, imm);
4509}
4510
4511void Assembler::hvc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004512 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004513 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004514 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004515 // HVC{<q>} {#}<imm16> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004516 if ((imm <= 65535) && (OutsideITBlock() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004517 EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4518 AdvanceIT();
4519 return;
4520 }
4521 } else {
4522 // HVC{<q>} {#}<imm16> ; A1
4523 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4524 EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4525 ((imm & 0xfff0) << 4));
4526 return;
4527 }
4528 }
4529 Delegate(kHvc, &Assembler::hvc, cond, imm);
4530}
4531
4532void Assembler::isb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004534 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004536 // ISB{<c>}{<q>} {<option>} ; T1
4537 EmitT32_32(0xf3bf8f60U | option.GetType());
4538 AdvanceIT();
4539 return;
4540 } else {
4541 // ISB{<c>}{<q>} {<option>} ; A1
4542 if (cond.Is(al)) {
4543 EmitA32(0xf57ff060U | option.GetType());
4544 return;
4545 }
4546 }
4547 Delegate(kIsb, &Assembler::isb, cond, option);
4548}
4549
4550void Assembler::it(Condition cond, uint16_t mask) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004551 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004552 CheckNotIT();
4553 if (mask != 0) {
4554 if ((cond.GetCondition() & 0x1) != 0) {
4555 if ((mask & 0x1) != 0) {
4556 mask ^= 0xE;
4557 } else if ((mask & 0x2) != 0) {
4558 mask ^= 0xC;
4559 } else if ((mask & 0x4) != 0) {
4560 mask ^= 0x8;
4561 }
4562 }
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004563 if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004564 SetIT(cond, mask);
4565 return;
4566 }
4567 DelegateIt(cond, mask);
4568}
4569
4570void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004571 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004572 CheckIT(cond);
4573 if (operand.IsImmediateZero()) {
4574 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004575 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004576 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004577 if (operand.IsOffset() &&
4578 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004579 EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4580 AdvanceIT();
4581 return;
4582 }
4583 } else {
4584 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004585 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004586 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004587 EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4588 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4589 return;
4590 }
4591 }
4592 }
4593 Delegate(kLda, &Assembler::lda, cond, rt, operand);
4594}
4595
4596void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004597 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004598 CheckIT(cond);
4599 if (operand.IsImmediateZero()) {
4600 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004601 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004602 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004603 if (operand.IsOffset() &&
4604 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004605 EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4606 AdvanceIT();
4607 return;
4608 }
4609 } else {
4610 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004611 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004612 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004613 EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4614 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4615 return;
4616 }
4617 }
4618 }
4619 Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4620}
4621
4622void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004623 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004624 CheckIT(cond);
4625 if (operand.IsImmediateZero()) {
4626 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004627 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004628 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004629 if (operand.IsOffset() &&
4630 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004631 EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4632 AdvanceIT();
4633 return;
4634 }
4635 } else {
4636 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004637 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004638 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004639 EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4640 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4641 return;
4642 }
4643 }
4644 }
4645 Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4646}
4647
4648void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004649 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004650 CheckIT(cond);
4651 if (operand.IsImmediateZero()) {
4652 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004653 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004654 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004655 if (operand.IsOffset() &&
4656 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004657 EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4658 AdvanceIT();
4659 return;
4660 }
4661 } else {
4662 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004663 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004664 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004665 EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4666 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4667 return;
4668 }
4669 }
4670 }
4671 Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4672}
4673
4674void Assembler::ldaexd(Condition cond,
4675 Register rt,
4676 Register rt2,
4677 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004678 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004679 CheckIT(cond);
4680 if (operand.IsImmediateZero()) {
4681 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004682 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004683 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004684 if (operand.IsOffset() &&
4685 ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004686 EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4687 (rn.GetCode() << 16));
4688 AdvanceIT();
4689 return;
4690 }
4691 } else {
4692 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4693 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004694 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00004695 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004696 AllowUnpredictable())) {
4697 EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4698 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4699 return;
4700 }
4701 }
4702 }
4703 Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4704}
4705
4706void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004707 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004708 CheckIT(cond);
4709 if (operand.IsImmediateZero()) {
4710 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004711 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004712 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004713 if (operand.IsOffset() &&
4714 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004715 EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4716 AdvanceIT();
4717 return;
4718 }
4719 } else {
4720 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004721 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004722 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004723 EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4724 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4725 return;
4726 }
4727 }
4728 }
4729 Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4730}
4731
4732void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004733 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004734 CheckIT(cond);
4735 if (operand.IsImmediateZero()) {
4736 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004737 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004738 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004739 if (operand.IsOffset() &&
4740 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004741 EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4742 AdvanceIT();
4743 return;
4744 }
4745 } else {
4746 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004747 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004748 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004749 EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4750 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4751 return;
4752 }
4753 }
4754 }
4755 Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4756}
4757
4758void Assembler::ldm(Condition cond,
4759 EncodingSize size,
4760 Register rn,
4761 WriteBack write_back,
4762 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004763 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004764 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004765 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004766 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4767 if (!size.IsWide() && rn.IsLow() &&
4768 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4769 write_back.DoesWriteBack()) &&
4770 ((registers.GetList() & ~0xff) == 0)) {
4771 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4772 GetRegisterListEncoding(registers, 0, 8));
4773 AdvanceIT();
4774 return;
4775 }
4776 // LDM{<c>}{<q>} SP!, <registers> ; T1
4777 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4778 ((registers.GetList() & ~0x80ff) == 0)) {
4779 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4780 GetRegisterListEncoding(registers, 0, 8));
4781 AdvanceIT();
4782 return;
4783 }
4784 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004785 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4786 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004787 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4788 (write_back.GetWriteBackUint32() << 21) |
4789 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4790 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4791 GetRegisterListEncoding(registers, 0, 13));
4792 AdvanceIT();
4793 return;
4794 }
4795 } else {
4796 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004797 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004798 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4799 (write_back.GetWriteBackUint32() << 21) |
4800 GetRegisterListEncoding(registers, 0, 16));
4801 return;
4802 }
4803 }
4804 Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4805}
4806
4807void Assembler::ldmda(Condition cond,
4808 Register rn,
4809 WriteBack write_back,
4810 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004811 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004812 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004813 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004814 // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004815 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004816 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4817 (write_back.GetWriteBackUint32() << 21) |
4818 GetRegisterListEncoding(registers, 0, 16));
4819 return;
4820 }
4821 }
4822 Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4823}
4824
4825void Assembler::ldmdb(Condition cond,
4826 Register rn,
4827 WriteBack write_back,
4828 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004829 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004830 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004831 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004832 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004833 if (((registers.GetList() & ~0xdfff) == 0) &&
4834 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004835 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4836 (write_back.GetWriteBackUint32() << 21) |
4837 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4838 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4839 GetRegisterListEncoding(registers, 0, 13));
4840 AdvanceIT();
4841 return;
4842 }
4843 } else {
4844 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004845 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004846 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4847 (write_back.GetWriteBackUint32() << 21) |
4848 GetRegisterListEncoding(registers, 0, 16));
4849 return;
4850 }
4851 }
4852 Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4853}
4854
4855void Assembler::ldmea(Condition cond,
4856 Register rn,
4857 WriteBack write_back,
4858 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004859 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004860 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004861 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004862 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004863 if (((registers.GetList() & ~0xdfff) == 0) &&
4864 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004865 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4866 (write_back.GetWriteBackUint32() << 21) |
4867 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4868 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4869 GetRegisterListEncoding(registers, 0, 13));
4870 AdvanceIT();
4871 return;
4872 }
4873 } else {
4874 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004875 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004876 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4877 (write_back.GetWriteBackUint32() << 21) |
4878 GetRegisterListEncoding(registers, 0, 16));
4879 return;
4880 }
4881 }
4882 Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4883}
4884
4885void Assembler::ldmed(Condition cond,
4886 Register rn,
4887 WriteBack write_back,
4888 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004889 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004890 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004891 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004892 // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004893 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004894 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4895 (write_back.GetWriteBackUint32() << 21) |
4896 GetRegisterListEncoding(registers, 0, 16));
4897 return;
4898 }
4899 }
4900 Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4901}
4902
4903void Assembler::ldmfa(Condition cond,
4904 Register rn,
4905 WriteBack write_back,
4906 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004907 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004908 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004909 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004910 // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004911 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004912 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4913 (write_back.GetWriteBackUint32() << 21) |
4914 GetRegisterListEncoding(registers, 0, 16));
4915 return;
4916 }
4917 }
4918 Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4919}
4920
4921void Assembler::ldmfd(Condition cond,
4922 EncodingSize size,
4923 Register rn,
4924 WriteBack write_back,
4925 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004926 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004927 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004928 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004929 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4930 if (!size.IsWide() && rn.IsLow() &&
4931 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4932 write_back.DoesWriteBack()) &&
4933 ((registers.GetList() & ~0xff) == 0)) {
4934 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4935 GetRegisterListEncoding(registers, 0, 8));
4936 AdvanceIT();
4937 return;
4938 }
4939 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004940 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4941 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004942 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4943 (write_back.GetWriteBackUint32() << 21) |
4944 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4945 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4946 GetRegisterListEncoding(registers, 0, 13));
4947 AdvanceIT();
4948 return;
4949 }
4950 } else {
4951 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004952 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004953 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4954 (write_back.GetWriteBackUint32() << 21) |
4955 GetRegisterListEncoding(registers, 0, 16));
4956 return;
4957 }
4958 }
4959 Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4960}
4961
4962void Assembler::ldmib(Condition cond,
4963 Register rn,
4964 WriteBack write_back,
4965 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004966 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004967 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004968 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004969 // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004970 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004971 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4972 (write_back.GetWriteBackUint32() << 21) |
4973 GetRegisterListEncoding(registers, 0, 16));
4974 return;
4975 }
4976 }
4977 Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4978}
4979
4980void Assembler::ldr(Condition cond,
4981 EncodingSize size,
4982 Register rt,
4983 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004984 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004985 CheckIT(cond);
4986 if (operand.IsImmediate()) {
4987 Register rn = operand.GetBaseRegister();
4988 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004989 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004990 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4991 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004992 (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004993 int32_t offset_ = offset >> 2;
4994 EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
4995 ((offset_ & 0x1f) << 6));
4996 AdvanceIT();
4997 return;
4998 }
4999 // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
5000 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005001 ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005002 int32_t offset_ = offset >> 2;
5003 EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
5004 AdvanceIT();
5005 return;
5006 }
5007 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
5008 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005009 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5010 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5011 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005012 EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5013 (offset & 0xfff));
5014 AdvanceIT();
5015 return;
5016 }
5017 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
5018 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005019 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5020 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5021 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005022 EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5023 (-offset & 0xff));
5024 AdvanceIT();
5025 return;
5026 }
5027 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
5028 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005029 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5030 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5031 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005032 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5033 uint32_t offset_ = abs(offset);
5034 EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5035 offset_ | (sign << 9));
5036 AdvanceIT();
5037 return;
5038 }
5039 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
5040 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005041 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5042 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5043 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005044 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5045 uint32_t offset_ = abs(offset);
5046 EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5047 offset_ | (sign << 9));
5048 AdvanceIT();
5049 return;
5050 }
5051 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
5052 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005053 rn.Is(pc) && operand.IsOffset() &&
5054 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5055 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005056 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5057 uint32_t offset_ = abs(offset);
5058 EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5059 AdvanceIT();
5060 return;
5061 }
5062 } else {
5063 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005064 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5065 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005066 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5067 uint32_t offset_ = abs(offset);
5068 EmitA32(0x05100000U | (cond.GetCondition() << 28) |
5069 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5070 (sign << 23));
5071 return;
5072 }
5073 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005074 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5075 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005076 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5077 uint32_t offset_ = abs(offset);
5078 EmitA32(0x04100000U | (cond.GetCondition() << 28) |
5079 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5080 (sign << 23));
5081 return;
5082 }
5083 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005084 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5085 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005086 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5087 uint32_t offset_ = abs(offset);
5088 EmitA32(0x05300000U | (cond.GetCondition() << 28) |
5089 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5090 (sign << 23));
5091 return;
5092 }
5093 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5094 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005095 operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005096 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5097 uint32_t offset_ = abs(offset);
5098 EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
5099 (rt.GetCode() << 12) | offset_ | (sign << 23));
5100 return;
5101 }
5102 }
5103 }
5104 if (operand.IsPlainRegister()) {
5105 Register rn = operand.GetBaseRegister();
5106 Sign sign = operand.GetSign();
5107 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005108 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005109 // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5110 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005111 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005112 EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
5113 (rm.GetCode() << 6));
5114 AdvanceIT();
5115 return;
5116 }
5117 }
5118 }
5119 if (operand.IsShiftedRegister()) {
5120 Register rn = operand.GetBaseRegister();
5121 Sign sign = operand.GetSign();
5122 Register rm = operand.GetOffsetRegister();
5123 Shift shift = operand.GetShift();
5124 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005125 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005126 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5127 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005128 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5129 ((!rm.IsPC() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
5130 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005131 EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5132 rm.GetCode() | (amount << 4));
5133 AdvanceIT();
5134 return;
5135 }
5136 } else {
5137 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005138 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5139 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005140 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5141 uint32_t shift_ = TypeEncodingValue(shift);
5142 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5143 EmitA32(0x07100000U | (cond.GetCondition() << 28) |
5144 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5145 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5146 return;
5147 }
5148 // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005149 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005150 cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005151 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5152 uint32_t shift_ = TypeEncodingValue(shift);
5153 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5154 EmitA32(0x06100000U | (cond.GetCondition() << 28) |
5155 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5156 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5157 return;
5158 }
5159 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005160 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5161 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005162 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5163 uint32_t shift_ = TypeEncodingValue(shift);
5164 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5165 EmitA32(0x07300000U | (cond.GetCondition() << 28) |
5166 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5167 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5168 return;
5169 }
5170 }
5171 }
5172 Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
5173}
5174
5175void Assembler::ldr(Condition cond,
5176 EncodingSize size,
5177 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005178 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005179 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005180 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005181 Location::Offset offset =
5182 location->IsBound()
5183 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005184 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5185 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005186 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005187 // LDR{<c>}{<q>} <Rt>, <label> ; T1
5188 if (!size.IsWide() && rt.IsLow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005189 ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005190 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005191 (!location->IsBound() && size.IsNarrow()))) {
5192 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005193 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005194 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005195 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005196 Location::Offset pc,
5197 const Location* location) const VIXL_OVERRIDE {
5198 pc += kT32PcDelta;
5199 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005200 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
5201 ((offset & 0x3) == 0));
5202 const int32_t target = offset >> 2;
5203 return instr | (target & 0xff);
5204 }
5205 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005206 EmitT32_16(
Vincent Belliardac285442017-05-16 09:26:45 -07005207 Link(0x4800 | (rt.GetCode() << 8), location, immop, &kT16DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005208 AdvanceIT();
5209 return;
5210 }
5211 // LDR{<c>}{<q>} <Rt>, <label> ; T2
5212 if (!size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005213 ((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5214 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005215 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5216 AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005217 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005218 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005219 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005220 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005221 Location::Offset pc,
5222 const Location* location) const VIXL_OVERRIDE {
5223 pc += kT32PcDelta;
5224 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005225 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005226 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005227 int32_t target = abs(offset) | (U << 12);
5228 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5229 }
5230 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005231 EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12),
5232 location,
5233 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005234 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005235 AdvanceIT();
5236 return;
5237 }
5238 } else {
5239 // LDR{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005240 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5241 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005242 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005243 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005244 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005245 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005246 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005247 Location::Offset pc,
5248 const Location* location) const VIXL_OVERRIDE {
5249 pc += kA32PcDelta;
5250 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005251 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005252 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005253 int32_t target = abs(offset) | (U << 12);
5254 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5255 }
5256 } immop;
5257 EmitA32(
5258 Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005259 location,
5260 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005261 &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005262 return;
5263 }
5264 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005265 Delegate(kLdr, &Assembler::ldr, cond, size, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005266}
5267
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005268bool Assembler::ldr_info(Condition cond,
5269 EncodingSize size,
5270 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005271 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005272 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005273 VIXL_ASSERT(!location->IsBound());
5274 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005275 if (IsUsingT32()) {
5276 // LDR{<c>}{<q>} <Rt>, <label> ; T1
5277 if (!size.IsWide() && rt.IsLow() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005278 *info = &kT16DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005279 return true;
5280 }
5281 // LDR{<c>}{<q>} <Rt>, <label> ; T2
5282 if (!size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005283 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005284 return true;
5285 }
5286 } else {
5287 // LDR{<c>}{<q>} <Rt>, <label> ; A1
5288 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005289 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005290 return true;
5291 }
5292 }
5293 return false;
5294}
5295
Alexandre Ramesd3832962016-07-04 15:03:43 +01005296void Assembler::ldrb(Condition cond,
5297 EncodingSize size,
5298 Register rt,
5299 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005300 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005301 CheckIT(cond);
5302 if (operand.IsImmediate()) {
5303 Register rn = operand.GetBaseRegister();
5304 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005305 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005306 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5307 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005308 (offset <= 31) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005309 EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
5310 ((offset & 0x1f) << 6));
5311 AdvanceIT();
5312 return;
5313 }
5314 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5315 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005316 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005317 EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5318 (offset & 0xfff));
5319 AdvanceIT();
5320 return;
5321 }
5322 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5323 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005324 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005325 EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5326 (-offset & 0xff));
5327 AdvanceIT();
5328 return;
5329 }
5330 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5331 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005332 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005333 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5334 uint32_t offset_ = abs(offset);
5335 EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5336 offset_ | (sign << 9));
5337 AdvanceIT();
5338 return;
5339 }
5340 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5341 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005342 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005343 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5344 uint32_t offset_ = abs(offset);
5345 EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5346 offset_ | (sign << 9));
5347 AdvanceIT();
5348 return;
5349 }
5350 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5351 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005352 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005353 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5354 uint32_t offset_ = abs(offset);
5355 EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5356 AdvanceIT();
5357 return;
5358 }
5359 } else {
5360 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005361 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005362 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5363 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005364 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5365 uint32_t offset_ = abs(offset);
5366 EmitA32(0x05500000U | (cond.GetCondition() << 28) |
5367 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5368 (sign << 23));
5369 return;
5370 }
5371 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005372 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005373 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5374 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005375 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5376 uint32_t offset_ = abs(offset);
5377 EmitA32(0x04500000U | (cond.GetCondition() << 28) |
5378 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5379 (sign << 23));
5380 return;
5381 }
5382 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005383 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005384 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5385 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005386 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5387 uint32_t offset_ = abs(offset);
5388 EmitA32(0x05700000U | (cond.GetCondition() << 28) |
5389 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5390 (sign << 23));
5391 return;
5392 }
5393 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5394 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005395 operand.IsOffset() && cond.IsNotNever() &&
5396 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005397 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5398 uint32_t offset_ = abs(offset);
5399 EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
5400 (rt.GetCode() << 12) | offset_ | (sign << 23));
5401 return;
5402 }
5403 }
5404 }
5405 if (operand.IsPlainRegister()) {
5406 Register rn = operand.GetBaseRegister();
5407 Sign sign = operand.GetSign();
5408 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005409 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005410 // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5411 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005412 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005413 EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
5414 (rm.GetCode() << 6));
5415 AdvanceIT();
5416 return;
5417 }
5418 }
5419 }
5420 if (operand.IsShiftedRegister()) {
5421 Register rn = operand.GetBaseRegister();
5422 Sign sign = operand.GetSign();
5423 Register rm = operand.GetOffsetRegister();
5424 Shift shift = operand.GetShift();
5425 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005426 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005427 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5428 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005429 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
5430 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005431 EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5432 rm.GetCode() | (amount << 4));
5433 AdvanceIT();
5434 return;
5435 }
5436 } else {
5437 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005438 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5439 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005440 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5441 uint32_t shift_ = TypeEncodingValue(shift);
5442 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5443 EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5444 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5445 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5446 return;
5447 }
5448 // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005449 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005450 cond.IsNotNever() &&
5451 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005452 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5453 uint32_t shift_ = TypeEncodingValue(shift);
5454 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5455 EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5456 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5457 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5458 return;
5459 }
5460 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005461 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5462 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005463 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5464 uint32_t shift_ = TypeEncodingValue(shift);
5465 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5466 EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5467 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5468 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5469 return;
5470 }
5471 }
5472 }
5473 Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5474}
5475
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005476void Assembler::ldrb(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005477 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005478 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005479 Location::Offset offset =
5480 location->IsBound()
5481 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005482 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5483 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005484 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005485 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005486 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5487 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005488 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005489 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005490 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005491 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005492 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005493 Location::Offset pc,
5494 const Location* location) const VIXL_OVERRIDE {
5495 pc += kT32PcDelta;
5496 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005497 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005498 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005499 int32_t target = abs(offset) | (U << 12);
5500 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5501 }
5502 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005503 EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12),
5504 location,
5505 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005506 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005507 AdvanceIT();
5508 return;
5509 }
5510 } else {
5511 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005512 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5513 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005514 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005515 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005516 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005517 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005518 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005519 Location::Offset pc,
5520 const Location* location) const VIXL_OVERRIDE {
5521 pc += kA32PcDelta;
5522 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005523 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005524 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005525 int32_t target = abs(offset) | (U << 12);
5526 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5527 }
5528 } immop;
5529 EmitA32(
5530 Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005531 location,
5532 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005533 &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005534 return;
5535 }
5536 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005537 Delegate(kLdrb, &Assembler::ldrb, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005538}
5539
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005540bool Assembler::ldrb_info(Condition cond,
5541 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005542 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005543 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005544 VIXL_ASSERT(!location->IsBound());
5545 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005546 if (IsUsingT32()) {
5547 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5548 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07005549 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005550 return true;
5551 }
5552 } else {
5553 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5554 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005555 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005556 return true;
5557 }
5558 }
5559 return false;
5560}
5561
Alexandre Ramesd3832962016-07-04 15:03:43 +01005562void Assembler::ldrd(Condition cond,
5563 Register rt,
5564 Register rt2,
5565 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005566 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005567 CheckIT(cond);
5568 if (operand.IsImmediate()) {
5569 Register rn = operand.GetBaseRegister();
5570 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005571 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005572 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5573 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005574 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5575 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005576 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5577 uint32_t offset_ = abs(offset) >> 2;
5578 EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5579 (rn.GetCode() << 16) | offset_ | (sign << 23));
5580 AdvanceIT();
5581 return;
5582 }
5583 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5584 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005585 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5586 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005587 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5588 uint32_t offset_ = abs(offset) >> 2;
5589 EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5590 (rn.GetCode() << 16) | offset_ | (sign << 23));
5591 AdvanceIT();
5592 return;
5593 }
5594 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5595 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005596 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5597 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005598 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5599 uint32_t offset_ = abs(offset) >> 2;
5600 EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5601 (rn.GetCode() << 16) | offset_ | (sign << 23));
5602 AdvanceIT();
5603 return;
5604 }
5605 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5606 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005607 operand.IsOffset() &&
5608 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005609 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5610 uint32_t offset_ = abs(offset);
5611 EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5612 offset_ | (sign << 23));
5613 AdvanceIT();
5614 return;
5615 }
5616 } else {
5617 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5618 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005619 (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5620 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005621 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005622 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005623 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5624 uint32_t offset_ = abs(offset);
5625 EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5626 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5627 ((offset_ & 0xf0) << 4) | (sign << 23));
5628 return;
5629 }
5630 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5631 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005632 (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5633 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005634 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005635 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005636 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5637 uint32_t offset_ = abs(offset);
5638 EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5639 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5640 ((offset_ & 0xf0) << 4) | (sign << 23));
5641 return;
5642 }
5643 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5644 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005645 (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5646 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005647 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005648 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005649 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5650 uint32_t offset_ = abs(offset);
5651 EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5652 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5653 ((offset_ & 0xf0) << 4) | (sign << 23));
5654 return;
5655 }
5656 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5657 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5658 (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005659 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005660 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005661 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005662 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5663 uint32_t offset_ = abs(offset);
5664 EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5665 (rt.GetCode() << 12) | (offset_ & 0xf) |
5666 ((offset_ & 0xf0) << 4) | (sign << 23));
5667 return;
5668 }
5669 }
5670 }
5671 if (operand.IsPlainRegister()) {
5672 Register rn = operand.GetBaseRegister();
5673 Sign sign = operand.GetSign();
5674 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005675 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005676 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5677 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005678 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005679 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005680 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005681 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5682 EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5683 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5684 (sign_ << 23));
5685 return;
5686 }
5687 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5688 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005689 operand.IsPostIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005690 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005691 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005692 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5693 EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5694 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5695 (sign_ << 23));
5696 return;
5697 }
5698 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5699 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005700 operand.IsPreIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005701 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005702 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005703 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5704 EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5705 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5706 (sign_ << 23));
5707 return;
5708 }
5709 }
5710 }
5711 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5712}
5713
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005714void Assembler::ldrd(Condition cond,
5715 Register rt,
5716 Register rt2,
5717 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005718 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005719 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005720 Location::Offset offset =
5721 location->IsBound()
5722 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005723 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5724 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005725 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005726 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005727 if (((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005728 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005729 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005730 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005731 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005732 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005733 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005734 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005735 Location::Offset pc,
5736 const Location* location) const VIXL_OVERRIDE {
5737 pc += kT32PcDelta;
5738 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005739 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5740 ((offset & 0x3) == 0));
5741 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005742 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005743 target = abs(target) | (U << 8);
5744 return instr | (target & 0xff) | ((target & 0x100) << 15);
5745 }
5746 } immop;
5747 EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005748 location,
5749 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005750 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005751 AdvanceIT();
5752 return;
5753 }
5754 } else {
5755 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5756 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005757 ((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
5758 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005759 cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005760 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005761 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005762 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005763 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005764 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005765 Location::Offset pc,
5766 const Location* location) const VIXL_OVERRIDE {
5767 pc += kA32PcDelta;
5768 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005769 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005770 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005771 int32_t target = abs(offset) | (U << 8);
5772 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5773 ((target & 0x100) << 15);
5774 }
5775 } immop;
5776 EmitA32(
5777 Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005778 location,
5779 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005780 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005781 return;
5782 }
5783 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005784 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005785}
5786
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005787bool Assembler::ldrd_info(Condition cond,
5788 Register rt,
5789 Register rt2,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005790 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005791 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005792 VIXL_ASSERT(!location->IsBound());
5793 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005794 if (IsUsingT32()) {
5795 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5796 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07005797 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005798 return true;
5799 }
5800 } else {
5801 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5802 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5803 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005804 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005805 return true;
5806 }
5807 }
5808 return false;
5809}
5810
Alexandre Ramesd3832962016-07-04 15:03:43 +01005811void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005812 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005813 CheckIT(cond);
5814 if (operand.IsImmediate()) {
5815 Register rn = operand.GetBaseRegister();
5816 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005817 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005818 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5819 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005820 operand.IsOffset() &&
5821 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005822 int32_t offset_ = offset >> 2;
5823 EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5824 (offset_ & 0xff));
5825 AdvanceIT();
5826 return;
5827 }
5828 } else {
5829 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005830 if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
5831 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005832 EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5833 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5834 return;
5835 }
5836 }
5837 }
5838 Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5839}
5840
5841void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005842 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005843 CheckIT(cond);
5844 if (operand.IsImmediateZero()) {
5845 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005846 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005847 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005848 if (operand.IsOffset() &&
5849 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005850 EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5851 AdvanceIT();
5852 return;
5853 }
5854 } else {
5855 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005856 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005857 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005858 EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5859 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5860 return;
5861 }
5862 }
5863 }
5864 Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5865}
5866
5867void Assembler::ldrexd(Condition cond,
5868 Register rt,
5869 Register rt2,
5870 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005871 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005872 CheckIT(cond);
5873 if (operand.IsImmediateZero()) {
5874 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005875 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005876 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005877 if (operand.IsOffset() &&
5878 ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005879 EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5880 (rn.GetCode() << 16));
5881 AdvanceIT();
5882 return;
5883 }
5884 } else {
5885 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5886 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005887 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005888 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01005889 AllowUnpredictable())) {
5890 EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5891 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5892 return;
5893 }
5894 }
5895 }
5896 Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5897}
5898
5899void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005900 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005901 CheckIT(cond);
5902 if (operand.IsImmediateZero()) {
5903 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005904 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005905 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005906 if (operand.IsOffset() &&
5907 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005908 EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5909 AdvanceIT();
5910 return;
5911 }
5912 } else {
5913 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005914 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005915 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005916 EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5917 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5918 return;
5919 }
5920 }
5921 }
5922 Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5923}
5924
5925void Assembler::ldrh(Condition cond,
5926 EncodingSize size,
5927 Register rt,
5928 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005929 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005930 CheckIT(cond);
5931 if (operand.IsImmediate()) {
5932 Register rn = operand.GetBaseRegister();
5933 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005934 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005935 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5936 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005937 (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005938 int32_t offset_ = offset >> 1;
5939 EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5940 ((offset_ & 0x1f) << 6));
5941 AdvanceIT();
5942 return;
5943 }
5944 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5945 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005946 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005947 EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5948 (offset & 0xfff));
5949 AdvanceIT();
5950 return;
5951 }
5952 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5953 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005954 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005955 EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5956 (-offset & 0xff));
5957 AdvanceIT();
5958 return;
5959 }
5960 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5961 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005962 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005963 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5964 uint32_t offset_ = abs(offset);
5965 EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5966 offset_ | (sign << 9));
5967 AdvanceIT();
5968 return;
5969 }
5970 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5971 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005972 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005973 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5974 uint32_t offset_ = abs(offset);
5975 EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5976 offset_ | (sign << 9));
5977 AdvanceIT();
5978 return;
5979 }
5980 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5981 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005982 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005983 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5984 uint32_t offset_ = abs(offset);
5985 EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5986 AdvanceIT();
5987 return;
5988 }
5989 } else {
5990 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005991 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005992 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5993 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005994 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5995 uint32_t offset_ = abs(offset);
5996 EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
5997 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5998 ((offset_ & 0xf0) << 4) | (sign << 23));
5999 return;
6000 }
6001 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006002 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006003 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6004 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006005 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6006 uint32_t offset_ = abs(offset);
6007 EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
6008 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6009 ((offset_ & 0xf0) << 4) | (sign << 23));
6010 return;
6011 }
6012 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006013 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006014 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6015 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006016 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6017 uint32_t offset_ = abs(offset);
6018 EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
6019 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6020 ((offset_ & 0xf0) << 4) | (sign << 23));
6021 return;
6022 }
6023 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6024 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006025 operand.IsOffset() && cond.IsNotNever() &&
6026 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006027 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6028 uint32_t offset_ = abs(offset);
6029 EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
6030 (rt.GetCode() << 12) | (offset_ & 0xf) |
6031 ((offset_ & 0xf0) << 4) | (sign << 23));
6032 return;
6033 }
6034 }
6035 }
6036 if (operand.IsPlainRegister()) {
6037 Register rn = operand.GetBaseRegister();
6038 Sign sign = operand.GetSign();
6039 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006040 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006041 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6042 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006043 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006044 EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
6045 (rm.GetCode() << 6));
6046 AdvanceIT();
6047 return;
6048 }
6049 } else {
6050 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006051 if (operand.IsOffset() && cond.IsNotNever() &&
6052 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006053 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6054 EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
6055 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6056 (sign_ << 23));
6057 return;
6058 }
6059 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006060 if (operand.IsPostIndex() && cond.IsNotNever() &&
6061 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006062 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6063 EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
6064 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6065 (sign_ << 23));
6066 return;
6067 }
6068 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006069 if (operand.IsPreIndex() && cond.IsNotNever() &&
6070 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006071 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6072 EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
6073 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6074 (sign_ << 23));
6075 return;
6076 }
6077 }
6078 }
6079 if (operand.IsShiftedRegister()) {
6080 Register rn = operand.GetBaseRegister();
6081 Sign sign = operand.GetSign();
6082 Register rm = operand.GetOffsetRegister();
6083 Shift shift = operand.GetShift();
6084 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006085 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006086 // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6087 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006088 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6089 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006090 EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6091 rm.GetCode() | (amount << 4));
6092 AdvanceIT();
6093 return;
6094 }
6095 }
6096 }
6097 Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
6098}
6099
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006100void Assembler::ldrh(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006101 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006102 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006103 Location::Offset offset =
6104 location->IsBound()
6105 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006106 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6107 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006108 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006109 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006110 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6111 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006112 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006113 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006114 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006115 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006116 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006117 Location::Offset pc,
6118 const Location* location) const VIXL_OVERRIDE {
6119 pc += kT32PcDelta;
6120 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006121 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006122 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006123 int32_t target = abs(offset) | (U << 12);
6124 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6125 }
6126 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006127 EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12),
6128 location,
6129 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006130 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006131 AdvanceIT();
6132 return;
6133 }
6134 } else {
6135 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006136 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6137 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006138 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006139 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006140 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006141 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006142 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006143 Location::Offset pc,
6144 const Location* location) const VIXL_OVERRIDE {
6145 pc += kA32PcDelta;
6146 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006147 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006148 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006149 int32_t target = abs(offset) | (U << 8);
6150 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6151 ((target & 0x100) << 15);
6152 }
6153 } immop;
6154 EmitA32(
6155 Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006156 location,
6157 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006158 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006159 return;
6160 }
6161 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006162 Delegate(kLdrh, &Assembler::ldrh, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006163}
6164
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006165bool Assembler::ldrh_info(Condition cond,
6166 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006167 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006168 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006169 VIXL_ASSERT(!location->IsBound());
6170 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006171 if (IsUsingT32()) {
6172 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6173 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006174 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006175 return true;
6176 }
6177 } else {
6178 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6179 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006180 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006181 return true;
6182 }
6183 }
6184 return false;
6185}
6186
Alexandre Ramesd3832962016-07-04 15:03:43 +01006187void Assembler::ldrsb(Condition cond,
6188 EncodingSize size,
6189 Register rt,
6190 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006191 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006192 CheckIT(cond);
6193 if (operand.IsImmediate()) {
6194 Register rn = operand.GetBaseRegister();
6195 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006196 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006197 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6198 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006199 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006200 EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6201 (offset & 0xfff));
6202 AdvanceIT();
6203 return;
6204 }
6205 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6206 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006207 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006208 EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6209 (-offset & 0xff));
6210 AdvanceIT();
6211 return;
6212 }
6213 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6214 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006215 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006216 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6217 uint32_t offset_ = abs(offset);
6218 EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6219 offset_ | (sign << 9));
6220 AdvanceIT();
6221 return;
6222 }
6223 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6224 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006225 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006226 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6227 uint32_t offset_ = abs(offset);
6228 EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6229 offset_ | (sign << 9));
6230 AdvanceIT();
6231 return;
6232 }
6233 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6234 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006235 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006236 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6237 uint32_t offset_ = abs(offset);
6238 EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6239 AdvanceIT();
6240 return;
6241 }
6242 } else {
6243 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006244 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006245 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6246 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006247 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6248 uint32_t offset_ = abs(offset);
6249 EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
6250 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6251 ((offset_ & 0xf0) << 4) | (sign << 23));
6252 return;
6253 }
6254 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006255 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006256 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6257 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006258 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6259 uint32_t offset_ = abs(offset);
6260 EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
6261 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6262 ((offset_ & 0xf0) << 4) | (sign << 23));
6263 return;
6264 }
6265 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006266 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006267 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6268 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006269 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6270 uint32_t offset_ = abs(offset);
6271 EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
6272 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6273 ((offset_ & 0xf0) << 4) | (sign << 23));
6274 return;
6275 }
6276 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6277 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006278 operand.IsOffset() && cond.IsNotNever() &&
6279 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006280 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6281 uint32_t offset_ = abs(offset);
6282 EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
6283 (rt.GetCode() << 12) | (offset_ & 0xf) |
6284 ((offset_ & 0xf0) << 4) | (sign << 23));
6285 return;
6286 }
6287 }
6288 }
6289 if (operand.IsPlainRegister()) {
6290 Register rn = operand.GetBaseRegister();
6291 Sign sign = operand.GetSign();
6292 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006293 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006294 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6295 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006296 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006297 EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
6298 (rm.GetCode() << 6));
6299 AdvanceIT();
6300 return;
6301 }
6302 } else {
6303 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006304 if (operand.IsOffset() && cond.IsNotNever() &&
6305 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006306 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6307 EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
6308 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6309 (sign_ << 23));
6310 return;
6311 }
6312 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006313 if (operand.IsPostIndex() && cond.IsNotNever() &&
6314 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006315 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6316 EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
6317 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6318 (sign_ << 23));
6319 return;
6320 }
6321 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006322 if (operand.IsPreIndex() && cond.IsNotNever() &&
6323 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006324 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6325 EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
6326 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6327 (sign_ << 23));
6328 return;
6329 }
6330 }
6331 }
6332 if (operand.IsShiftedRegister()) {
6333 Register rn = operand.GetBaseRegister();
6334 Sign sign = operand.GetSign();
6335 Register rm = operand.GetOffsetRegister();
6336 Shift shift = operand.GetShift();
6337 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006338 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006339 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6340 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006341 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6342 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006343 EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6344 rm.GetCode() | (amount << 4));
6345 AdvanceIT();
6346 return;
6347 }
6348 }
6349 }
6350 Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
6351}
6352
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006353void Assembler::ldrsb(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006354 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006355 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006356 Location::Offset offset =
6357 location->IsBound()
6358 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006359 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6360 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006361 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006362 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006363 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6364 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006365 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006366 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006367 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006368 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006369 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006370 Location::Offset pc,
6371 const Location* location) const VIXL_OVERRIDE {
6372 pc += kT32PcDelta;
6373 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006374 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006375 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006376 int32_t target = abs(offset) | (U << 12);
6377 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6378 }
6379 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006380 EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12),
6381 location,
6382 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006383 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006384 AdvanceIT();
6385 return;
6386 }
6387 } else {
6388 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006389 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6390 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006391 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006392 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006393 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006394 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006395 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006396 Location::Offset pc,
6397 const Location* location) const VIXL_OVERRIDE {
6398 pc += kA32PcDelta;
6399 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006400 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006401 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006402 int32_t target = abs(offset) | (U << 8);
6403 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6404 ((target & 0x100) << 15);
6405 }
6406 } immop;
6407 EmitA32(
6408 Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006409 location,
6410 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006411 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006412 return;
6413 }
6414 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006415 Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006416}
6417
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006418bool Assembler::ldrsb_info(Condition cond,
6419 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006420 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006421 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006422 VIXL_ASSERT(!location->IsBound());
6423 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006424 if (IsUsingT32()) {
6425 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6426 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006427 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006428 return true;
6429 }
6430 } else {
6431 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6432 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006433 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006434 return true;
6435 }
6436 }
6437 return false;
6438}
6439
Alexandre Ramesd3832962016-07-04 15:03:43 +01006440void Assembler::ldrsh(Condition cond,
6441 EncodingSize size,
6442 Register rt,
6443 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006444 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006445 CheckIT(cond);
6446 if (operand.IsImmediate()) {
6447 Register rn = operand.GetBaseRegister();
6448 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006449 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006450 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6451 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006452 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006453 EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6454 (offset & 0xfff));
6455 AdvanceIT();
6456 return;
6457 }
6458 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6459 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006460 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006461 EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6462 (-offset & 0xff));
6463 AdvanceIT();
6464 return;
6465 }
6466 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6467 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006468 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006469 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6470 uint32_t offset_ = abs(offset);
6471 EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6472 offset_ | (sign << 9));
6473 AdvanceIT();
6474 return;
6475 }
6476 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6477 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006478 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006479 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6480 uint32_t offset_ = abs(offset);
6481 EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6482 offset_ | (sign << 9));
6483 AdvanceIT();
6484 return;
6485 }
6486 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6487 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006488 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006489 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6490 uint32_t offset_ = abs(offset);
6491 EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6492 AdvanceIT();
6493 return;
6494 }
6495 } else {
6496 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006497 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006498 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6499 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006500 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6501 uint32_t offset_ = abs(offset);
6502 EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
6503 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6504 ((offset_ & 0xf0) << 4) | (sign << 23));
6505 return;
6506 }
6507 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006508 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006509 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6510 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006511 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6512 uint32_t offset_ = abs(offset);
6513 EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
6514 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6515 ((offset_ & 0xf0) << 4) | (sign << 23));
6516 return;
6517 }
6518 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006519 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006520 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6521 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006522 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6523 uint32_t offset_ = abs(offset);
6524 EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
6525 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6526 ((offset_ & 0xf0) << 4) | (sign << 23));
6527 return;
6528 }
6529 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6530 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006531 operand.IsOffset() && cond.IsNotNever() &&
6532 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006533 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6534 uint32_t offset_ = abs(offset);
6535 EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
6536 (rt.GetCode() << 12) | (offset_ & 0xf) |
6537 ((offset_ & 0xf0) << 4) | (sign << 23));
6538 return;
6539 }
6540 }
6541 }
6542 if (operand.IsPlainRegister()) {
6543 Register rn = operand.GetBaseRegister();
6544 Sign sign = operand.GetSign();
6545 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006546 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006547 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6548 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006549 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006550 EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
6551 (rm.GetCode() << 6));
6552 AdvanceIT();
6553 return;
6554 }
6555 } else {
6556 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006557 if (operand.IsOffset() && cond.IsNotNever() &&
6558 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006559 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6560 EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6561 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6562 (sign_ << 23));
6563 return;
6564 }
6565 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006566 if (operand.IsPostIndex() && cond.IsNotNever() &&
6567 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006568 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6569 EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6570 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6571 (sign_ << 23));
6572 return;
6573 }
6574 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006575 if (operand.IsPreIndex() && cond.IsNotNever() &&
6576 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006577 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6578 EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6579 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6580 (sign_ << 23));
6581 return;
6582 }
6583 }
6584 }
6585 if (operand.IsShiftedRegister()) {
6586 Register rn = operand.GetBaseRegister();
6587 Sign sign = operand.GetSign();
6588 Register rm = operand.GetOffsetRegister();
6589 Shift shift = operand.GetShift();
6590 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006591 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006592 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6593 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006594 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6595 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006596 EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6597 rm.GetCode() | (amount << 4));
6598 AdvanceIT();
6599 return;
6600 }
6601 }
6602 }
6603 Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6604}
6605
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006606void Assembler::ldrsh(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006607 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006608 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006609 Location::Offset offset =
6610 location->IsBound()
6611 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006612 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6613 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006614 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006615 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006616 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6617 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006618 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006619 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006620 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006621 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006622 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006623 Location::Offset pc,
6624 const Location* location) const VIXL_OVERRIDE {
6625 pc += kT32PcDelta;
6626 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006627 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006628 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006629 int32_t target = abs(offset) | (U << 12);
6630 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6631 }
6632 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006633 EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12),
6634 location,
6635 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006636 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006637 AdvanceIT();
6638 return;
6639 }
6640 } else {
6641 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006642 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6643 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006644 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006645 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006646 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006647 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006648 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006649 Location::Offset pc,
6650 const Location* location) const VIXL_OVERRIDE {
6651 pc += kA32PcDelta;
6652 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006653 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006654 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006655 int32_t target = abs(offset) | (U << 8);
6656 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6657 ((target & 0x100) << 15);
6658 }
6659 } immop;
6660 EmitA32(
6661 Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006662 location,
6663 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006664 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006665 return;
6666 }
6667 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006668 Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006669}
6670
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006671bool Assembler::ldrsh_info(Condition cond,
6672 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006673 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006674 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006675 VIXL_ASSERT(!location->IsBound());
6676 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006677 if (IsUsingT32()) {
6678 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6679 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006680 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006681 return true;
6682 }
6683 } else {
6684 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6685 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006686 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006687 return true;
6688 }
6689 }
6690 return false;
6691}
6692
Alexandre Ramesd3832962016-07-04 15:03:43 +01006693void Assembler::lsl(Condition cond,
6694 EncodingSize size,
6695 Register rd,
6696 Register rm,
6697 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006698 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006699 CheckIT(cond);
6700 if (operand.IsImmediate()) {
6701 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006702 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006703 // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6704 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6705 (imm >= 1) && (imm <= 31)) {
6706 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6707 AdvanceIT();
6708 return;
6709 }
6710 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006711 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6712 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006713 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6714 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6715 AdvanceIT();
6716 return;
6717 }
6718 } else {
6719 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6720 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6721 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6722 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6723 return;
6724 }
6725 }
6726 }
6727 if (operand.IsPlainRegister()) {
6728 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006729 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006730 // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6731 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6732 rs.IsLow()) {
6733 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6734 AdvanceIT();
6735 return;
6736 }
6737 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006738 if (!size.IsNarrow() &&
6739 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006740 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6741 rs.GetCode());
6742 AdvanceIT();
6743 return;
6744 }
6745 } else {
6746 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006747 if (cond.IsNotNever() &&
6748 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006749 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6750 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6751 return;
6752 }
6753 }
6754 }
6755 Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6756}
6757
6758void Assembler::lsls(Condition cond,
6759 EncodingSize size,
6760 Register rd,
6761 Register rm,
6762 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006763 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006764 CheckIT(cond);
6765 if (operand.IsImmediate()) {
6766 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006767 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006768 // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6769 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6770 (imm >= 1) && (imm <= 31)) {
6771 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6772 AdvanceIT();
6773 return;
6774 }
6775 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006776 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6777 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006778 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6779 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6780 AdvanceIT();
6781 return;
6782 }
6783 } else {
6784 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6785 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6786 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6787 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6788 return;
6789 }
6790 }
6791 }
6792 if (operand.IsPlainRegister()) {
6793 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006794 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006795 // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6796 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6797 rs.IsLow()) {
6798 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6799 AdvanceIT();
6800 return;
6801 }
6802 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006803 if (!size.IsNarrow() &&
6804 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006805 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6806 rs.GetCode());
6807 AdvanceIT();
6808 return;
6809 }
6810 } else {
6811 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006812 if (cond.IsNotNever() &&
6813 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006814 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6815 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6816 return;
6817 }
6818 }
6819 }
6820 Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6821}
6822
6823void Assembler::lsr(Condition cond,
6824 EncodingSize size,
6825 Register rd,
6826 Register rm,
6827 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006828 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006829 CheckIT(cond);
6830 if (operand.IsImmediate()) {
6831 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006833 // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6834 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6835 (imm >= 1) && (imm <= 32)) {
6836 uint32_t amount_ = imm % 32;
6837 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6838 (amount_ << 6));
6839 AdvanceIT();
6840 return;
6841 }
6842 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006843 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6844 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006845 uint32_t amount_ = imm % 32;
6846 EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6847 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6848 AdvanceIT();
6849 return;
6850 }
6851 } else {
6852 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6853 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6854 uint32_t amount_ = imm % 32;
6855 EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6856 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6857 return;
6858 }
6859 }
6860 }
6861 if (operand.IsPlainRegister()) {
6862 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006863 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006864 // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6865 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6866 rs.IsLow()) {
6867 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6868 AdvanceIT();
6869 return;
6870 }
6871 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006872 if (!size.IsNarrow() &&
6873 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006874 EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6875 rs.GetCode());
6876 AdvanceIT();
6877 return;
6878 }
6879 } else {
6880 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006881 if (cond.IsNotNever() &&
6882 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006883 EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6884 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6885 return;
6886 }
6887 }
6888 }
6889 Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6890}
6891
6892void Assembler::lsrs(Condition cond,
6893 EncodingSize size,
6894 Register rd,
6895 Register rm,
6896 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006897 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006898 CheckIT(cond);
6899 if (operand.IsImmediate()) {
6900 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006901 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006902 // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6903 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6904 (imm >= 1) && (imm <= 32)) {
6905 uint32_t amount_ = imm % 32;
6906 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6907 (amount_ << 6));
6908 AdvanceIT();
6909 return;
6910 }
6911 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006912 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6913 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006914 uint32_t amount_ = imm % 32;
6915 EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6916 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6917 AdvanceIT();
6918 return;
6919 }
6920 } else {
6921 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6922 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6923 uint32_t amount_ = imm % 32;
6924 EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6925 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6926 return;
6927 }
6928 }
6929 }
6930 if (operand.IsPlainRegister()) {
6931 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006932 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006933 // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6934 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6935 rs.IsLow()) {
6936 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6937 AdvanceIT();
6938 return;
6939 }
6940 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006941 if (!size.IsNarrow() &&
6942 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006943 EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6944 rs.GetCode());
6945 AdvanceIT();
6946 return;
6947 }
6948 } else {
6949 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006950 if (cond.IsNotNever() &&
6951 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006952 EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6953 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6954 return;
6955 }
6956 }
6957 }
6958 Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6959}
6960
6961void Assembler::mla(
6962 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006963 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006964 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006965 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006966 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006967 if (!ra.Is(pc) &&
6968 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006969 EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6970 rm.GetCode() | (ra.GetCode() << 12));
6971 AdvanceIT();
6972 return;
6973 }
6974 } else {
6975 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006976 if (cond.IsNotNever() &&
6977 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6978 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006979 EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6980 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6981 return;
6982 }
6983 }
6984 Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
6985}
6986
6987void Assembler::mlas(
6988 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006989 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006990 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006991 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006992 // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006993 if (cond.IsNotNever() &&
6994 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6995 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006996 EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6997 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6998 return;
6999 }
7000 }
7001 Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
7002}
7003
7004void Assembler::mls(
7005 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007006 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007007 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007008 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007009 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007010 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7011 AllowUnpredictable())) {
7012 EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7013 rm.GetCode() | (ra.GetCode() << 12));
7014 AdvanceIT();
7015 return;
7016 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007017 } else {
7018 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007019 if (cond.IsNotNever() &&
7020 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7021 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007022 EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7023 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7024 return;
7025 }
7026 }
7027 Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
7028}
7029
7030void Assembler::mov(Condition cond,
7031 EncodingSize size,
7032 Register rd,
7033 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007034 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007035 CheckIT(cond);
7036 if (operand.IsImmediateShiftedRegister()) {
7037 Register rm = operand.GetBaseRegister();
7038 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007039 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007040 // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007041 if (!size.IsWide() &&
7042 ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
7043 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007044 EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
7045 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
7046 AdvanceIT();
7047 return;
7048 }
7049 }
7050 }
7051 Shift shift = operand.GetShift();
7052 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007053 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007054 // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7055 if (InITBlock() && !size.IsWide() && rd.IsLow() &&
7056 shift.IsValidAmount(amount) && rm.IsLow() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007057 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
7058 ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007059 uint32_t amount_ = amount % 32;
7060 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7061 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7062 AdvanceIT();
7063 return;
7064 }
7065 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007066 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7067 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007068 uint32_t amount_ = amount % 32;
7069 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7070 (operand.GetTypeEncodingValue() << 4) |
7071 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7072 AdvanceIT();
7073 return;
7074 }
7075 } else {
7076 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7077 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7078 uint32_t amount_ = amount % 32;
7079 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
7080 (rd.GetCode() << 12) | rm.GetCode() |
7081 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7082 return;
7083 }
7084 }
7085 }
7086 if (operand.IsRegisterShiftedRegister()) {
7087 Register rm = operand.GetBaseRegister();
7088 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007089 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007090 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007091 // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7092 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007093 shift.IsASR() && rs.IsLow()) {
7094 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007095 AdvanceIT();
7096 return;
7097 }
7098 // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7099 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007100 shift.IsLSL() && rs.IsLow()) {
7101 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007102 AdvanceIT();
7103 return;
7104 }
7105 // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7106 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007107 shift.IsLSR() && rs.IsLow()) {
7108 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007109 AdvanceIT();
7110 return;
7111 }
7112 // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7113 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007114 shift.IsROR() && rs.IsLow()) {
7115 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007116 AdvanceIT();
7117 return;
7118 }
7119 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
Vincent Belliard942e3b72016-11-29 15:50:14 -08007120 if (!size.IsNarrow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007121 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007122 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007123 (shift.GetType() << 21) | rs.GetCode());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007124 AdvanceIT();
7125 return;
7126 }
7127 } else {
7128 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007129 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007130 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007131 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
7132 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007133 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007134 return;
7135 }
7136 }
7137 }
7138 if (operand.IsImmediate()) {
7139 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007140 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007141 ImmediateT32 immediate_t32(imm);
7142 // MOV<c>{<q>} <Rd>, #<imm8> ; T1
7143 if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7144 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7145 AdvanceIT();
7146 return;
7147 }
7148 // MOV{<c>}{<q>} <Rd>, #<const> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007149 if (!size.IsNarrow() && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007150 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007151 EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
7152 (immediate_t32.GetEncodingValue() & 0xff) |
7153 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7154 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7155 AdvanceIT();
7156 return;
7157 }
7158 // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08007159 if (!size.IsNarrow() && (imm <= 65535) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007160 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007161 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7162 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7163 ((imm & 0xf000) << 4));
7164 AdvanceIT();
7165 return;
7166 }
7167 } else {
7168 ImmediateA32 immediate_a32(imm);
7169 // MOV{<c>}{<q>} <Rd>, #<const> ; A1
7170 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7171 EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
7172 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7173 return;
7174 }
7175 // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007176 if ((imm <= 65535) && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007177 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007178 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7179 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7180 return;
7181 }
7182 }
7183 }
7184 Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
7185}
7186
7187void Assembler::movs(Condition cond,
7188 EncodingSize size,
7189 Register rd,
7190 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007191 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007192 CheckIT(cond);
7193 if (operand.IsImmediateShiftedRegister()) {
7194 Register rm = operand.GetBaseRegister();
7195 Shift shift = operand.GetShift();
7196 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007197 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007198 // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7199 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
7200 shift.IsValidAmount(amount) && rm.IsLow() &&
7201 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
7202 uint32_t amount_ = amount % 32;
7203 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7204 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7205 AdvanceIT();
7206 return;
7207 }
7208 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007209 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7210 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007211 uint32_t amount_ = amount % 32;
7212 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7213 (operand.GetTypeEncodingValue() << 4) |
7214 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7215 AdvanceIT();
7216 return;
7217 }
7218 } else {
7219 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007220 if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
7221 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007222 uint32_t amount_ = amount % 32;
7223 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
7224 (rd.GetCode() << 12) | rm.GetCode() |
7225 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7226 return;
7227 }
7228 }
7229 }
7230 if (operand.IsRegisterShiftedRegister()) {
7231 Register rm = operand.GetBaseRegister();
7232 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007233 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007234 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007235 // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7236 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007237 shift.IsASR() && rs.IsLow()) {
7238 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007239 AdvanceIT();
7240 return;
7241 }
7242 // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7243 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007244 shift.IsLSL() && rs.IsLow()) {
7245 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007246 AdvanceIT();
7247 return;
7248 }
7249 // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7250 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007251 shift.IsLSR() && rs.IsLow()) {
7252 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007253 AdvanceIT();
7254 return;
7255 }
7256 // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7257 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007258 shift.IsROR() && rs.IsLow()) {
7259 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007260 AdvanceIT();
7261 return;
7262 }
7263 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
Vincent Belliard942e3b72016-11-29 15:50:14 -08007264 if (!size.IsNarrow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007265 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007266 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007267 (shift.GetType() << 21) | rs.GetCode());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007268 AdvanceIT();
7269 return;
7270 }
7271 } else {
7272 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007273 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007274 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007275 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
7276 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007277 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007278 return;
7279 }
7280 }
7281 }
7282 if (operand.IsImmediate()) {
7283 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007285 ImmediateT32 immediate_t32(imm);
7286 // MOVS{<q>} <Rd>, #<imm8> ; T1
7287 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7288 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7289 AdvanceIT();
7290 return;
7291 }
7292 // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007293 if (!size.IsNarrow() && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007294 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007295 EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
7296 (immediate_t32.GetEncodingValue() & 0xff) |
7297 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7298 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7299 AdvanceIT();
7300 return;
7301 }
7302 } else {
7303 ImmediateA32 immediate_a32(imm);
7304 // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
7305 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7306 EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
7307 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7308 return;
7309 }
7310 }
7311 }
7312 Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
7313}
7314
7315void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007316 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007317 CheckIT(cond);
7318 if (operand.IsImmediate()) {
7319 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007320 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007321 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007322 if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007323 EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
7324 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7325 ((imm & 0xf000) << 4));
7326 AdvanceIT();
7327 return;
7328 }
7329 } else {
7330 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007331 if ((imm <= 65535) && cond.IsNotNever() &&
7332 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007333 EmitA32(0x03400000U | (cond.GetCondition() << 28) |
7334 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7335 return;
7336 }
7337 }
7338 }
7339 Delegate(kMovt, &Assembler::movt, cond, rd, operand);
7340}
7341
7342void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007343 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007344 CheckIT(cond);
7345 if (operand.IsImmediate()) {
7346 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007347 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007348 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007349 if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007350 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7351 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7352 ((imm & 0xf000) << 4));
7353 AdvanceIT();
7354 return;
7355 }
7356 } else {
7357 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007358 if ((imm <= 65535) && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007359 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007360 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7361 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7362 return;
7363 }
7364 }
7365 }
7366 Delegate(kMovw, &Assembler::movw, cond, rd, operand);
7367}
7368
7369void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007370 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007371 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007372 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007373 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007374 if ((!rd.IsPC() || AllowUnpredictable())) {
7375 EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
7376 AdvanceIT();
7377 return;
7378 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007379 } else {
7380 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007381 if (cond.IsNotNever() && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007382 EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7383 (spec_reg.GetReg() << 22));
7384 return;
7385 }
7386 }
7387 Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
7388}
7389
7390void Assembler::msr(Condition cond,
7391 MaskedSpecialRegister spec_reg,
7392 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007393 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007394 CheckIT(cond);
7395 if (operand.IsImmediate()) {
7396 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007397 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007398 ImmediateA32 immediate_a32(imm);
7399 // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
7400 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7401 EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
7402 ((spec_reg.GetReg() & 0xf) << 16) |
7403 ((spec_reg.GetReg() & 0x10) << 18) |
7404 immediate_a32.GetEncodingValue());
7405 return;
7406 }
7407 }
7408 }
7409 if (operand.IsPlainRegister()) {
7410 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007411 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007412 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007413 if ((!rn.IsPC() || AllowUnpredictable())) {
7414 EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
7415 ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
7416 AdvanceIT();
7417 return;
7418 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007419 } else {
7420 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007421 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007422 EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
7423 ((spec_reg.GetReg() & 0xf) << 16) |
7424 ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
7425 return;
7426 }
7427 }
7428 }
7429 Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
7430}
7431
7432void Assembler::mul(
7433 Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007434 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007435 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007436 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007437 // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7438 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
7439 rm.IsLow()) {
7440 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7441 AdvanceIT();
7442 return;
7443 }
7444 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007445 if (!size.IsNarrow() &&
7446 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007447 EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7448 rm.GetCode());
7449 AdvanceIT();
7450 return;
7451 }
7452 } else {
7453 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007454 if (cond.IsNotNever() &&
7455 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007456 EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7457 rn.GetCode() | (rm.GetCode() << 8));
7458 return;
7459 }
7460 }
7461 Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
7462}
7463
7464void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007465 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007466 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007467 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007468 // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7469 if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
7470 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7471 AdvanceIT();
7472 return;
7473 }
7474 } else {
7475 // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007476 if (cond.IsNotNever() &&
7477 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007478 EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7479 rn.GetCode() | (rm.GetCode() << 8));
7480 return;
7481 }
7482 }
7483 Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
7484}
7485
7486void Assembler::mvn(Condition cond,
7487 EncodingSize size,
7488 Register rd,
7489 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007490 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007491 CheckIT(cond);
7492 if (operand.IsImmediate()) {
7493 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007494 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007495 ImmediateT32 immediate_t32(imm);
7496 // MVN{<c>}{<q>} <Rd>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007497 if (!size.IsNarrow() && immediate_t32.IsValid() &&
7498 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007499 EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
7500 (immediate_t32.GetEncodingValue() & 0xff) |
7501 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7502 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7503 AdvanceIT();
7504 return;
7505 }
7506 } else {
7507 ImmediateA32 immediate_a32(imm);
7508 // MVN{<c>}{<q>} <Rd>, #<const> ; A1
7509 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7510 EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
7511 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7512 return;
7513 }
7514 }
7515 }
7516 if (operand.IsImmediateShiftedRegister()) {
7517 Register rm = operand.GetBaseRegister();
7518 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007519 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007520 // MVN<c>{<q>} <Rd>, <Rm> ; T1
7521 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7522 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7523 AdvanceIT();
7524 return;
7525 }
7526 }
7527 }
7528 Shift shift = operand.GetShift();
7529 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007530 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007531 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007532 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7533 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007534 uint32_t amount_ = amount % 32;
7535 EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7536 (operand.GetTypeEncodingValue() << 4) |
7537 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7538 AdvanceIT();
7539 return;
7540 }
7541 } else {
7542 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7543 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7544 uint32_t amount_ = amount % 32;
7545 EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
7546 (rd.GetCode() << 12) | rm.GetCode() |
7547 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7548 return;
7549 }
7550 }
7551 }
7552 if (operand.IsRegisterShiftedRegister()) {
7553 Register rm = operand.GetBaseRegister();
7554 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007555 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007556 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007557 // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007558 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007559 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007560 EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
7561 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007562 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007563 return;
7564 }
7565 }
7566 }
7567 Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
7568}
7569
7570void Assembler::mvns(Condition cond,
7571 EncodingSize size,
7572 Register rd,
7573 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007574 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007575 CheckIT(cond);
7576 if (operand.IsImmediate()) {
7577 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007578 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007579 ImmediateT32 immediate_t32(imm);
7580 // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007581 if (!size.IsNarrow() && immediate_t32.IsValid() &&
7582 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007583 EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
7584 (immediate_t32.GetEncodingValue() & 0xff) |
7585 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7586 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7587 AdvanceIT();
7588 return;
7589 }
7590 } else {
7591 ImmediateA32 immediate_a32(imm);
7592 // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
7593 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7594 EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
7595 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7596 return;
7597 }
7598 }
7599 }
7600 if (operand.IsImmediateShiftedRegister()) {
7601 Register rm = operand.GetBaseRegister();
7602 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007603 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007604 // MVNS{<q>} <Rd>, <Rm> ; T1
7605 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7606 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7607 AdvanceIT();
7608 return;
7609 }
7610 }
7611 }
7612 Shift shift = operand.GetShift();
7613 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007614 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007615 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007616 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7617 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007618 uint32_t amount_ = amount % 32;
7619 EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7620 (operand.GetTypeEncodingValue() << 4) |
7621 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7622 AdvanceIT();
7623 return;
7624 }
7625 } else {
7626 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7627 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7628 uint32_t amount_ = amount % 32;
7629 EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7630 (rd.GetCode() << 12) | rm.GetCode() |
7631 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7632 return;
7633 }
7634 }
7635 }
7636 if (operand.IsRegisterShiftedRegister()) {
7637 Register rm = operand.GetBaseRegister();
7638 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007639 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007640 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007641 // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007642 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007643 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007644 EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7645 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007646 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007647 return;
7648 }
7649 }
7650 }
7651 Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7652}
7653
7654void Assembler::nop(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007655 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007656 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007657 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007658 // NOP{<c>}{<q>} ; T1
7659 if (!size.IsWide()) {
7660 EmitT32_16(0xbf00);
7661 AdvanceIT();
7662 return;
7663 }
7664 // NOP{<c>}.W ; T2
7665 if (!size.IsNarrow()) {
7666 EmitT32_32(0xf3af8000U);
7667 AdvanceIT();
7668 return;
7669 }
7670 } else {
7671 // NOP{<c>}{<q>} ; A1
7672 if (cond.IsNotNever()) {
7673 EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7674 return;
7675 }
7676 }
7677 Delegate(kNop, &Assembler::nop, cond, size);
7678}
7679
7680void Assembler::orn(Condition cond,
7681 Register rd,
7682 Register rn,
7683 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007684 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007685 CheckIT(cond);
7686 if (operand.IsImmediate()) {
7687 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007688 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007689 ImmediateT32 immediate_t32(imm);
7690 // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007691 if (immediate_t32.IsValid() && !rn.Is(pc) &&
7692 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007693 EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7694 (immediate_t32.GetEncodingValue() & 0xff) |
7695 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7696 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7697 AdvanceIT();
7698 return;
7699 }
7700 }
7701 }
7702 if (operand.IsImmediateShiftedRegister()) {
7703 Register rm = operand.GetBaseRegister();
7704 Shift shift = operand.GetShift();
7705 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007706 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007707 // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007708 if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7709 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007710 uint32_t amount_ = amount % 32;
7711 EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7712 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7713 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7714 AdvanceIT();
7715 return;
7716 }
7717 }
7718 }
7719 Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7720}
7721
7722void Assembler::orns(Condition cond,
7723 Register rd,
7724 Register rn,
7725 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007726 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007727 CheckIT(cond);
7728 if (operand.IsImmediate()) {
7729 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007730 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007731 ImmediateT32 immediate_t32(imm);
7732 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007733 if (immediate_t32.IsValid() && !rn.Is(pc) &&
7734 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007735 EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7736 (immediate_t32.GetEncodingValue() & 0xff) |
7737 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7738 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7739 AdvanceIT();
7740 return;
7741 }
7742 }
7743 }
7744 if (operand.IsImmediateShiftedRegister()) {
7745 Register rm = operand.GetBaseRegister();
7746 Shift shift = operand.GetShift();
7747 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007748 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007749 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007750 if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7751 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007752 uint32_t amount_ = amount % 32;
7753 EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7754 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7755 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7756 AdvanceIT();
7757 return;
7758 }
7759 }
7760 }
7761 Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7762}
7763
7764void Assembler::orr(Condition cond,
7765 EncodingSize size,
7766 Register rd,
7767 Register rn,
7768 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007769 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007770 CheckIT(cond);
7771 if (operand.IsImmediate()) {
7772 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007773 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007774 ImmediateT32 immediate_t32(imm);
7775 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007776 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7777 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007778 EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7779 (immediate_t32.GetEncodingValue() & 0xff) |
7780 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7781 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7782 AdvanceIT();
7783 return;
7784 }
7785 } else {
7786 ImmediateA32 immediate_a32(imm);
7787 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7788 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7789 EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7790 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7791 immediate_a32.GetEncodingValue());
7792 return;
7793 }
7794 }
7795 }
7796 if (operand.IsImmediateShiftedRegister()) {
7797 Register rm = operand.GetBaseRegister();
7798 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007799 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007800 // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7801 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7802 rm.IsLow()) {
7803 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7804 AdvanceIT();
7805 return;
7806 }
7807 }
7808 }
7809 Shift shift = operand.GetShift();
7810 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007811 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007812 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007813 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7814 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007815 uint32_t amount_ = amount % 32;
7816 EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7817 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7818 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7819 AdvanceIT();
7820 return;
7821 }
7822 } else {
7823 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7824 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7825 uint32_t amount_ = amount % 32;
7826 EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7827 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7828 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7829 return;
7830 }
7831 }
7832 }
7833 if (operand.IsRegisterShiftedRegister()) {
7834 Register rm = operand.GetBaseRegister();
7835 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007836 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007837 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007838 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00007839 if (cond.IsNotNever() &&
7840 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7841 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007842 EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7843 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007844 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007845 return;
7846 }
7847 }
7848 }
7849 Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7850}
7851
7852void Assembler::orrs(Condition cond,
7853 EncodingSize size,
7854 Register rd,
7855 Register rn,
7856 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007857 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007858 CheckIT(cond);
7859 if (operand.IsImmediate()) {
7860 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007861 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007862 ImmediateT32 immediate_t32(imm);
7863 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007864 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7865 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007866 EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7867 (immediate_t32.GetEncodingValue() & 0xff) |
7868 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7869 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7870 AdvanceIT();
7871 return;
7872 }
7873 } else {
7874 ImmediateA32 immediate_a32(imm);
7875 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7876 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7877 EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7878 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7879 immediate_a32.GetEncodingValue());
7880 return;
7881 }
7882 }
7883 }
7884 if (operand.IsImmediateShiftedRegister()) {
7885 Register rm = operand.GetBaseRegister();
7886 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007887 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007888 // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7889 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7890 rm.IsLow()) {
7891 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7892 AdvanceIT();
7893 return;
7894 }
7895 }
7896 }
7897 Shift shift = operand.GetShift();
7898 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007899 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007900 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007901 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7902 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007903 uint32_t amount_ = amount % 32;
7904 EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7905 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7906 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7907 AdvanceIT();
7908 return;
7909 }
7910 } else {
7911 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7912 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7913 uint32_t amount_ = amount % 32;
7914 EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7915 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7916 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7917 return;
7918 }
7919 }
7920 }
7921 if (operand.IsRegisterShiftedRegister()) {
7922 Register rm = operand.GetBaseRegister();
7923 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007924 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007925 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007926 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00007927 if (cond.IsNotNever() &&
7928 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7929 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007930 EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7931 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007932 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007933 return;
7934 }
7935 }
7936 }
7937 Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7938}
7939
7940void Assembler::pkhbt(Condition cond,
7941 Register rd,
7942 Register rn,
7943 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007944 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007945 CheckIT(cond);
7946 if (operand.IsImmediateShiftedRegister()) {
7947 Register rm = operand.GetBaseRegister();
7948 Shift shift = operand.GetShift();
7949 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007950 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007951 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007952 if (shift.IsLSL() && shift.IsValidAmount(amount) &&
7953 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007954 EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7955 rm.GetCode() | ((amount & 0x3) << 6) |
7956 ((amount & 0x1c) << 10));
7957 AdvanceIT();
7958 return;
7959 }
7960 } else {
7961 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007962 if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever() &&
7963 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007964 EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7965 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7966 (amount << 7));
7967 return;
7968 }
7969 }
7970 }
7971 Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7972}
7973
7974void Assembler::pkhtb(Condition cond,
7975 Register rd,
7976 Register rn,
7977 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007978 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007979 CheckIT(cond);
7980 if (operand.IsImmediateShiftedRegister()) {
7981 Register rm = operand.GetBaseRegister();
7982 Shift shift = operand.GetShift();
7983 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007984 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007985 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007986 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7987 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007988 uint32_t amount_ = amount % 32;
7989 EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7990 rm.GetCode() | ((amount_ & 0x3) << 6) |
7991 ((amount_ & 0x1c) << 10));
7992 AdvanceIT();
7993 return;
7994 }
7995 } else {
7996 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
7997 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00007998 cond.IsNotNever() &&
7999 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008000 uint32_t amount_ = amount % 32;
8001 EmitA32(0x06800050U | (cond.GetCondition() << 28) |
8002 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8003 (amount_ << 7));
8004 return;
8005 }
8006 }
8007 }
8008 Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
8009}
8010
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008011void Assembler::pld(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008012 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008013 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008014 Location::Offset offset =
8015 location->IsBound()
8016 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01008017 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8018 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008019 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008020 // PLD{<c>}{<q>} <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008021 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8022 !location->IsBound())) {
8023 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008024 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008025 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008026 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008027 Location::Offset pc,
8028 const Location* location) const VIXL_OVERRIDE {
8029 pc += kT32PcDelta;
8030 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008031 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008032 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008033 int32_t target = abs(offset) | (U << 12);
8034 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8035 }
8036 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008037 EmitT32_32(Link(0xf81ff000U, location, immop, &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008038 AdvanceIT();
8039 return;
8040 }
8041 } else {
8042 // PLD{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008043 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8044 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008045 if (cond.Is(al)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008046 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008047 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008048 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008049 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008050 Location::Offset pc,
8051 const Location* location) const
8052 VIXL_OVERRIDE {
8053 pc += kA32PcDelta;
8054 Location::Offset offset =
8055 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008056 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008057 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008058 int32_t target = abs(offset) | (U << 12);
8059 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8060 }
8061 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008062 EmitA32(Link(0xf55ff000U, location, immop, &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008063 return;
8064 }
8065 }
8066 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008067 Delegate(kPld, &Assembler::pld, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008068}
8069
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008070bool Assembler::pld_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008071 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008072 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008073 VIXL_ASSERT(!location->IsBound());
8074 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008075 USE(cond);
8076 if (IsUsingT32()) {
8077 // PLD{<c>}{<q>} <label> ; T1
8078 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008079 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008080 return true;
8081 }
8082 } else {
8083 // PLD{<c>}{<q>} <label> ; A1
8084 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008085 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008086 return true;
8087 }
8088 }
8089 return false;
8090}
8091
Alexandre Ramesd3832962016-07-04 15:03:43 +01008092void Assembler::pld(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008093 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008094 CheckIT(cond);
8095 if (operand.IsImmediate()) {
8096 Register rn = operand.GetBaseRegister();
8097 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008098 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008099 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008100 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8101 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008102 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8103 uint32_t offset_ = abs(offset);
8104 EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
8105 AdvanceIT();
8106 return;
8107 }
8108 } else {
8109 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008110 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8111 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008112 if (cond.Is(al)) {
8113 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8114 uint32_t offset_ = abs(offset);
8115 EmitA32(0xf55ff000U | offset_ | (sign << 23));
8116 return;
8117 }
8118 }
8119 }
8120 }
8121 if (operand.IsImmediate()) {
8122 Register rn = operand.GetBaseRegister();
8123 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008124 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008125 // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008126 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8127 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008128 EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8129 AdvanceIT();
8130 return;
8131 }
8132 // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008133 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8134 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008135 EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8136 AdvanceIT();
8137 return;
8138 }
8139 } else {
8140 // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008141 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008142 ((rn.GetCode() & 0xf) != 0xf)) {
8143 if (cond.Is(al)) {
8144 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8145 uint32_t offset_ = abs(offset);
8146 EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8147 return;
8148 }
8149 }
8150 }
8151 }
8152 if (operand.IsShiftedRegister()) {
8153 Register rn = operand.GetBaseRegister();
8154 Sign sign = operand.GetSign();
8155 Register rm = operand.GetOffsetRegister();
8156 Shift shift = operand.GetShift();
8157 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008158 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008159 // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008160 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008161 ((rn.GetCode() & 0xf) != 0xf) &&
8162 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008163 EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
8164 (amount << 4));
8165 AdvanceIT();
8166 return;
8167 }
8168 } else {
8169 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008170 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8171 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008172 if (cond.Is(al)) {
8173 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8174 uint32_t amount_ = amount % 32;
8175 EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
8176 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8177 return;
8178 }
8179 }
8180 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008181 if (shift.IsRRX() && operand.IsOffset() &&
8182 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008183 if (cond.Is(al)) {
8184 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8185 EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
8186 (sign_ << 23));
8187 return;
8188 }
8189 }
8190 }
8191 }
8192 Delegate(kPld, &Assembler::pld, cond, operand);
8193}
8194
8195void Assembler::pldw(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008196 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008197 CheckIT(cond);
8198 if (operand.IsImmediate()) {
8199 Register rn = operand.GetBaseRegister();
8200 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008201 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008202 // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008203 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8204 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008205 EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8206 AdvanceIT();
8207 return;
8208 }
8209 // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008210 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8211 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008212 EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8213 AdvanceIT();
8214 return;
8215 }
8216 } else {
8217 // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008218 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008219 ((rn.GetCode() & 0xf) != 0xf)) {
8220 if (cond.Is(al)) {
8221 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8222 uint32_t offset_ = abs(offset);
8223 EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8224 return;
8225 }
8226 }
8227 }
8228 }
8229 if (operand.IsShiftedRegister()) {
8230 Register rn = operand.GetBaseRegister();
8231 Sign sign = operand.GetSign();
8232 Register rm = operand.GetOffsetRegister();
8233 Shift shift = operand.GetShift();
8234 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008235 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008236 // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008237 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008238 ((rn.GetCode() & 0xf) != 0xf) &&
8239 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008240 EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
8241 (amount << 4));
8242 AdvanceIT();
8243 return;
8244 }
8245 } else {
8246 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008247 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8248 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008249 if (cond.Is(al)) {
8250 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8251 uint32_t amount_ = amount % 32;
8252 EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
8253 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8254 return;
8255 }
8256 }
8257 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008258 if (shift.IsRRX() && operand.IsOffset() &&
8259 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008260 if (cond.Is(al)) {
8261 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8262 EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
8263 (sign_ << 23));
8264 return;
8265 }
8266 }
8267 }
8268 }
8269 Delegate(kPldw, &Assembler::pldw, cond, operand);
8270}
8271
8272void Assembler::pli(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008273 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008274 CheckIT(cond);
8275 if (operand.IsImmediate()) {
8276 Register rn = operand.GetBaseRegister();
8277 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008278 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008279 // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008280 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8281 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008282 EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8283 AdvanceIT();
8284 return;
8285 }
8286 // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008287 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8288 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008289 EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8290 AdvanceIT();
8291 return;
8292 }
8293 } else {
8294 // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008295 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008296 ((rn.GetCode() & 0xf) != 0xf)) {
8297 if (cond.Is(al)) {
8298 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8299 uint32_t offset_ = abs(offset);
8300 EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8301 return;
8302 }
8303 }
8304 }
8305 }
8306 if (operand.IsImmediate()) {
8307 Register rn = operand.GetBaseRegister();
8308 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008309 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008310 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008311 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8312 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008313 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8314 uint32_t offset_ = abs(offset);
8315 EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
8316 AdvanceIT();
8317 return;
8318 }
8319 } else {
8320 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008321 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8322 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008323 if (cond.Is(al)) {
8324 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8325 uint32_t offset_ = abs(offset);
8326 EmitA32(0xf45ff000U | offset_ | (sign << 23));
8327 return;
8328 }
8329 }
8330 }
8331 }
8332 if (operand.IsShiftedRegister()) {
8333 Register rn = operand.GetBaseRegister();
8334 Sign sign = operand.GetSign();
8335 Register rm = operand.GetOffsetRegister();
8336 Shift shift = operand.GetShift();
8337 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008338 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008339 // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008340 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008341 ((rn.GetCode() & 0xf) != 0xf) &&
8342 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008343 EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
8344 (amount << 4));
8345 AdvanceIT();
8346 return;
8347 }
8348 } else {
8349 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008350 if (shift.IsRRX() && operand.IsOffset() &&
8351 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008352 if (cond.Is(al)) {
8353 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8354 EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
8355 (sign_ << 23));
8356 return;
8357 }
8358 }
8359 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008360 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8361 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008362 if (cond.Is(al)) {
8363 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8364 uint32_t amount_ = amount % 32;
8365 EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
8366 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8367 return;
8368 }
8369 }
8370 }
8371 }
8372 Delegate(kPli, &Assembler::pli, cond, operand);
8373}
8374
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008375void Assembler::pli(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008376 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008377 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008378 Location::Offset offset =
8379 location->IsBound()
8380 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01008381 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8382 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008383 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008384 // PLI{<c>}{<q>} <label> ; T3
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008385 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8386 !location->IsBound())) {
8387 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008388 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008389 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008390 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008391 Location::Offset pc,
8392 const Location* location) const VIXL_OVERRIDE {
8393 pc += kT32PcDelta;
8394 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008395 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008396 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008397 int32_t target = abs(offset) | (U << 12);
8398 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8399 }
8400 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008401 EmitT32_32(Link(0xf91ff000U, location, immop, &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008402 AdvanceIT();
8403 return;
8404 }
8405 } else {
8406 // PLI{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008407 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8408 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008409 if (cond.Is(al)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008410 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008411 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008412 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008413 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008414 Location::Offset pc,
8415 const Location* location) const
8416 VIXL_OVERRIDE {
8417 pc += kA32PcDelta;
8418 Location::Offset offset =
8419 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008420 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008421 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008422 int32_t target = abs(offset) | (U << 12);
8423 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8424 }
8425 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008426 EmitA32(Link(0xf45ff000U, location, immop, &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008427 return;
8428 }
8429 }
8430 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008431 Delegate(kPli, &Assembler::pli, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008432}
8433
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008434bool Assembler::pli_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008435 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008436 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008437 VIXL_ASSERT(!location->IsBound());
8438 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008439 USE(cond);
8440 if (IsUsingT32()) {
8441 // PLI{<c>}{<q>} <label> ; T3
8442 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008443 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008444 return true;
8445 }
8446 } else {
8447 // PLI{<c>}{<q>} <label> ; A1
8448 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008449 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008450 return true;
8451 }
8452 }
8453 return false;
8454}
8455
Alexandre Ramesd3832962016-07-04 15:03:43 +01008456void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008457 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008458 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008459 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008460 // POP{<c>}{<q>} <registers> ; T1
8461 if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
8462 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
8463 GetRegisterListEncoding(registers, 0, 8));
8464 AdvanceIT();
8465 return;
8466 }
8467 // POP{<c>}{<q>} <registers> ; T2
8468 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
8469 EmitT32_32(0xe8bd0000U |
8470 (GetRegisterListEncoding(registers, 15, 1) << 15) |
8471 (GetRegisterListEncoding(registers, 14, 1) << 14) |
8472 GetRegisterListEncoding(registers, 0, 13));
8473 AdvanceIT();
8474 return;
8475 }
8476 } else {
8477 // POP{<c>}{<q>} <registers> ; A1
8478 if (cond.IsNotNever()) {
8479 EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
8480 GetRegisterListEncoding(registers, 0, 16));
8481 return;
8482 }
8483 }
8484 Delegate(kPop, &Assembler::pop, cond, size, registers);
8485}
8486
8487void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008488 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008489 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008490 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008491 // POP{<c>}{<q>} <single_register_list> ; T4
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008492 if (!size.IsNarrow() && ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
8493 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008494 EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
8495 AdvanceIT();
8496 return;
8497 }
8498 } else {
8499 // POP{<c>}{<q>} <single_register_list> ; A1
8500 if (cond.IsNotNever()) {
8501 EmitA32(0x049d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8502 return;
8503 }
8504 }
8505 Delegate(kPop, &Assembler::pop, cond, size, rt);
8506}
8507
8508void Assembler::push(Condition cond,
8509 EncodingSize size,
8510 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008511 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008512 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008513 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008514 // PUSH{<c>}{<q>} <registers> ; T1
8515 if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
8516 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
8517 GetRegisterListEncoding(registers, 0, 8));
8518 AdvanceIT();
8519 return;
8520 }
8521 // PUSH{<c>}{<q>} <registers> ; T1
8522 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
8523 EmitT32_32(0xe92d0000U |
8524 (GetRegisterListEncoding(registers, 14, 1) << 14) |
8525 GetRegisterListEncoding(registers, 0, 13));
8526 AdvanceIT();
8527 return;
8528 }
8529 } else {
8530 // PUSH{<c>}{<q>} <registers> ; A1
8531 if (cond.IsNotNever()) {
8532 EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
8533 GetRegisterListEncoding(registers, 0, 16));
8534 return;
8535 }
8536 }
8537 Delegate(kPush, &Assembler::push, cond, size, registers);
8538}
8539
8540void Assembler::push(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008541 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008542 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008543 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008544 // PUSH{<c>}{<q>} <single_register_list> ; T4
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008545 if (!size.IsNarrow() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008546 EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
8547 AdvanceIT();
8548 return;
8549 }
8550 } else {
8551 // PUSH{<c>}{<q>} <single_register_list> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08008552 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008553 EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8554 return;
8555 }
8556 }
8557 Delegate(kPush, &Assembler::push, cond, size, rt);
8558}
8559
8560void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008561 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008562 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008563 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008564 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008565 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8566 EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
8567 (rn.GetCode() << 16));
8568 AdvanceIT();
8569 return;
8570 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008571 } else {
8572 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008573 if (cond.IsNotNever() &&
8574 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008575 EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8576 rm.GetCode() | (rn.GetCode() << 16));
8577 return;
8578 }
8579 }
8580 Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
8581}
8582
8583void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008584 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008585 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008586 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008587 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008588 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8589 EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8590 rm.GetCode());
8591 AdvanceIT();
8592 return;
8593 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008594 } else {
8595 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008596 if (cond.IsNotNever() &&
8597 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008598 EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8599 (rn.GetCode() << 16) | rm.GetCode());
8600 return;
8601 }
8602 }
8603 Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
8604}
8605
8606void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008607 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008608 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008609 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008610 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008611 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8612 EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8613 rm.GetCode());
8614 AdvanceIT();
8615 return;
8616 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008617 } else {
8618 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008619 if (cond.IsNotNever() &&
8620 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008621 EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8622 (rn.GetCode() << 16) | rm.GetCode());
8623 return;
8624 }
8625 }
8626 Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
8627}
8628
8629void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008630 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008631 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008632 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008633 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008634 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8635 EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8636 rm.GetCode());
8637 AdvanceIT();
8638 return;
8639 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008640 } else {
8641 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008642 if (cond.IsNotNever() &&
8643 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008644 EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8645 (rn.GetCode() << 16) | rm.GetCode());
8646 return;
8647 }
8648 }
8649 Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
8650}
8651
8652void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008653 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008654 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008655 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008656 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008657 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8658 EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
8659 (rn.GetCode() << 16));
8660 AdvanceIT();
8661 return;
8662 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008663 } else {
8664 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008665 if (cond.IsNotNever() &&
8666 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008667 EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8668 rm.GetCode() | (rn.GetCode() << 16));
8669 return;
8670 }
8671 }
8672 Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
8673}
8674
8675void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008676 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008677 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008678 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008679 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008680 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8681 EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8682 (rn.GetCode() << 16));
8683 AdvanceIT();
8684 return;
8685 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008686 } else {
8687 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008688 if (cond.IsNotNever() &&
8689 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008690 EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8691 rm.GetCode() | (rn.GetCode() << 16));
8692 return;
8693 }
8694 }
8695 Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
8696}
8697
8698void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008699 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008700 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008701 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008702 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008703 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8704 EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8705 rm.GetCode());
8706 AdvanceIT();
8707 return;
8708 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008709 } else {
8710 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008711 if (cond.IsNotNever() &&
8712 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008713 EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8714 (rn.GetCode() << 16) | rm.GetCode());
8715 return;
8716 }
8717 }
8718 Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
8719}
8720
8721void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008722 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008723 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008724 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008725 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008726 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8727 EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8728 (rn.GetCode() << 16));
8729 AdvanceIT();
8730 return;
8731 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008732 } else {
8733 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008734 if (cond.IsNotNever() &&
8735 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008736 EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8737 rm.GetCode() | (rn.GetCode() << 16));
8738 return;
8739 }
8740 }
8741 Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8742}
8743
8744void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008745 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008746 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008747 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008748 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008749 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8750 EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8751 rm.GetCode());
8752 AdvanceIT();
8753 return;
8754 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008755 } else {
8756 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008757 if (cond.IsNotNever() &&
8758 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008759 EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8760 (rn.GetCode() << 16) | rm.GetCode());
8761 return;
8762 }
8763 }
8764 Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8765}
8766
8767void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008768 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008769 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008770 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008771 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008772 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8773 EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8774 rm.GetCode());
8775 AdvanceIT();
8776 return;
8777 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008778 } else {
8779 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008780 if (cond.IsNotNever() &&
8781 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008782 EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8783 (rn.GetCode() << 16) | rm.GetCode());
8784 return;
8785 }
8786 }
8787 Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8788}
8789
8790void Assembler::rbit(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008791 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008792 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008793 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008794 // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008795 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8796 EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8797 (rm.GetCode() << 16));
8798 AdvanceIT();
8799 return;
8800 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008801 } else {
8802 // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008803 if (cond.IsNotNever() &&
8804 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008805 EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8806 rm.GetCode());
8807 return;
8808 }
8809 }
8810 Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8811}
8812
8813void Assembler::rev(Condition cond,
8814 EncodingSize size,
8815 Register rd,
8816 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008817 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008818 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008819 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008820 // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8821 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8822 EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8823 AdvanceIT();
8824 return;
8825 }
8826 // REV{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008827 if (!size.IsNarrow() &&
8828 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008829 EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8830 (rm.GetCode() << 16));
8831 AdvanceIT();
8832 return;
8833 }
8834 } else {
8835 // REV{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008836 if (cond.IsNotNever() &&
8837 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008838 EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8839 rm.GetCode());
8840 return;
8841 }
8842 }
8843 Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8844}
8845
8846void Assembler::rev16(Condition cond,
8847 EncodingSize size,
8848 Register rd,
8849 Register rm) {
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 // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8854 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8855 EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8856 AdvanceIT();
8857 return;
8858 }
8859 // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008860 if (!size.IsNarrow() &&
8861 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008862 EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8863 (rm.GetCode() << 16));
8864 AdvanceIT();
8865 return;
8866 }
8867 } else {
8868 // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008869 if (cond.IsNotNever() &&
8870 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008871 EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8872 rm.GetCode());
8873 return;
8874 }
8875 }
8876 Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8877}
8878
8879void Assembler::revsh(Condition cond,
8880 EncodingSize size,
8881 Register rd,
8882 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008883 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008884 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008885 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008886 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8887 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8888 EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8889 AdvanceIT();
8890 return;
8891 }
8892 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008893 if (!size.IsNarrow() &&
8894 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008895 EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8896 (rm.GetCode() << 16));
8897 AdvanceIT();
8898 return;
8899 }
8900 } else {
8901 // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008902 if (cond.IsNotNever() &&
8903 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008904 EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8905 rm.GetCode());
8906 return;
8907 }
8908 }
8909 Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8910}
8911
8912void Assembler::ror(Condition cond,
8913 EncodingSize size,
8914 Register rd,
8915 Register rm,
8916 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008917 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008918 CheckIT(cond);
8919 if (operand.IsImmediate()) {
8920 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008921 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008922 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008923 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8924 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008925 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8926 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8927 AdvanceIT();
8928 return;
8929 }
8930 } else {
8931 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8932 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8933 EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8934 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8935 return;
8936 }
8937 }
8938 }
8939 if (operand.IsPlainRegister()) {
8940 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008941 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008942 // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8943 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8944 rs.IsLow()) {
8945 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8946 AdvanceIT();
8947 return;
8948 }
8949 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008950 if (!size.IsNarrow() &&
8951 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008952 EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8953 rs.GetCode());
8954 AdvanceIT();
8955 return;
8956 }
8957 } else {
8958 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008959 if (cond.IsNotNever() &&
8960 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008961 EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
8962 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8963 return;
8964 }
8965 }
8966 }
8967 Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
8968}
8969
8970void Assembler::rors(Condition cond,
8971 EncodingSize size,
8972 Register rd,
8973 Register rm,
8974 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008975 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008976 CheckIT(cond);
8977 if (operand.IsImmediate()) {
8978 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008979 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008980 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008981 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8982 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008983 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8984 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8985 AdvanceIT();
8986 return;
8987 }
8988 } else {
8989 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8990 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8991 EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
8992 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8993 return;
8994 }
8995 }
8996 }
8997 if (operand.IsPlainRegister()) {
8998 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008999 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009000 // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
9001 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
9002 rs.IsLow()) {
9003 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
9004 AdvanceIT();
9005 return;
9006 }
9007 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009008 if (!size.IsNarrow() &&
9009 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009010 EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
9011 rs.GetCode());
9012 AdvanceIT();
9013 return;
9014 }
9015 } else {
9016 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009017 if (cond.IsNotNever() &&
9018 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009019 EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
9020 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9021 return;
9022 }
9023 }
9024 }
9025 Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
9026}
9027
9028void Assembler::rrx(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009029 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009030 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009031 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009032 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009033 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9034 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
9035 AdvanceIT();
9036 return;
9037 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009038 } else {
9039 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
9040 if (cond.IsNotNever()) {
9041 EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9042 rm.GetCode());
9043 return;
9044 }
9045 }
9046 Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
9047}
9048
9049void Assembler::rrxs(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009050 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009051 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009052 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009053 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009054 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9055 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
9056 AdvanceIT();
9057 return;
9058 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009059 } else {
9060 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
9061 if (cond.IsNotNever()) {
9062 EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9063 rm.GetCode());
9064 return;
9065 }
9066 }
9067 Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
9068}
9069
9070void Assembler::rsb(Condition cond,
9071 EncodingSize size,
9072 Register rd,
9073 Register rn,
9074 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009075 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009076 CheckIT(cond);
9077 if (operand.IsImmediate()) {
9078 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009079 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009080 ImmediateT32 immediate_t32(imm);
9081 // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
9082 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9083 (imm == 0)) {
9084 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9085 AdvanceIT();
9086 return;
9087 }
9088 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009089 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9090 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009091 EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9092 (immediate_t32.GetEncodingValue() & 0xff) |
9093 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9094 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9095 AdvanceIT();
9096 return;
9097 }
9098 } else {
9099 ImmediateA32 immediate_a32(imm);
9100 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9101 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9102 EmitA32(0x02600000U | (cond.GetCondition() << 28) |
9103 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9104 immediate_a32.GetEncodingValue());
9105 return;
9106 }
9107 }
9108 }
9109 if (operand.IsImmediateShiftedRegister()) {
9110 Register rm = operand.GetBaseRegister();
9111 Shift shift = operand.GetShift();
9112 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009113 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009114 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009115 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9116 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009117 uint32_t amount_ = amount % 32;
9118 EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9119 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9120 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9121 AdvanceIT();
9122 return;
9123 }
9124 } else {
9125 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9126 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9127 uint32_t amount_ = amount % 32;
9128 EmitA32(0x00600000U | (cond.GetCondition() << 28) |
9129 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9130 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9131 return;
9132 }
9133 }
9134 }
9135 if (operand.IsRegisterShiftedRegister()) {
9136 Register rm = operand.GetBaseRegister();
9137 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009138 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009139 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009140 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009141 if (cond.IsNotNever() &&
9142 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9143 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009144 EmitA32(0x00600010U | (cond.GetCondition() << 28) |
9145 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009146 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009147 return;
9148 }
9149 }
9150 }
9151 Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
9152}
9153
9154void Assembler::rsbs(Condition cond,
9155 EncodingSize size,
9156 Register rd,
9157 Register rn,
9158 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009159 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009160 CheckIT(cond);
9161 if (operand.IsImmediate()) {
9162 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009163 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009164 ImmediateT32 immediate_t32(imm);
9165 // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
9166 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9167 (imm == 0)) {
9168 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9169 AdvanceIT();
9170 return;
9171 }
9172 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009173 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9174 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009175 EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9176 (immediate_t32.GetEncodingValue() & 0xff) |
9177 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9178 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9179 AdvanceIT();
9180 return;
9181 }
9182 } else {
9183 ImmediateA32 immediate_a32(imm);
9184 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9185 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9186 EmitA32(0x02700000U | (cond.GetCondition() << 28) |
9187 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9188 immediate_a32.GetEncodingValue());
9189 return;
9190 }
9191 }
9192 }
9193 if (operand.IsImmediateShiftedRegister()) {
9194 Register rm = operand.GetBaseRegister();
9195 Shift shift = operand.GetShift();
9196 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009197 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009198 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009199 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9200 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009201 uint32_t amount_ = amount % 32;
9202 EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9203 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9204 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9205 AdvanceIT();
9206 return;
9207 }
9208 } else {
9209 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9210 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9211 uint32_t amount_ = amount % 32;
9212 EmitA32(0x00700000U | (cond.GetCondition() << 28) |
9213 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9214 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9215 return;
9216 }
9217 }
9218 }
9219 if (operand.IsRegisterShiftedRegister()) {
9220 Register rm = operand.GetBaseRegister();
9221 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009222 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009223 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009224 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009225 if (cond.IsNotNever() &&
9226 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9227 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009228 EmitA32(0x00700010U | (cond.GetCondition() << 28) |
9229 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009230 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009231 return;
9232 }
9233 }
9234 }
9235 Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
9236}
9237
9238void Assembler::rsc(Condition cond,
9239 Register rd,
9240 Register rn,
9241 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009243 CheckIT(cond);
9244 if (operand.IsImmediate()) {
9245 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009246 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009247 ImmediateA32 immediate_a32(imm);
9248 // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9249 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9250 EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
9251 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9252 immediate_a32.GetEncodingValue());
9253 return;
9254 }
9255 }
9256 }
9257 if (operand.IsImmediateShiftedRegister()) {
9258 Register rm = operand.GetBaseRegister();
9259 Shift shift = operand.GetShift();
9260 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009261 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009262 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9263 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9264 uint32_t amount_ = amount % 32;
9265 EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
9266 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9267 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9268 return;
9269 }
9270 }
9271 }
9272 if (operand.IsRegisterShiftedRegister()) {
9273 Register rm = operand.GetBaseRegister();
9274 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009275 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009276 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009277 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009278 if (cond.IsNotNever() &&
9279 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9280 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009281 EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
9282 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009283 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009284 return;
9285 }
9286 }
9287 }
9288 Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
9289}
9290
9291void Assembler::rscs(Condition cond,
9292 Register rd,
9293 Register rn,
9294 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009295 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009296 CheckIT(cond);
9297 if (operand.IsImmediate()) {
9298 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009299 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009300 ImmediateA32 immediate_a32(imm);
9301 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9302 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9303 EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
9304 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9305 immediate_a32.GetEncodingValue());
9306 return;
9307 }
9308 }
9309 }
9310 if (operand.IsImmediateShiftedRegister()) {
9311 Register rm = operand.GetBaseRegister();
9312 Shift shift = operand.GetShift();
9313 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009314 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009315 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9316 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9317 uint32_t amount_ = amount % 32;
9318 EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
9319 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9320 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9321 return;
9322 }
9323 }
9324 }
9325 if (operand.IsRegisterShiftedRegister()) {
9326 Register rm = operand.GetBaseRegister();
9327 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009328 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009329 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009330 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009331 if (cond.IsNotNever() &&
9332 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9333 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009334 EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
9335 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009336 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009337 return;
9338 }
9339 }
9340 }
9341 Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
9342}
9343
9344void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
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 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009349 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9350 EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9351 rm.GetCode());
9352 AdvanceIT();
9353 return;
9354 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009355 } else {
9356 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009357 if (cond.IsNotNever() &&
9358 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009359 EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9360 (rn.GetCode() << 16) | rm.GetCode());
9361 return;
9362 }
9363 }
9364 Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
9365}
9366
9367void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
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 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009372 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9373 EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9374 rm.GetCode());
9375 AdvanceIT();
9376 return;
9377 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009378 } else {
9379 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009380 if (cond.IsNotNever() &&
9381 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009382 EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9383 (rn.GetCode() << 16) | rm.GetCode());
9384 return;
9385 }
9386 }
9387 Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
9388}
9389
9390void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
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 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009395 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9396 EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9397 rm.GetCode());
9398 AdvanceIT();
9399 return;
9400 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009401 } else {
9402 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009403 if (cond.IsNotNever() &&
9404 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009405 EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9406 (rn.GetCode() << 16) | rm.GetCode());
9407 return;
9408 }
9409 }
9410 Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
9411}
9412
9413void Assembler::sbc(Condition cond,
9414 EncodingSize size,
9415 Register rd,
9416 Register rn,
9417 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009418 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009419 CheckIT(cond);
9420 if (operand.IsImmediate()) {
9421 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009422 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009423 ImmediateT32 immediate_t32(imm);
9424 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009425 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9426 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009427 EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9428 (immediate_t32.GetEncodingValue() & 0xff) |
9429 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9430 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9431 AdvanceIT();
9432 return;
9433 }
9434 } else {
9435 ImmediateA32 immediate_a32(imm);
9436 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9437 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9438 EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
9439 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9440 immediate_a32.GetEncodingValue());
9441 return;
9442 }
9443 }
9444 }
9445 if (operand.IsImmediateShiftedRegister()) {
9446 Register rm = operand.GetBaseRegister();
9447 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009448 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009449 // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9450 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9451 rm.IsLow()) {
9452 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9453 AdvanceIT();
9454 return;
9455 }
9456 }
9457 }
9458 Shift shift = operand.GetShift();
9459 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009460 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009461 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009462 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9463 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009464 uint32_t amount_ = amount % 32;
9465 EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9466 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9467 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9468 AdvanceIT();
9469 return;
9470 }
9471 } else {
9472 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9473 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9474 uint32_t amount_ = amount % 32;
9475 EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
9476 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9477 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9478 return;
9479 }
9480 }
9481 }
9482 if (operand.IsRegisterShiftedRegister()) {
9483 Register rm = operand.GetBaseRegister();
9484 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009485 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009486 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009487 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009488 if (cond.IsNotNever() &&
9489 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9490 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009491 EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
9492 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009493 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009494 return;
9495 }
9496 }
9497 }
9498 Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
9499}
9500
9501void Assembler::sbcs(Condition cond,
9502 EncodingSize size,
9503 Register rd,
9504 Register rn,
9505 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009506 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009507 CheckIT(cond);
9508 if (operand.IsImmediate()) {
9509 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009510 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009511 ImmediateT32 immediate_t32(imm);
9512 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009513 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9514 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009515 EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9516 (immediate_t32.GetEncodingValue() & 0xff) |
9517 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9518 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9519 AdvanceIT();
9520 return;
9521 }
9522 } else {
9523 ImmediateA32 immediate_a32(imm);
9524 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9525 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9526 EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
9527 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9528 immediate_a32.GetEncodingValue());
9529 return;
9530 }
9531 }
9532 }
9533 if (operand.IsImmediateShiftedRegister()) {
9534 Register rm = operand.GetBaseRegister();
9535 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009536 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009537 // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9538 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9539 rm.IsLow()) {
9540 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9541 AdvanceIT();
9542 return;
9543 }
9544 }
9545 }
9546 Shift shift = operand.GetShift();
9547 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009548 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009549 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009550 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9551 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009552 uint32_t amount_ = amount % 32;
9553 EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9554 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9555 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9556 AdvanceIT();
9557 return;
9558 }
9559 } else {
9560 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9561 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9562 uint32_t amount_ = amount % 32;
9563 EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
9564 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9565 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9566 return;
9567 }
9568 }
9569 }
9570 if (operand.IsRegisterShiftedRegister()) {
9571 Register rm = operand.GetBaseRegister();
9572 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009573 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009574 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009575 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009576 if (cond.IsNotNever() &&
9577 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9578 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009579 EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
9580 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009581 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009582 return;
9583 }
9584 }
9585 }
9586 Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
9587}
9588
Vincent Belliard609821f2017-02-08 14:17:25 -08009589void Assembler::sbfx(
9590 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009591 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009592 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08009593 if (IsUsingT32()) {
9594 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
9595 if ((lsb <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00009596 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9597 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08009598 uint32_t widthm1 = width - 1;
9599 EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9600 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
9601 AdvanceIT();
9602 return;
9603 }
9604 } else {
9605 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
9606 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00009607 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9608 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08009609 uint32_t widthm1 = width - 1;
9610 EmitA32(0x07a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9611 rn.GetCode() | (lsb << 7) | (widthm1 << 16));
9612 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01009613 }
9614 }
Vincent Belliard609821f2017-02-08 14:17:25 -08009615 Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009616}
9617
9618void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009619 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009620 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009621 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009622 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009623 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9624 EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9625 rm.GetCode());
9626 AdvanceIT();
9627 return;
9628 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009629 } else {
9630 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009631 if (cond.IsNotNever() &&
9632 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009633 EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9634 rn.GetCode() | (rm.GetCode() << 8));
9635 return;
9636 }
9637 }
9638 Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
9639}
9640
9641void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009642 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009643 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009644 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009645 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009646 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9647 EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9648 rm.GetCode());
9649 AdvanceIT();
9650 return;
9651 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009652 } else {
9653 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009654 if (cond.IsNotNever() &&
9655 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009656 EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9657 (rn.GetCode() << 16) | rm.GetCode());
9658 return;
9659 }
9660 }
9661 Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
9662}
9663
9664void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
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 (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009668 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009669 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9670 EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9671 rm.GetCode());
9672 AdvanceIT();
9673 return;
9674 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009675 } else {
9676 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009677 if (cond.IsNotNever() &&
9678 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009679 EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9680 (rn.GetCode() << 16) | rm.GetCode());
9681 return;
9682 }
9683 }
9684 Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
9685}
9686
9687void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009688 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009689 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009690 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009691 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009692 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9693 EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9694 rm.GetCode());
9695 AdvanceIT();
9696 return;
9697 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009698 } else {
9699 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009700 if (cond.IsNotNever() &&
9701 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009702 EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9703 (rn.GetCode() << 16) | rm.GetCode());
9704 return;
9705 }
9706 }
9707 Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
9708}
9709
9710void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009711 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009712 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009713 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009714 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009715 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9716 EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9717 rm.GetCode());
9718 AdvanceIT();
9719 return;
9720 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009721 } else {
9722 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009723 if (cond.IsNotNever() &&
9724 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009725 EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9726 (rn.GetCode() << 16) | rm.GetCode());
9727 return;
9728 }
9729 }
9730 Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
9731}
9732
9733void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009734 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009735 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009736 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009737 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009738 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9739 EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9740 rm.GetCode());
9741 AdvanceIT();
9742 return;
9743 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009744 } else {
9745 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009746 if (cond.IsNotNever() &&
9747 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009748 EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9749 (rn.GetCode() << 16) | rm.GetCode());
9750 return;
9751 }
9752 }
9753 Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
9754}
9755
9756void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009757 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009758 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009759 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009760 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009761 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9762 EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9763 rm.GetCode());
9764 AdvanceIT();
9765 return;
9766 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009767 } else {
9768 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009769 if (cond.IsNotNever() &&
9770 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009771 EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9772 (rn.GetCode() << 16) | rm.GetCode());
9773 return;
9774 }
9775 }
9776 Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
9777}
9778
9779void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
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 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009784 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9785 EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9786 rm.GetCode());
9787 AdvanceIT();
9788 return;
9789 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009790 } else {
9791 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009792 if (cond.IsNotNever() &&
9793 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009794 EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9795 (rn.GetCode() << 16) | rm.GetCode());
9796 return;
9797 }
9798 }
9799 Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
9800}
9801
9802void Assembler::smlabb(
9803 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009804 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009805 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009806 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009807 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009808 if (!ra.Is(pc) &&
9809 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009810 EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9811 rm.GetCode() | (ra.GetCode() << 12));
9812 AdvanceIT();
9813 return;
9814 }
9815 } else {
9816 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009817 if (cond.IsNotNever() &&
9818 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9819 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009820 EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9821 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9822 return;
9823 }
9824 }
9825 Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9826}
9827
9828void Assembler::smlabt(
9829 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009830 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009831 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009833 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009834 if (!ra.Is(pc) &&
9835 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009836 EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9837 rm.GetCode() | (ra.GetCode() << 12));
9838 AdvanceIT();
9839 return;
9840 }
9841 } else {
9842 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009843 if (cond.IsNotNever() &&
9844 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9845 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009846 EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9847 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9848 return;
9849 }
9850 }
9851 Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9852}
9853
9854void Assembler::smlad(
9855 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009856 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009857 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009858 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009859 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009860 if (!ra.Is(pc) &&
9861 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009862 EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9863 rm.GetCode() | (ra.GetCode() << 12));
9864 AdvanceIT();
9865 return;
9866 }
9867 } else {
9868 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009869 if (cond.IsNotNever() && !ra.Is(pc) &&
9870 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009871 EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9872 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9873 return;
9874 }
9875 }
9876 Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9877}
9878
9879void Assembler::smladx(
9880 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009881 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009882 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009883 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009884 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009885 if (!ra.Is(pc) &&
9886 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009887 EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9888 rm.GetCode() | (ra.GetCode() << 12));
9889 AdvanceIT();
9890 return;
9891 }
9892 } else {
9893 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009894 if (cond.IsNotNever() && !ra.Is(pc) &&
9895 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009896 EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9897 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9898 return;
9899 }
9900 }
9901 Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9902}
9903
9904void Assembler::smlal(
9905 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009906 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009907 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009908 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009909 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009910 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9911 AllowUnpredictable())) {
9912 EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9913 (rn.GetCode() << 16) | rm.GetCode());
9914 AdvanceIT();
9915 return;
9916 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009917 } else {
9918 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009919 if (cond.IsNotNever() &&
9920 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9921 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009922 EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9923 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9924 (rm.GetCode() << 8));
9925 return;
9926 }
9927 }
9928 Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9929}
9930
9931void Assembler::smlalbb(
9932 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009933 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009934 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009936 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009937 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9938 AllowUnpredictable())) {
9939 EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9940 (rn.GetCode() << 16) | rm.GetCode());
9941 AdvanceIT();
9942 return;
9943 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009944 } else {
9945 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009946 if (cond.IsNotNever() &&
9947 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9948 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009949 EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9950 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9951 (rm.GetCode() << 8));
9952 return;
9953 }
9954 }
9955 Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9956}
9957
9958void Assembler::smlalbt(
9959 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009960 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009961 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009962 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009963 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009964 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9965 AllowUnpredictable())) {
9966 EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9967 (rn.GetCode() << 16) | rm.GetCode());
9968 AdvanceIT();
9969 return;
9970 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009971 } else {
9972 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009973 if (cond.IsNotNever() &&
9974 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9975 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009976 EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
9977 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9978 (rm.GetCode() << 8));
9979 return;
9980 }
9981 }
9982 Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
9983}
9984
9985void Assembler::smlald(
9986 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009987 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009988 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009989 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009990 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009991 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9992 AllowUnpredictable())) {
9993 EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9994 (rn.GetCode() << 16) | rm.GetCode());
9995 AdvanceIT();
9996 return;
9997 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009998 } else {
9999 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010000 if (cond.IsNotNever() &&
10001 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10002 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010003 EmitA32(0x07400010U | (cond.GetCondition() << 28) |
10004 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10005 (rm.GetCode() << 8));
10006 return;
10007 }
10008 }
10009 Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
10010}
10011
10012void Assembler::smlaldx(
10013 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010014 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010015 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010016 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010017 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010018 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10019 AllowUnpredictable())) {
10020 EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10021 (rn.GetCode() << 16) | rm.GetCode());
10022 AdvanceIT();
10023 return;
10024 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010025 } else {
10026 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010027 if (cond.IsNotNever() &&
10028 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10029 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010030 EmitA32(0x07400030U | (cond.GetCondition() << 28) |
10031 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10032 (rm.GetCode() << 8));
10033 return;
10034 }
10035 }
10036 Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
10037}
10038
10039void Assembler::smlals(
10040 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010041 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010042 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010043 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010044 // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010045 if (cond.IsNotNever() &&
10046 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10047 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010048 EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
10049 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10050 (rm.GetCode() << 8));
10051 return;
10052 }
10053 }
10054 Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
10055}
10056
10057void Assembler::smlaltb(
10058 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010059 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010060 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010061 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010062 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010063 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10064 AllowUnpredictable())) {
10065 EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10066 (rn.GetCode() << 16) | rm.GetCode());
10067 AdvanceIT();
10068 return;
10069 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010070 } else {
10071 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010072 if (cond.IsNotNever() &&
10073 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10074 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010075 EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
10076 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10077 (rm.GetCode() << 8));
10078 return;
10079 }
10080 }
10081 Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
10082}
10083
10084void Assembler::smlaltt(
10085 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010086 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010087 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010088 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010089 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010090 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10091 AllowUnpredictable())) {
10092 EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10093 (rn.GetCode() << 16) | rm.GetCode());
10094 AdvanceIT();
10095 return;
10096 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010097 } else {
10098 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010099 if (cond.IsNotNever() &&
10100 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10101 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010102 EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
10103 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10104 (rm.GetCode() << 8));
10105 return;
10106 }
10107 }
10108 Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
10109}
10110
10111void Assembler::smlatb(
10112 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010113 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010114 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010115 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010116 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010117 if (!ra.Is(pc) &&
10118 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010119 EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10120 rm.GetCode() | (ra.GetCode() << 12));
10121 AdvanceIT();
10122 return;
10123 }
10124 } else {
10125 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010126 if (cond.IsNotNever() &&
10127 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10128 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010129 EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10130 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10131 return;
10132 }
10133 }
10134 Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
10135}
10136
10137void Assembler::smlatt(
10138 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010139 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010140 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010141 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010142 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010143 if (!ra.Is(pc) &&
10144 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010145 EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10146 rm.GetCode() | (ra.GetCode() << 12));
10147 AdvanceIT();
10148 return;
10149 }
10150 } else {
10151 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010152 if (cond.IsNotNever() &&
10153 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10154 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010155 EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10156 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10157 return;
10158 }
10159 }
10160 Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
10161}
10162
10163void Assembler::smlawb(
10164 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010165 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010166 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010167 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010168 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010169 if (!ra.Is(pc) &&
10170 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010171 EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10172 rm.GetCode() | (ra.GetCode() << 12));
10173 AdvanceIT();
10174 return;
10175 }
10176 } else {
10177 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010178 if (cond.IsNotNever() &&
10179 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10180 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010181 EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10182 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10183 return;
10184 }
10185 }
10186 Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
10187}
10188
10189void Assembler::smlawt(
10190 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010191 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010192 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010193 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010194 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010195 if (!ra.Is(pc) &&
10196 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010197 EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10198 rm.GetCode() | (ra.GetCode() << 12));
10199 AdvanceIT();
10200 return;
10201 }
10202 } else {
10203 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010204 if (cond.IsNotNever() &&
10205 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10206 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010207 EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10208 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10209 return;
10210 }
10211 }
10212 Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
10213}
10214
10215void Assembler::smlsd(
10216 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010217 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010218 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010219 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010220 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010221 if (!ra.Is(pc) &&
10222 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010223 EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10224 rm.GetCode() | (ra.GetCode() << 12));
10225 AdvanceIT();
10226 return;
10227 }
10228 } else {
10229 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010230 if (cond.IsNotNever() && !ra.Is(pc) &&
10231 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010232 EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10233 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10234 return;
10235 }
10236 }
10237 Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
10238}
10239
10240void Assembler::smlsdx(
10241 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010243 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010244 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010245 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010246 if (!ra.Is(pc) &&
10247 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010248 EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10249 rm.GetCode() | (ra.GetCode() << 12));
10250 AdvanceIT();
10251 return;
10252 }
10253 } else {
10254 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010255 if (cond.IsNotNever() && !ra.Is(pc) &&
10256 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010257 EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10258 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10259 return;
10260 }
10261 }
10262 Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
10263}
10264
10265void Assembler::smlsld(
10266 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010267 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010268 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010269 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010270 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010271 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10272 AllowUnpredictable())) {
10273 EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10274 (rn.GetCode() << 16) | rm.GetCode());
10275 AdvanceIT();
10276 return;
10277 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010278 } else {
10279 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010280 if (cond.IsNotNever() &&
10281 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10282 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010283 EmitA32(0x07400050U | (cond.GetCondition() << 28) |
10284 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10285 (rm.GetCode() << 8));
10286 return;
10287 }
10288 }
10289 Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
10290}
10291
10292void Assembler::smlsldx(
10293 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010294 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010295 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010296 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010297 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010298 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10299 AllowUnpredictable())) {
10300 EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10301 (rn.GetCode() << 16) | rm.GetCode());
10302 AdvanceIT();
10303 return;
10304 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010305 } else {
10306 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010307 if (cond.IsNotNever() &&
10308 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10309 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010310 EmitA32(0x07400070U | (cond.GetCondition() << 28) |
10311 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10312 (rm.GetCode() << 8));
10313 return;
10314 }
10315 }
10316 Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
10317}
10318
10319void Assembler::smmla(
10320 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010321 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010322 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010323 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010324 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010325 if (!ra.Is(pc) &&
10326 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010327 EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10328 rm.GetCode() | (ra.GetCode() << 12));
10329 AdvanceIT();
10330 return;
10331 }
10332 } else {
10333 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010334 if (cond.IsNotNever() && !ra.Is(pc) &&
10335 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010336 EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10337 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10338 return;
10339 }
10340 }
10341 Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
10342}
10343
10344void Assembler::smmlar(
10345 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010346 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010347 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010348 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010349 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010350 if (!ra.Is(pc) &&
10351 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010352 EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10353 rm.GetCode() | (ra.GetCode() << 12));
10354 AdvanceIT();
10355 return;
10356 }
10357 } else {
10358 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010359 if (cond.IsNotNever() && !ra.Is(pc) &&
10360 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010361 EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10362 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10363 return;
10364 }
10365 }
10366 Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
10367}
10368
10369void Assembler::smmls(
10370 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010371 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010372 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010373 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010374 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010375 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10376 AllowUnpredictable())) {
10377 EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10378 rm.GetCode() | (ra.GetCode() << 12));
10379 AdvanceIT();
10380 return;
10381 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010382 } else {
10383 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010384 if (cond.IsNotNever() &&
10385 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10386 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010387 EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10388 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10389 return;
10390 }
10391 }
10392 Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
10393}
10394
10395void Assembler::smmlsr(
10396 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010397 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010398 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010399 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010400 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010401 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10402 AllowUnpredictable())) {
10403 EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10404 rm.GetCode() | (ra.GetCode() << 12));
10405 AdvanceIT();
10406 return;
10407 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010408 } else {
10409 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010410 if (cond.IsNotNever() &&
10411 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10412 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010413 EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10414 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10415 return;
10416 }
10417 }
10418 Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
10419}
10420
10421void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010422 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010423 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010424 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010425 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010426 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10427 EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10428 rm.GetCode());
10429 AdvanceIT();
10430 return;
10431 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010432 } else {
10433 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010434 if (cond.IsNotNever() &&
10435 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010436 EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10437 rn.GetCode() | (rm.GetCode() << 8));
10438 return;
10439 }
10440 }
10441 Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
10442}
10443
10444void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010445 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010446 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010447 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010448 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010449 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10450 EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10451 rm.GetCode());
10452 AdvanceIT();
10453 return;
10454 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010455 } else {
10456 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010457 if (cond.IsNotNever() &&
10458 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010459 EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10460 rn.GetCode() | (rm.GetCode() << 8));
10461 return;
10462 }
10463 }
10464 Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
10465}
10466
10467void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010468 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010469 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010470 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010471 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010472 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10473 EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10474 rm.GetCode());
10475 AdvanceIT();
10476 return;
10477 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010478 } else {
10479 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010480 if (cond.IsNotNever() &&
10481 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010482 EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10483 rn.GetCode() | (rm.GetCode() << 8));
10484 return;
10485 }
10486 }
10487 Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
10488}
10489
10490void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010491 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010492 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010493 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010494 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010495 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10496 EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10497 rm.GetCode());
10498 AdvanceIT();
10499 return;
10500 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010501 } else {
10502 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010503 if (cond.IsNotNever() &&
10504 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010505 EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10506 rn.GetCode() | (rm.GetCode() << 8));
10507 return;
10508 }
10509 }
10510 Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
10511}
10512
10513void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010514 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010515 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010516 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010517 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010518 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10519 EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10520 rm.GetCode());
10521 AdvanceIT();
10522 return;
10523 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010524 } else {
10525 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010526 if (cond.IsNotNever() &&
10527 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010528 EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10529 rn.GetCode() | (rm.GetCode() << 8));
10530 return;
10531 }
10532 }
10533 Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
10534}
10535
10536void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010537 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010538 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010539 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010540 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010541 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10542 EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10543 rm.GetCode());
10544 AdvanceIT();
10545 return;
10546 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010547 } else {
10548 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010549 if (cond.IsNotNever() &&
10550 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010551 EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10552 rn.GetCode() | (rm.GetCode() << 8));
10553 return;
10554 }
10555 }
10556 Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
10557}
10558
10559void Assembler::smull(
10560 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010561 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010562 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010563 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010564 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010565 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10566 AllowUnpredictable())) {
10567 EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10568 (rn.GetCode() << 16) | rm.GetCode());
10569 AdvanceIT();
10570 return;
10571 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010572 } else {
10573 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010574 if (cond.IsNotNever() &&
10575 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10576 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010577 EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
10578 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10579 (rm.GetCode() << 8));
10580 return;
10581 }
10582 }
10583 Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
10584}
10585
10586void Assembler::smulls(
10587 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010588 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010589 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010590 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010591 // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010592 if (cond.IsNotNever() &&
10593 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10594 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010595 EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
10596 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10597 (rm.GetCode() << 8));
10598 return;
10599 }
10600 }
10601 Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
10602}
10603
10604void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010605 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010606 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010607 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010608 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010609 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10610 EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10611 rm.GetCode());
10612 AdvanceIT();
10613 return;
10614 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010615 } else {
10616 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010617 if (cond.IsNotNever() &&
10618 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010619 EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10620 rn.GetCode() | (rm.GetCode() << 8));
10621 return;
10622 }
10623 }
10624 Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
10625}
10626
10627void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010628 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010629 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010630 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010631 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010632 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10633 EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10634 rm.GetCode());
10635 AdvanceIT();
10636 return;
10637 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010638 } else {
10639 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010640 if (cond.IsNotNever() &&
10641 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010642 EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10643 rn.GetCode() | (rm.GetCode() << 8));
10644 return;
10645 }
10646 }
10647 Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
10648}
10649
10650void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010651 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010652 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010653 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010654 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010655 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10656 EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10657 rm.GetCode());
10658 AdvanceIT();
10659 return;
10660 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010661 } else {
10662 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010663 if (cond.IsNotNever() &&
10664 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010665 EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10666 rn.GetCode() | (rm.GetCode() << 8));
10667 return;
10668 }
10669 }
10670 Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
10671}
10672
10673void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010674 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010675 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010676 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010677 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010678 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10679 EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10680 rm.GetCode());
10681 AdvanceIT();
10682 return;
10683 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010684 } else {
10685 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010686 if (cond.IsNotNever() &&
10687 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010688 EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10689 rn.GetCode() | (rm.GetCode() << 8));
10690 return;
10691 }
10692 }
10693 Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
10694}
10695
10696void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010697 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010698 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010699 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010700 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010701 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10702 EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10703 rm.GetCode());
10704 AdvanceIT();
10705 return;
10706 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010707 } else {
10708 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010709 if (cond.IsNotNever() &&
10710 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010711 EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10712 rn.GetCode() | (rm.GetCode() << 8));
10713 return;
10714 }
10715 }
10716 Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
10717}
10718
10719void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010721 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010722 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010723 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010724 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10725 EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10726 rm.GetCode());
10727 AdvanceIT();
10728 return;
10729 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010730 } else {
10731 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010732 if (cond.IsNotNever() &&
10733 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010734 EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10735 rn.GetCode() | (rm.GetCode() << 8));
10736 return;
10737 }
10738 }
10739 Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
10740}
10741
10742void Assembler::ssat(Condition cond,
10743 Register rd,
10744 uint32_t imm,
10745 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010746 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010747 CheckIT(cond);
10748 if (operand.IsImmediateShiftedRegister()) {
10749 Register rn = operand.GetBaseRegister();
10750 Shift shift = operand.GetShift();
10751 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010752 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010753 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
10754 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010755 (amount <= 31) &&
10756 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010757 uint32_t imm_ = imm - 1;
10758 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10759 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10760 ((amount & 0x1c) << 10));
10761 AdvanceIT();
10762 return;
10763 }
10764 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010765 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10766 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010767 uint32_t imm_ = imm - 1;
10768 EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
10769 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10770 ((amount & 0x1c) << 10));
10771 AdvanceIT();
10772 return;
10773 }
10774 } else {
10775 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
10776 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010777 (amount <= 32) && cond.IsNotNever() &&
10778 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010779 uint32_t imm_ = imm - 1;
10780 uint32_t amount_ = amount % 32;
10781 EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
10782 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10783 (amount_ << 7));
10784 return;
10785 }
10786 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
10787 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010788 cond.IsNotNever() &&
10789 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010790 uint32_t imm_ = imm - 1;
10791 EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
10792 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10793 (amount << 7));
10794 return;
10795 }
10796 }
10797 }
10798 Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
10799}
10800
10801void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010802 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010803 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010804 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010805 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010806 if ((imm >= 1) && (imm <= 16) &&
10807 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010808 uint32_t imm_ = imm - 1;
10809 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10810 (rn.GetCode() << 16));
10811 AdvanceIT();
10812 return;
10813 }
10814 } else {
10815 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010816 if ((imm >= 1) && (imm <= 16) && cond.IsNotNever() &&
10817 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010818 uint32_t imm_ = imm - 1;
10819 EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10820 (imm_ << 16) | rn.GetCode());
10821 return;
10822 }
10823 }
10824 Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
10825}
10826
10827void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010828 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010829 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010831 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010832 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10833 EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10834 rm.GetCode());
10835 AdvanceIT();
10836 return;
10837 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010838 } else {
10839 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010840 if (cond.IsNotNever() &&
10841 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010842 EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10843 (rn.GetCode() << 16) | rm.GetCode());
10844 return;
10845 }
10846 }
10847 Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
10848}
10849
10850void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010851 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010852 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010853 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010854 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010855 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10856 EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10857 rm.GetCode());
10858 AdvanceIT();
10859 return;
10860 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010861 } else {
10862 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010863 if (cond.IsNotNever() &&
10864 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010865 EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10866 (rn.GetCode() << 16) | rm.GetCode());
10867 return;
10868 }
10869 }
10870 Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
10871}
10872
10873void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010874 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010875 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010876 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010877 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010878 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10879 EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10880 rm.GetCode());
10881 AdvanceIT();
10882 return;
10883 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010884 } else {
10885 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010886 if (cond.IsNotNever() &&
10887 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010888 EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10889 (rn.GetCode() << 16) | rm.GetCode());
10890 return;
10891 }
10892 }
10893 Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
10894}
10895
10896void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010897 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010898 CheckIT(cond);
10899 if (operand.IsImmediateZero()) {
10900 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010901 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010902 // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010903 if (operand.IsOffset() &&
10904 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010905 EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10906 AdvanceIT();
10907 return;
10908 }
10909 } else {
10910 // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010911 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010912 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010913 EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10914 (rn.GetCode() << 16));
10915 return;
10916 }
10917 }
10918 }
10919 Delegate(kStl, &Assembler::stl, cond, rt, operand);
10920}
10921
10922void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010923 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010924 CheckIT(cond);
10925 if (operand.IsImmediateZero()) {
10926 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010927 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010928 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010929 if (operand.IsOffset() &&
10930 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010931 EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10932 AdvanceIT();
10933 return;
10934 }
10935 } else {
10936 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010937 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010938 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010939 EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10940 (rn.GetCode() << 16));
10941 return;
10942 }
10943 }
10944 }
10945 Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
10946}
10947
10948void Assembler::stlex(Condition cond,
10949 Register rd,
10950 Register rt,
10951 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010952 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010953 CheckIT(cond);
10954 if (operand.IsImmediateZero()) {
10955 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010956 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010957 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010958 if (operand.IsOffset() &&
10959 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010960 EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
10961 (rn.GetCode() << 16));
10962 AdvanceIT();
10963 return;
10964 }
10965 } else {
10966 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010967 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010968 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010969 EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
10970 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10971 return;
10972 }
10973 }
10974 }
10975 Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
10976}
10977
10978void Assembler::stlexb(Condition cond,
10979 Register rd,
10980 Register rt,
10981 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010982 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010983 CheckIT(cond);
10984 if (operand.IsImmediateZero()) {
10985 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010986 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010987 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010988 if (operand.IsOffset() &&
10989 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010990 EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
10991 (rn.GetCode() << 16));
10992 AdvanceIT();
10993 return;
10994 }
10995 } else {
10996 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010997 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010998 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010999 EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
11000 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11001 return;
11002 }
11003 }
11004 }
11005 Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
11006}
11007
11008void Assembler::stlexd(Condition cond,
11009 Register rd,
11010 Register rt,
11011 Register rt2,
11012 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011013 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011014 CheckIT(cond);
11015 if (operand.IsImmediateZero()) {
11016 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011017 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011018 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011019 if (operand.IsOffset() &&
11020 ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11021 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011022 EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
11023 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11024 AdvanceIT();
11025 return;
11026 }
11027 } else {
11028 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11029 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011030 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011031 ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11032 !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +010011033 AllowUnpredictable())) {
11034 EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
11035 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11036 return;
11037 }
11038 }
11039 }
11040 Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
11041}
11042
11043void Assembler::stlexh(Condition cond,
11044 Register rd,
11045 Register rt,
11046 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011047 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011048 CheckIT(cond);
11049 if (operand.IsImmediateZero()) {
11050 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011051 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011052 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011053 if (operand.IsOffset() &&
11054 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011055 EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
11056 (rn.GetCode() << 16));
11057 AdvanceIT();
11058 return;
11059 }
11060 } else {
11061 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011062 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011063 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011064 EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
11065 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11066 return;
11067 }
11068 }
11069 }
11070 Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
11071}
11072
11073void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011074 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011075 CheckIT(cond);
11076 if (operand.IsImmediateZero()) {
11077 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011078 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011079 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011080 if (operand.IsOffset() &&
11081 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011082 EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
11083 AdvanceIT();
11084 return;
11085 }
11086 } else {
11087 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011088 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011089 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011090 EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
11091 (rn.GetCode() << 16));
11092 return;
11093 }
11094 }
11095 }
11096 Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
11097}
11098
11099void Assembler::stm(Condition cond,
11100 EncodingSize size,
11101 Register rn,
11102 WriteBack write_back,
11103 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011104 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011105 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011106 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011107 // STM{<c>}{<q>} <Rn>!, <registers> ; T1
11108 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11109 ((registers.GetList() & ~0xff) == 0)) {
11110 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11111 GetRegisterListEncoding(registers, 0, 8));
11112 AdvanceIT();
11113 return;
11114 }
11115 // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011116 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11117 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011118 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11119 (write_back.GetWriteBackUint32() << 21) |
11120 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11121 GetRegisterListEncoding(registers, 0, 13));
11122 AdvanceIT();
11123 return;
11124 }
11125 } else {
11126 // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011127 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011128 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11129 (write_back.GetWriteBackUint32() << 21) |
11130 GetRegisterListEncoding(registers, 0, 16));
11131 return;
11132 }
11133 }
11134 Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
11135}
11136
11137void Assembler::stmda(Condition cond,
11138 Register rn,
11139 WriteBack write_back,
11140 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011141 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011142 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011143 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011144 // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011145 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011146 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11147 (write_back.GetWriteBackUint32() << 21) |
11148 GetRegisterListEncoding(registers, 0, 16));
11149 return;
11150 }
11151 }
11152 Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
11153}
11154
11155void Assembler::stmdb(Condition cond,
11156 EncodingSize size,
11157 Register rn,
11158 WriteBack write_back,
11159 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011160 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011161 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011162 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011163 // STMDB{<c>}{<q>} SP!, <registers> ; T1
11164 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
11165 ((registers.GetList() & ~0x40ff) == 0)) {
11166 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
11167 GetRegisterListEncoding(registers, 0, 8));
11168 AdvanceIT();
11169 return;
11170 }
11171 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011172 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11173 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011174 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11175 (write_back.GetWriteBackUint32() << 21) |
11176 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11177 GetRegisterListEncoding(registers, 0, 13));
11178 AdvanceIT();
11179 return;
11180 }
11181 } else {
11182 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011183 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011184 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11185 (write_back.GetWriteBackUint32() << 21) |
11186 GetRegisterListEncoding(registers, 0, 16));
11187 return;
11188 }
11189 }
11190 Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
11191}
11192
11193void Assembler::stmea(Condition cond,
11194 EncodingSize size,
11195 Register rn,
11196 WriteBack write_back,
11197 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011198 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011199 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011200 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011201 // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
11202 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11203 ((registers.GetList() & ~0xff) == 0)) {
11204 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11205 GetRegisterListEncoding(registers, 0, 8));
11206 AdvanceIT();
11207 return;
11208 }
11209 // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011210 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11211 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011212 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11213 (write_back.GetWriteBackUint32() << 21) |
11214 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11215 GetRegisterListEncoding(registers, 0, 13));
11216 AdvanceIT();
11217 return;
11218 }
11219 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011220 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11221 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011222 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11223 (write_back.GetWriteBackUint32() << 21) |
11224 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11225 GetRegisterListEncoding(registers, 0, 13));
11226 AdvanceIT();
11227 return;
11228 }
11229 } else {
11230 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011231 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011232 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11233 (write_back.GetWriteBackUint32() << 21) |
11234 GetRegisterListEncoding(registers, 0, 16));
11235 return;
11236 }
11237 }
11238 Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
11239}
11240
11241void Assembler::stmed(Condition cond,
11242 Register rn,
11243 WriteBack write_back,
11244 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011245 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011246 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011247 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011248 // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011249 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011250 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11251 (write_back.GetWriteBackUint32() << 21) |
11252 GetRegisterListEncoding(registers, 0, 16));
11253 return;
11254 }
11255 }
11256 Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
11257}
11258
11259void Assembler::stmfa(Condition cond,
11260 Register rn,
11261 WriteBack write_back,
11262 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011263 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011264 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011265 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011266 // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011267 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011268 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11269 (write_back.GetWriteBackUint32() << 21) |
11270 GetRegisterListEncoding(registers, 0, 16));
11271 return;
11272 }
11273 }
11274 Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
11275}
11276
11277void Assembler::stmfd(Condition cond,
11278 Register rn,
11279 WriteBack write_back,
11280 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011281 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011282 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011283 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011284 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011285 if (((registers.GetList() & ~0x5fff) == 0) &&
11286 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011287 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11288 (write_back.GetWriteBackUint32() << 21) |
11289 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11290 GetRegisterListEncoding(registers, 0, 13));
11291 AdvanceIT();
11292 return;
11293 }
11294 } else {
11295 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011296 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011297 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11298 (write_back.GetWriteBackUint32() << 21) |
11299 GetRegisterListEncoding(registers, 0, 16));
11300 return;
11301 }
11302 }
11303 Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
11304}
11305
11306void Assembler::stmib(Condition cond,
11307 Register rn,
11308 WriteBack write_back,
11309 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011310 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011311 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011312 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011313 // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011314 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011315 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11316 (write_back.GetWriteBackUint32() << 21) |
11317 GetRegisterListEncoding(registers, 0, 16));
11318 return;
11319 }
11320 }
11321 Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
11322}
11323
11324void Assembler::str(Condition cond,
11325 EncodingSize size,
11326 Register rt,
11327 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011328 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011329 CheckIT(cond);
11330 if (operand.IsImmediate()) {
11331 Register rn = operand.GetBaseRegister();
11332 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011333 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011334 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11335 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011336 (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011337 int32_t offset_ = offset >> 2;
11338 EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
11339 ((offset_ & 0x1f) << 6));
11340 AdvanceIT();
11341 return;
11342 }
11343 // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
11344 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011345 ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011346 int32_t offset_ = offset >> 2;
11347 EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
11348 AdvanceIT();
11349 return;
11350 }
11351 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
11352 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011353 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11354 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011355 EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11356 (offset & 0xfff));
11357 AdvanceIT();
11358 return;
11359 }
11360 // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
11361 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011362 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11363 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011364 EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11365 (-offset & 0xff));
11366 AdvanceIT();
11367 return;
11368 }
11369 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
11370 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011371 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11372 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011373 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11374 uint32_t offset_ = abs(offset);
11375 EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11376 offset_ | (sign << 9));
11377 AdvanceIT();
11378 return;
11379 }
11380 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
11381 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011382 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11383 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011384 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11385 uint32_t offset_ = abs(offset);
11386 EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11387 offset_ | (sign << 9));
11388 AdvanceIT();
11389 return;
11390 }
11391 } else {
11392 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011393 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11394 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011395 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11396 uint32_t offset_ = abs(offset);
11397 EmitA32(0x05000000U | (cond.GetCondition() << 28) |
11398 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11399 (sign << 23));
11400 return;
11401 }
11402 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011403 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11404 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011405 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11406 uint32_t offset_ = abs(offset);
11407 EmitA32(0x04000000U | (cond.GetCondition() << 28) |
11408 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11409 (sign << 23));
11410 return;
11411 }
11412 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011413 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11414 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011415 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11416 uint32_t offset_ = abs(offset);
11417 EmitA32(0x05200000U | (cond.GetCondition() << 28) |
11418 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11419 (sign << 23));
11420 return;
11421 }
11422 }
11423 }
11424 if (operand.IsPlainRegister()) {
11425 Register rn = operand.GetBaseRegister();
11426 Sign sign = operand.GetSign();
11427 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011428 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011429 // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11430 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011431 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011432 EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
11433 (rm.GetCode() << 6));
11434 AdvanceIT();
11435 return;
11436 }
11437 }
11438 }
11439 if (operand.IsShiftedRegister()) {
11440 Register rn = operand.GetBaseRegister();
11441 Sign sign = operand.GetSign();
11442 Register rm = operand.GetOffsetRegister();
11443 Shift shift = operand.GetShift();
11444 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011445 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011446 // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11447 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011448 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11449 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011450 EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11451 rm.GetCode() | (amount << 4));
11452 AdvanceIT();
11453 return;
11454 }
11455 } else {
11456 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011457 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11458 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011459 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11460 uint32_t shift_ = TypeEncodingValue(shift);
11461 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11462 EmitA32(0x07000000U | (cond.GetCondition() << 28) |
11463 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11464 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11465 return;
11466 }
11467 // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011468 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011469 cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011470 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11471 uint32_t shift_ = TypeEncodingValue(shift);
11472 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11473 EmitA32(0x06000000U | (cond.GetCondition() << 28) |
11474 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11475 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11476 return;
11477 }
11478 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011479 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11480 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011481 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11482 uint32_t shift_ = TypeEncodingValue(shift);
11483 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11484 EmitA32(0x07200000U | (cond.GetCondition() << 28) |
11485 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11486 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11487 return;
11488 }
11489 }
11490 }
11491 Delegate(kStr, &Assembler::str, cond, size, rt, operand);
11492}
11493
11494void Assembler::strb(Condition cond,
11495 EncodingSize size,
11496 Register rt,
11497 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011498 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011499 CheckIT(cond);
11500 if (operand.IsImmediate()) {
11501 Register rn = operand.GetBaseRegister();
11502 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011503 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011504 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11505 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011506 (offset <= 31) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011507 EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
11508 ((offset & 0x1f) << 6));
11509 AdvanceIT();
11510 return;
11511 }
11512 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11513 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011514 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11515 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011516 EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11517 (offset & 0xfff));
11518 AdvanceIT();
11519 return;
11520 }
11521 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11522 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011523 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11524 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011525 EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11526 (-offset & 0xff));
11527 AdvanceIT();
11528 return;
11529 }
11530 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11531 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011532 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11533 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011534 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11535 uint32_t offset_ = abs(offset);
11536 EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11537 offset_ | (sign << 9));
11538 AdvanceIT();
11539 return;
11540 }
11541 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11542 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011543 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11544 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011545 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11546 uint32_t offset_ = abs(offset);
11547 EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11548 offset_ | (sign << 9));
11549 AdvanceIT();
11550 return;
11551 }
11552 } else {
11553 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011554 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011555 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011556 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11557 uint32_t offset_ = abs(offset);
11558 EmitA32(0x05400000U | (cond.GetCondition() << 28) |
11559 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11560 (sign << 23));
11561 return;
11562 }
11563 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011564 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011565 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011566 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11567 uint32_t offset_ = abs(offset);
11568 EmitA32(0x04400000U | (cond.GetCondition() << 28) |
11569 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11570 (sign << 23));
11571 return;
11572 }
11573 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011574 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011575 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011576 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11577 uint32_t offset_ = abs(offset);
11578 EmitA32(0x05600000U | (cond.GetCondition() << 28) |
11579 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11580 (sign << 23));
11581 return;
11582 }
11583 }
11584 }
11585 if (operand.IsPlainRegister()) {
11586 Register rn = operand.GetBaseRegister();
11587 Sign sign = operand.GetSign();
11588 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011589 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011590 // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11591 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011592 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011593 EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
11594 (rm.GetCode() << 6));
11595 AdvanceIT();
11596 return;
11597 }
11598 }
11599 }
11600 if (operand.IsShiftedRegister()) {
11601 Register rn = operand.GetBaseRegister();
11602 Sign sign = operand.GetSign();
11603 Register rm = operand.GetOffsetRegister();
11604 Shift shift = operand.GetShift();
11605 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011606 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011607 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11608 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011609 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11610 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011611 EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11612 rm.GetCode() | (amount << 4));
11613 AdvanceIT();
11614 return;
11615 }
11616 } else {
11617 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011618 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11619 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011620 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11621 uint32_t shift_ = TypeEncodingValue(shift);
11622 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11623 EmitA32(0x07400000U | (cond.GetCondition() << 28) |
11624 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11625 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11626 return;
11627 }
11628 // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011629 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011630 cond.IsNotNever() &&
11631 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011632 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11633 uint32_t shift_ = TypeEncodingValue(shift);
11634 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11635 EmitA32(0x06400000U | (cond.GetCondition() << 28) |
11636 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11637 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11638 return;
11639 }
11640 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011641 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11642 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011643 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11644 uint32_t shift_ = TypeEncodingValue(shift);
11645 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11646 EmitA32(0x07600000U | (cond.GetCondition() << 28) |
11647 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11648 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11649 return;
11650 }
11651 }
11652 }
11653 Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
11654}
11655
11656void Assembler::strd(Condition cond,
11657 Register rt,
11658 Register rt2,
11659 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011660 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011661 CheckIT(cond);
11662 if (operand.IsImmediate()) {
11663 Register rn = operand.GetBaseRegister();
11664 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011665 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011666 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
11667 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011668 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11669 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011670 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11671 uint32_t offset_ = abs(offset) >> 2;
11672 EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11673 (rn.GetCode() << 16) | offset_ | (sign << 23));
11674 AdvanceIT();
11675 return;
11676 }
11677 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
11678 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011679 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11680 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011681 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11682 uint32_t offset_ = abs(offset) >> 2;
11683 EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11684 (rn.GetCode() << 16) | offset_ | (sign << 23));
11685 AdvanceIT();
11686 return;
11687 }
11688 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
11689 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011690 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11691 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011692 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11693 uint32_t offset_ = abs(offset) >> 2;
11694 EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11695 (rn.GetCode() << 16) | offset_ | (sign << 23));
11696 AdvanceIT();
11697 return;
11698 }
11699 } else {
11700 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
11701 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011702 (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011703 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11704 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011705 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11706 uint32_t offset_ = abs(offset);
11707 EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
11708 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11709 ((offset_ & 0xf0) << 4) | (sign << 23));
11710 return;
11711 }
11712 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
11713 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011714 (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011715 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11716 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011717 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11718 uint32_t offset_ = abs(offset);
11719 EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
11720 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11721 ((offset_ & 0xf0) << 4) | (sign << 23));
11722 return;
11723 }
11724 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
11725 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011726 (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011727 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11728 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011729 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11730 uint32_t offset_ = abs(offset);
11731 EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
11732 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11733 ((offset_ & 0xf0) << 4) | (sign << 23));
11734 return;
11735 }
11736 }
11737 }
11738 if (operand.IsPlainRegister()) {
11739 Register rn = operand.GetBaseRegister();
11740 Sign sign = operand.GetSign();
11741 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011742 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011743 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
11744 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011745 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011746 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011747 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011748 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11749 EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
11750 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11751 (sign_ << 23));
11752 return;
11753 }
11754 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
11755 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011756 operand.IsPostIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011757 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011758 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011759 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11760 EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
11761 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11762 (sign_ << 23));
11763 return;
11764 }
11765 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
11766 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011767 operand.IsPreIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011768 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011769 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011770 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11771 EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
11772 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11773 (sign_ << 23));
11774 return;
11775 }
11776 }
11777 }
11778 Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
11779}
11780
11781void Assembler::strex(Condition cond,
11782 Register rd,
11783 Register rt,
11784 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011785 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011786 CheckIT(cond);
11787 if (operand.IsImmediate()) {
11788 Register rn = operand.GetBaseRegister();
11789 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011790 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011791 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
11792 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011793 operand.IsOffset() &&
11794 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011795 int32_t offset_ = offset >> 2;
11796 EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
11797 (rn.GetCode() << 16) | (offset_ & 0xff));
11798 AdvanceIT();
11799 return;
11800 }
11801 } else {
11802 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011803 if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
11804 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011805 EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
11806 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11807 return;
11808 }
11809 }
11810 }
11811 Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
11812}
11813
11814void Assembler::strexb(Condition cond,
11815 Register rd,
11816 Register rt,
11817 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011818 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011819 CheckIT(cond);
11820 if (operand.IsImmediateZero()) {
11821 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011822 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011823 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011824 if (operand.IsOffset() &&
11825 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011826 EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
11827 (rn.GetCode() << 16));
11828 AdvanceIT();
11829 return;
11830 }
11831 } else {
11832 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011833 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011834 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011835 EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
11836 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11837 return;
11838 }
11839 }
11840 }
11841 Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
11842}
11843
11844void Assembler::strexd(Condition cond,
11845 Register rd,
11846 Register rt,
11847 Register rt2,
11848 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011849 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011850 CheckIT(cond);
11851 if (operand.IsImmediateZero()) {
11852 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011853 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011854 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011855 if (operand.IsOffset() &&
11856 ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11857 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011858 EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
11859 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11860 AdvanceIT();
11861 return;
11862 }
11863 } else {
11864 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11865 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011866 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011867 ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11868 !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +010011869 AllowUnpredictable())) {
11870 EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
11871 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11872 return;
11873 }
11874 }
11875 }
11876 Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
11877}
11878
11879void Assembler::strexh(Condition cond,
11880 Register rd,
11881 Register rt,
11882 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011883 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011884 CheckIT(cond);
11885 if (operand.IsImmediateZero()) {
11886 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011887 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011888 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011889 if (operand.IsOffset() &&
11890 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011891 EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
11892 (rn.GetCode() << 16));
11893 AdvanceIT();
11894 return;
11895 }
11896 } else {
11897 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011898 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011899 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011900 EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
11901 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11902 return;
11903 }
11904 }
11905 }
11906 Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
11907}
11908
11909void Assembler::strh(Condition cond,
11910 EncodingSize size,
11911 Register rt,
11912 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011913 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011914 CheckIT(cond);
11915 if (operand.IsImmediate()) {
11916 Register rn = operand.GetBaseRegister();
11917 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011918 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011919 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11920 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011921 (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011922 int32_t offset_ = offset >> 1;
11923 EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
11924 ((offset_ & 0x1f) << 6));
11925 AdvanceIT();
11926 return;
11927 }
11928 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11929 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011930 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11931 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011932 EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11933 (offset & 0xfff));
11934 AdvanceIT();
11935 return;
11936 }
11937 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11938 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011939 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11940 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011941 EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11942 (-offset & 0xff));
11943 AdvanceIT();
11944 return;
11945 }
11946 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11947 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011948 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11949 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011950 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11951 uint32_t offset_ = abs(offset);
11952 EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11953 offset_ | (sign << 9));
11954 AdvanceIT();
11955 return;
11956 }
11957 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11958 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011959 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11960 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011961 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11962 uint32_t offset_ = abs(offset);
11963 EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11964 offset_ | (sign << 9));
11965 AdvanceIT();
11966 return;
11967 }
11968 } else {
11969 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011970 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011971 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011972 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11973 uint32_t offset_ = abs(offset);
11974 EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
11975 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11976 ((offset_ & 0xf0) << 4) | (sign << 23));
11977 return;
11978 }
11979 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011980 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011981 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011982 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11983 uint32_t offset_ = abs(offset);
11984 EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
11985 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11986 ((offset_ & 0xf0) << 4) | (sign << 23));
11987 return;
11988 }
11989 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011990 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011991 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011992 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11993 uint32_t offset_ = abs(offset);
11994 EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
11995 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11996 ((offset_ & 0xf0) << 4) | (sign << 23));
11997 return;
11998 }
11999 }
12000 }
12001 if (operand.IsPlainRegister()) {
12002 Register rn = operand.GetBaseRegister();
12003 Sign sign = operand.GetSign();
12004 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012005 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012006 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
12007 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080012008 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012009 EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
12010 (rm.GetCode() << 6));
12011 AdvanceIT();
12012 return;
12013 }
12014 } else {
12015 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012016 if (operand.IsOffset() && cond.IsNotNever() &&
12017 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012018 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12019 EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
12020 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12021 (sign_ << 23));
12022 return;
12023 }
12024 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012025 if (operand.IsPostIndex() && cond.IsNotNever() &&
12026 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012027 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12028 EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
12029 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12030 (sign_ << 23));
12031 return;
12032 }
12033 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012034 if (operand.IsPreIndex() && cond.IsNotNever() &&
12035 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012036 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12037 EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
12038 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12039 (sign_ << 23));
12040 return;
12041 }
12042 }
12043 }
12044 if (operand.IsShiftedRegister()) {
12045 Register rn = operand.GetBaseRegister();
12046 Sign sign = operand.GetSign();
12047 Register rm = operand.GetOffsetRegister();
12048 Shift shift = operand.GetShift();
12049 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012050 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012051 // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
12052 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012053 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
12054 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012055 EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12056 rm.GetCode() | (amount << 4));
12057 AdvanceIT();
12058 return;
12059 }
12060 }
12061 }
12062 Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
12063}
12064
12065void Assembler::sub(Condition cond,
12066 EncodingSize size,
12067 Register rd,
12068 Register rn,
12069 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012070 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012071 CheckIT(cond);
12072 if (operand.IsImmediate()) {
12073 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012074 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012075 ImmediateT32 immediate_t32(imm);
12076 // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
12077 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12078 (imm <= 7)) {
12079 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12080 AdvanceIT();
12081 return;
12082 }
12083 // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12084 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12085 (imm <= 255)) {
12086 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12087 AdvanceIT();
12088 return;
12089 }
12090 // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
12091 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
12092 ((imm % 4) == 0)) {
12093 uint32_t imm_ = imm >> 2;
12094 EmitT32_16(0xb080 | imm_);
12095 AdvanceIT();
12096 return;
12097 }
12098 // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +000012099 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
12100 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012101 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12102 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12103 AdvanceIT();
12104 return;
12105 }
12106 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012107 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12108 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012109 EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12110 (immediate_t32.GetEncodingValue() & 0xff) |
12111 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12112 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12113 AdvanceIT();
12114 return;
12115 }
12116 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Pierre Langlois960d28b2017-02-15 13:06:01 +000012117 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12118 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012119 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12120 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12121 AdvanceIT();
12122 return;
12123 }
12124 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012125 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12126 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012127 EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
12128 (immediate_t32.GetEncodingValue() & 0xff) |
12129 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12130 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12131 AdvanceIT();
12132 return;
12133 }
12134 // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012135 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
12136 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012137 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12138 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12139 AdvanceIT();
12140 return;
12141 }
12142 } else {
12143 ImmediateA32 immediate_a32(imm);
12144 // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
12145 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
12146 EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
12147 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12148 return;
12149 }
12150 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12151 if (immediate_a32.IsValid() && cond.IsNotNever() &&
12152 ((rn.GetCode() & 0xd) != 0xd)) {
12153 EmitA32(0x02400000U | (cond.GetCondition() << 28) |
12154 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12155 immediate_a32.GetEncodingValue());
12156 return;
12157 }
12158 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12159 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12160 EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
12161 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12162 return;
12163 }
12164 }
12165 }
12166 if (operand.IsImmediateShiftedRegister()) {
12167 Register rm = operand.GetBaseRegister();
12168 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012169 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012170 // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
12171 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12172 rm.IsLow()) {
12173 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12174 (rm.GetCode() << 6));
12175 AdvanceIT();
12176 return;
12177 }
12178 // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012179 if (rn.Is(sp) && ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012180 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
12181 AdvanceIT();
12182 return;
12183 }
12184 }
12185 }
12186 Shift shift = operand.GetShift();
12187 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012188 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012189 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012190 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12191 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012192 uint32_t amount_ = amount % 32;
12193 EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12194 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12195 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12196 AdvanceIT();
12197 return;
12198 }
12199 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012200 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12201 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012202 uint32_t amount_ = amount % 32;
12203 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
12204 (operand.GetTypeEncodingValue() << 4) |
12205 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12206 AdvanceIT();
12207 return;
12208 }
12209 } else {
12210 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12211 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12212 uint32_t amount_ = amount % 32;
12213 EmitA32(0x00400000U | (cond.GetCondition() << 28) |
12214 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12215 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12216 return;
12217 }
12218 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12219 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12220 uint32_t amount_ = amount % 32;
12221 EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
12222 (rd.GetCode() << 12) | rm.GetCode() |
12223 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12224 return;
12225 }
12226 }
12227 }
12228 if (operand.IsRegisterShiftedRegister()) {
12229 Register rm = operand.GetBaseRegister();
12230 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012231 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012232 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012233 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +000012234 if (cond.IsNotNever() &&
12235 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12236 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012237 EmitA32(0x00400010U | (cond.GetCondition() << 28) |
12238 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012239 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012240 return;
12241 }
12242 }
12243 }
12244 Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
12245}
12246
12247void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012248 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012249 CheckIT(cond);
12250 if (operand.IsImmediate()) {
12251 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012252 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012253 // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
12254 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
12255 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12256 AdvanceIT();
12257 return;
12258 }
12259 }
12260 }
12261 Delegate(kSub, &Assembler::sub, cond, rd, operand);
12262}
12263
12264void Assembler::subs(Condition cond,
12265 EncodingSize size,
12266 Register rd,
12267 Register rn,
12268 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012269 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012270 CheckIT(cond);
12271 if (operand.IsImmediate()) {
12272 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012273 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012274 ImmediateT32 immediate_t32(imm);
12275 // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
12276 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12277 (imm <= 7)) {
12278 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12279 AdvanceIT();
12280 return;
12281 }
12282 // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12283 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12284 (imm <= 255)) {
12285 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12286 AdvanceIT();
12287 return;
12288 }
12289 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12290 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012291 !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012292 EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12293 (immediate_t32.GetEncodingValue() & 0xff) |
12294 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12295 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12296 AdvanceIT();
12297 return;
12298 }
12299 // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
Pierre Langloisdc626f32017-02-15 13:31:28 +000012300 if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255) &&
12301 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012302 EmitT32_32(0xf3de8f00U | imm);
12303 AdvanceIT();
12304 return;
12305 }
12306 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12307 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12308 !rd.Is(pc)) {
12309 EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
12310 (immediate_t32.GetEncodingValue() & 0xff) |
12311 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12312 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12313 AdvanceIT();
12314 return;
12315 }
12316 } else {
12317 ImmediateA32 immediate_a32(imm);
12318 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12319 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
12320 EmitA32(0x02500000U | (cond.GetCondition() << 28) |
12321 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12322 immediate_a32.GetEncodingValue());
12323 return;
12324 }
12325 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12326 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12327 EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
12328 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12329 return;
12330 }
12331 }
12332 }
12333 if (operand.IsImmediateShiftedRegister()) {
12334 Register rm = operand.GetBaseRegister();
12335 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012336 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012337 // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12338 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12339 rm.IsLow()) {
12340 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12341 (rm.GetCode() << 6));
12342 AdvanceIT();
12343 return;
12344 }
12345 }
12346 }
12347 Shift shift = operand.GetShift();
12348 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012349 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012350 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12351 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012352 !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012353 uint32_t amount_ = amount % 32;
12354 EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12355 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12356 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12357 AdvanceIT();
12358 return;
12359 }
12360 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12361 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012362 !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012363 uint32_t amount_ = amount % 32;
12364 EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
12365 (operand.GetTypeEncodingValue() << 4) |
12366 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12367 AdvanceIT();
12368 return;
12369 }
12370 } else {
12371 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12372 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12373 uint32_t amount_ = amount % 32;
12374 EmitA32(0x00500000U | (cond.GetCondition() << 28) |
12375 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12376 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12377 return;
12378 }
12379 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12380 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12381 uint32_t amount_ = amount % 32;
12382 EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
12383 (rd.GetCode() << 12) | rm.GetCode() |
12384 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12385 return;
12386 }
12387 }
12388 }
12389 if (operand.IsRegisterShiftedRegister()) {
12390 Register rm = operand.GetBaseRegister();
12391 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012392 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012393 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012394 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +000012395 if (cond.IsNotNever() &&
12396 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12397 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012398 EmitA32(0x00500010U | (cond.GetCondition() << 28) |
12399 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012400 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012401 return;
12402 }
12403 }
12404 }
12405 Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
12406}
12407
12408void Assembler::subs(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012409 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012410 CheckIT(al);
12411 if (operand.IsImmediate()) {
12412 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012413 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012414 // SUBS{<q>} <Rdn>, #<imm8> ; T2
12415 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
12416 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12417 AdvanceIT();
12418 return;
12419 }
12420 }
12421 }
12422 Delegate(kSubs, &Assembler::subs, rd, operand);
12423}
12424
12425void Assembler::subw(Condition cond,
12426 Register rd,
12427 Register rn,
12428 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012429 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012430 CheckIT(cond);
12431 if (operand.IsImmediate()) {
12432 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012433 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012434 // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Pierre Langlois960d28b2017-02-15 13:06:01 +000012435 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12436 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012437 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12438 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12439 AdvanceIT();
12440 return;
12441 }
12442 // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012443 if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012444 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12445 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12446 AdvanceIT();
12447 return;
12448 }
12449 }
12450 }
12451 Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
12452}
12453
12454void Assembler::svc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012455 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012456 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012457 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012458 // SVC{<c>}{<q>} {#}<imm> ; T1
12459 if ((imm <= 255)) {
12460 EmitT32_16(0xdf00 | imm);
12461 AdvanceIT();
12462 return;
12463 }
12464 } else {
12465 // SVC{<c>}{<q>} {#}<imm> ; A1
12466 if ((imm <= 16777215) && cond.IsNotNever()) {
12467 EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
12468 return;
12469 }
12470 }
12471 Delegate(kSvc, &Assembler::svc, cond, imm);
12472}
12473
12474void Assembler::sxtab(Condition cond,
12475 Register rd,
12476 Register rn,
12477 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012478 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012479 CheckIT(cond);
12480 if (operand.IsImmediateShiftedRegister()) {
12481 Register rm = operand.GetBaseRegister();
12482 Shift shift = operand.GetShift();
12483 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012484 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012485 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12486 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012487 ((amount % 8) == 0) && !rn.Is(pc) &&
12488 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012489 uint32_t amount_ = amount / 8;
12490 EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12491 rm.GetCode() | (amount_ << 4));
12492 AdvanceIT();
12493 return;
12494 }
12495 } else {
12496 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12497 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012498 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12499 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012500 uint32_t amount_ = amount / 8;
12501 EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
12502 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12503 (amount_ << 10));
12504 return;
12505 }
12506 }
12507 }
12508 Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
12509}
12510
12511void Assembler::sxtab16(Condition cond,
12512 Register rd,
12513 Register rn,
12514 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012515 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012516 CheckIT(cond);
12517 if (operand.IsImmediateShiftedRegister()) {
12518 Register rm = operand.GetBaseRegister();
12519 Shift shift = operand.GetShift();
12520 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012521 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012522 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12523 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012524 ((amount % 8) == 0) && !rn.Is(pc) &&
12525 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012526 uint32_t amount_ = amount / 8;
12527 EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12528 rm.GetCode() | (amount_ << 4));
12529 AdvanceIT();
12530 return;
12531 }
12532 } else {
12533 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12534 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012535 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12536 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012537 uint32_t amount_ = amount / 8;
12538 EmitA32(0x06800070U | (cond.GetCondition() << 28) |
12539 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12540 (amount_ << 10));
12541 return;
12542 }
12543 }
12544 }
12545 Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
12546}
12547
12548void Assembler::sxtah(Condition cond,
12549 Register rd,
12550 Register rn,
12551 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012552 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012553 CheckIT(cond);
12554 if (operand.IsImmediateShiftedRegister()) {
12555 Register rm = operand.GetBaseRegister();
12556 Shift shift = operand.GetShift();
12557 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012558 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012559 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12560 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012561 ((amount % 8) == 0) && !rn.Is(pc) &&
12562 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012563 uint32_t amount_ = amount / 8;
12564 EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12565 rm.GetCode() | (amount_ << 4));
12566 AdvanceIT();
12567 return;
12568 }
12569 } else {
12570 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12571 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012572 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12573 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012574 uint32_t amount_ = amount / 8;
12575 EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
12576 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12577 (amount_ << 10));
12578 return;
12579 }
12580 }
12581 }
12582 Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
12583}
12584
12585void Assembler::sxtb(Condition cond,
12586 EncodingSize size,
12587 Register rd,
12588 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012589 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012590 CheckIT(cond);
12591 if (operand.IsImmediateShiftedRegister()) {
12592 Register rm = operand.GetBaseRegister();
12593 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012594 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012595 // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12596 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12597 EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
12598 AdvanceIT();
12599 return;
12600 }
12601 }
12602 }
12603 Shift shift = operand.GetShift();
12604 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012605 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012606 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12607 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012608 (amount <= 24) && ((amount % 8) == 0) &&
12609 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012610 uint32_t amount_ = amount / 8;
12611 EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12612 (amount_ << 4));
12613 AdvanceIT();
12614 return;
12615 }
12616 } else {
12617 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12618 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012619 ((amount % 8) == 0) && cond.IsNotNever() &&
12620 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012621 uint32_t amount_ = amount / 8;
12622 EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
12623 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12624 return;
12625 }
12626 }
12627 }
12628 Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
12629}
12630
12631void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012632 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012633 CheckIT(cond);
12634 if (operand.IsImmediateShiftedRegister()) {
12635 Register rm = operand.GetBaseRegister();
12636 Shift shift = operand.GetShift();
12637 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012638 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012639 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12640 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012641 ((amount % 8) == 0) &&
12642 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012643 uint32_t amount_ = amount / 8;
12644 EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12645 (amount_ << 4));
12646 AdvanceIT();
12647 return;
12648 }
12649 } else {
12650 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12651 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012652 ((amount % 8) == 0) && cond.IsNotNever() &&
12653 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012654 uint32_t amount_ = amount / 8;
12655 EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
12656 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12657 return;
12658 }
12659 }
12660 }
12661 Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
12662}
12663
12664void Assembler::sxth(Condition cond,
12665 EncodingSize size,
12666 Register rd,
12667 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012668 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012669 CheckIT(cond);
12670 if (operand.IsImmediateShiftedRegister()) {
12671 Register rm = operand.GetBaseRegister();
12672 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012673 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012674 // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12675 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12676 EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
12677 AdvanceIT();
12678 return;
12679 }
12680 }
12681 }
12682 Shift shift = operand.GetShift();
12683 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012684 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012685 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12686 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012687 (amount <= 24) && ((amount % 8) == 0) &&
12688 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012689 uint32_t amount_ = amount / 8;
12690 EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12691 (amount_ << 4));
12692 AdvanceIT();
12693 return;
12694 }
12695 } else {
12696 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12697 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012698 ((amount % 8) == 0) && cond.IsNotNever() &&
12699 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012700 uint32_t amount_ = amount / 8;
12701 EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
12702 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12703 return;
12704 }
12705 }
12706 }
12707 Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
12708}
12709
12710void Assembler::tbb(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012711 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012712 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012713 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012714 // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
12715 if (OutsideITBlockAndAlOrLast(cond) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080012716 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012717 EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
12718 AdvanceIT();
12719 return;
12720 }
12721 }
12722 Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
12723}
12724
12725void Assembler::tbh(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012726 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012727 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012728 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012729 // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
12730 if (OutsideITBlockAndAlOrLast(cond) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080012731 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012732 EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
12733 AdvanceIT();
12734 return;
12735 }
12736 }
12737 Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
12738}
12739
12740void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012741 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012742 CheckIT(cond);
12743 if (operand.IsImmediate()) {
12744 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012745 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012746 ImmediateT32 immediate_t32(imm);
12747 // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012748 if (immediate_t32.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012749 EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
12750 (immediate_t32.GetEncodingValue() & 0xff) |
12751 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12752 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12753 AdvanceIT();
12754 return;
12755 }
12756 } else {
12757 ImmediateA32 immediate_a32(imm);
12758 // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
12759 if (immediate_a32.IsValid() && cond.IsNotNever()) {
12760 EmitA32(0x03300000U | (cond.GetCondition() << 28) |
12761 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12762 return;
12763 }
12764 }
12765 }
12766 if (operand.IsImmediateShiftedRegister()) {
12767 Register rm = operand.GetBaseRegister();
12768 Shift shift = operand.GetShift();
12769 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012770 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012771 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012772 if (shift.IsValidAmount(amount) &&
12773 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012774 uint32_t amount_ = amount % 32;
12775 EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
12776 (operand.GetTypeEncodingValue() << 4) |
12777 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12778 AdvanceIT();
12779 return;
12780 }
12781 } else {
12782 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12783 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12784 uint32_t amount_ = amount % 32;
12785 EmitA32(0x01300000U | (cond.GetCondition() << 28) |
12786 (rn.GetCode() << 16) | rm.GetCode() |
12787 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12788 return;
12789 }
12790 }
12791 }
12792 if (operand.IsRegisterShiftedRegister()) {
12793 Register rm = operand.GetBaseRegister();
12794 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012795 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012796 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012797 // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012798 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +000012799 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012800 EmitA32(0x01300010U | (cond.GetCondition() << 28) |
12801 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012802 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012803 return;
12804 }
12805 }
12806 }
12807 Delegate(kTeq, &Assembler::teq, cond, rn, operand);
12808}
12809
12810void Assembler::tst(Condition cond,
12811 EncodingSize size,
12812 Register rn,
12813 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012814 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012815 CheckIT(cond);
12816 if (operand.IsImmediate()) {
12817 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012818 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012819 ImmediateT32 immediate_t32(imm);
12820 // TST{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012821 if (!size.IsNarrow() && immediate_t32.IsValid() &&
12822 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012823 EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
12824 (immediate_t32.GetEncodingValue() & 0xff) |
12825 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12826 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12827 AdvanceIT();
12828 return;
12829 }
12830 } else {
12831 ImmediateA32 immediate_a32(imm);
12832 // TST{<c>}{<q>} <Rn>, #<const> ; A1
12833 if (immediate_a32.IsValid() && cond.IsNotNever()) {
12834 EmitA32(0x03100000U | (cond.GetCondition() << 28) |
12835 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12836 return;
12837 }
12838 }
12839 }
12840 if (operand.IsImmediateShiftedRegister()) {
12841 Register rm = operand.GetBaseRegister();
12842 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012844 // TST{<c>}{<q>} <Rn>, <Rm> ; T1
12845 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
12846 EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
12847 AdvanceIT();
12848 return;
12849 }
12850 }
12851 }
12852 Shift shift = operand.GetShift();
12853 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012854 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012855 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012856 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
12857 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012858 uint32_t amount_ = amount % 32;
12859 EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
12860 (operand.GetTypeEncodingValue() << 4) |
12861 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12862 AdvanceIT();
12863 return;
12864 }
12865 } else {
12866 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12867 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12868 uint32_t amount_ = amount % 32;
12869 EmitA32(0x01100000U | (cond.GetCondition() << 28) |
12870 (rn.GetCode() << 16) | rm.GetCode() |
12871 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12872 return;
12873 }
12874 }
12875 }
12876 if (operand.IsRegisterShiftedRegister()) {
12877 Register rm = operand.GetBaseRegister();
12878 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012879 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012880 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012881 // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012882 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +000012883 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012884 EmitA32(0x01100010U | (cond.GetCondition() << 28) |
12885 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012886 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012887 return;
12888 }
12889 }
12890 }
12891 Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
12892}
12893
12894void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012895 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012896 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012897 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012898 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012899 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12900 EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12901 rm.GetCode());
12902 AdvanceIT();
12903 return;
12904 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012905 } else {
12906 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012907 if (cond.IsNotNever() &&
12908 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012909 EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12910 (rn.GetCode() << 16) | rm.GetCode());
12911 return;
12912 }
12913 }
12914 Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
12915}
12916
12917void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012918 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012919 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012920 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012921 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012922 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12923 EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12924 rm.GetCode());
12925 AdvanceIT();
12926 return;
12927 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012928 } else {
12929 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012930 if (cond.IsNotNever() &&
12931 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012932 EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12933 (rn.GetCode() << 16) | rm.GetCode());
12934 return;
12935 }
12936 }
12937 Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
12938}
12939
12940void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012941 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012942 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012944 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012945 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12946 EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12947 rm.GetCode());
12948 AdvanceIT();
12949 return;
12950 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012951 } else {
12952 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012953 if (cond.IsNotNever() &&
12954 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012955 EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12956 (rn.GetCode() << 16) | rm.GetCode());
12957 return;
12958 }
12959 }
12960 Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
12961}
12962
Vincent Belliard609821f2017-02-08 14:17:25 -080012963void Assembler::ubfx(
12964 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012965 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012966 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -080012967 if (IsUsingT32()) {
12968 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
12969 if ((lsb <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012970 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
12971 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -080012972 uint32_t widthm1 = width - 1;
12973 EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12974 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
12975 AdvanceIT();
12976 return;
12977 }
12978 } else {
12979 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
12980 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012981 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
12982 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -080012983 uint32_t widthm1 = width - 1;
12984 EmitA32(0x07e00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12985 rn.GetCode() | (lsb << 7) | (widthm1 << 16));
12986 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +010012987 }
12988 }
Vincent Belliard609821f2017-02-08 14:17:25 -080012989 Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +010012990}
12991
12992void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012993 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012994 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012995 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012996 // UDF{<c>}{<q>} {#}<imm> ; T1
12997 if (!size.IsWide() && (imm <= 255)) {
12998 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12999 EmitT32_16(0xde00 | imm);
13000 AdvanceIT();
13001 return;
13002 }
13003 }
13004 // UDF{<c>}{<q>} {#}<imm> ; T2
13005 if (!size.IsNarrow() && (imm <= 65535)) {
13006 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13007 EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
13008 AdvanceIT();
13009 return;
13010 }
13011 }
13012 } else {
13013 // UDF{<c>}{<q>} {#}<imm> ; A1
13014 if ((imm <= 65535)) {
13015 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13016 EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
13017 return;
13018 }
13019 }
13020 }
13021 Delegate(kUdf, &Assembler::udf, cond, size, imm);
13022}
13023
13024void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013025 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013026 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013027 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013028 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013029 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13030 EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13031 rm.GetCode());
13032 AdvanceIT();
13033 return;
13034 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013035 } else {
13036 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013037 if (cond.IsNotNever() &&
13038 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013039 EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13040 rn.GetCode() | (rm.GetCode() << 8));
13041 return;
13042 }
13043 }
13044 Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
13045}
13046
13047void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013048 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013049 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013050 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013051 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013052 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13053 EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13054 rm.GetCode());
13055 AdvanceIT();
13056 return;
13057 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013058 } else {
13059 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013060 if (cond.IsNotNever() &&
13061 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013062 EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13063 (rn.GetCode() << 16) | rm.GetCode());
13064 return;
13065 }
13066 }
13067 Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
13068}
13069
13070void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013071 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013072 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013074 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013075 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13076 EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13077 rm.GetCode());
13078 AdvanceIT();
13079 return;
13080 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013081 } else {
13082 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013083 if (cond.IsNotNever() &&
13084 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013085 EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13086 (rn.GetCode() << 16) | rm.GetCode());
13087 return;
13088 }
13089 }
13090 Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
13091}
13092
13093void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013094 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013095 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013096 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013097 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013098 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13099 EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13100 rm.GetCode());
13101 AdvanceIT();
13102 return;
13103 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013104 } else {
13105 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013106 if (cond.IsNotNever() &&
13107 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013108 EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13109 (rn.GetCode() << 16) | rm.GetCode());
13110 return;
13111 }
13112 }
13113 Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
13114}
13115
13116void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013117 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013118 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013119 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013120 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013121 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13122 EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13123 rm.GetCode());
13124 AdvanceIT();
13125 return;
13126 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013127 } else {
13128 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013129 if (cond.IsNotNever() &&
13130 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013131 EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13132 (rn.GetCode() << 16) | rm.GetCode());
13133 return;
13134 }
13135 }
13136 Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
13137}
13138
13139void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013140 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013141 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013142 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013143 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013144 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13145 EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13146 rm.GetCode());
13147 AdvanceIT();
13148 return;
13149 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013150 } else {
13151 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013152 if (cond.IsNotNever() &&
13153 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013154 EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13155 (rn.GetCode() << 16) | rm.GetCode());
13156 return;
13157 }
13158 }
13159 Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
13160}
13161
13162void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013163 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013164 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013165 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013166 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013167 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13168 EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13169 rm.GetCode());
13170 AdvanceIT();
13171 return;
13172 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013173 } else {
13174 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013175 if (cond.IsNotNever() &&
13176 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013177 EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13178 (rn.GetCode() << 16) | rm.GetCode());
13179 return;
13180 }
13181 }
13182 Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
13183}
13184
13185void Assembler::umaal(
13186 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013187 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013188 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013189 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013190 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013191 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13192 AllowUnpredictable())) {
13193 EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13194 (rn.GetCode() << 16) | rm.GetCode());
13195 AdvanceIT();
13196 return;
13197 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013198 } else {
13199 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013200 if (cond.IsNotNever() &&
13201 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13202 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013203 EmitA32(0x00400090U | (cond.GetCondition() << 28) |
13204 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13205 (rm.GetCode() << 8));
13206 return;
13207 }
13208 }
13209 Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
13210}
13211
13212void Assembler::umlal(
13213 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013214 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013215 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013216 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013217 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013218 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13219 AllowUnpredictable())) {
13220 EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13221 (rn.GetCode() << 16) | rm.GetCode());
13222 AdvanceIT();
13223 return;
13224 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013225 } else {
13226 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013227 if (cond.IsNotNever() &&
13228 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13229 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013230 EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
13231 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13232 (rm.GetCode() << 8));
13233 return;
13234 }
13235 }
13236 Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
13237}
13238
13239void Assembler::umlals(
13240 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013241 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013242 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013243 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013244 // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013245 if (cond.IsNotNever() &&
13246 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13247 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013248 EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
13249 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13250 (rm.GetCode() << 8));
13251 return;
13252 }
13253 }
13254 Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
13255}
13256
13257void Assembler::umull(
13258 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013259 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013260 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013261 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013262 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013263 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13264 AllowUnpredictable())) {
13265 EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13266 (rn.GetCode() << 16) | rm.GetCode());
13267 AdvanceIT();
13268 return;
13269 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013270 } else {
13271 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013272 if (cond.IsNotNever() &&
13273 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13274 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013275 EmitA32(0x00800090U | (cond.GetCondition() << 28) |
13276 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13277 (rm.GetCode() << 8));
13278 return;
13279 }
13280 }
13281 Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
13282}
13283
13284void Assembler::umulls(
13285 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013286 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013287 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013288 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013289 // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013290 if (cond.IsNotNever() &&
13291 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13292 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013293 EmitA32(0x00900090U | (cond.GetCondition() << 28) |
13294 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13295 (rm.GetCode() << 8));
13296 return;
13297 }
13298 }
13299 Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
13300}
13301
13302void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013303 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013304 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013305 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013306 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013307 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13308 EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13309 rm.GetCode());
13310 AdvanceIT();
13311 return;
13312 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013313 } else {
13314 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013315 if (cond.IsNotNever() &&
13316 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013317 EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13318 (rn.GetCode() << 16) | rm.GetCode());
13319 return;
13320 }
13321 }
13322 Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
13323}
13324
13325void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013326 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013327 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013328 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013329 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013330 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13331 EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13332 rm.GetCode());
13333 AdvanceIT();
13334 return;
13335 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013336 } else {
13337 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013338 if (cond.IsNotNever() &&
13339 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013340 EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13341 (rn.GetCode() << 16) | rm.GetCode());
13342 return;
13343 }
13344 }
13345 Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
13346}
13347
13348void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013349 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013350 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013352 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013353 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13354 EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13355 rm.GetCode());
13356 AdvanceIT();
13357 return;
13358 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013359 } else {
13360 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013361 if (cond.IsNotNever() &&
13362 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013363 EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13364 (rn.GetCode() << 16) | rm.GetCode());
13365 return;
13366 }
13367 }
13368 Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
13369}
13370
13371void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013372 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013373 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013374 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013375 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013376 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13377 EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13378 rm.GetCode());
13379 AdvanceIT();
13380 return;
13381 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013382 } else {
13383 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013384 if (cond.IsNotNever() &&
13385 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013386 EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13387 (rn.GetCode() << 16) | rm.GetCode());
13388 return;
13389 }
13390 }
13391 Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
13392}
13393
13394void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013395 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013396 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013397 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013398 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013399 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13400 EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13401 rm.GetCode());
13402 AdvanceIT();
13403 return;
13404 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013405 } else {
13406 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013407 if (cond.IsNotNever() &&
13408 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013409 EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13410 (rn.GetCode() << 16) | rm.GetCode());
13411 return;
13412 }
13413 }
13414 Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
13415}
13416
13417void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013418 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013419 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013420 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013421 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013422 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13423 EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13424 rm.GetCode());
13425 AdvanceIT();
13426 return;
13427 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013428 } else {
13429 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013430 if (cond.IsNotNever() &&
13431 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013432 EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13433 (rn.GetCode() << 16) | rm.GetCode());
13434 return;
13435 }
13436 }
13437 Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
13438}
13439
13440void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013441 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013442 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013443 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013444 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013445 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13446 EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13447 rm.GetCode());
13448 AdvanceIT();
13449 return;
13450 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013451 } else {
13452 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013453 if (cond.IsNotNever() &&
13454 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013455 EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13456 rn.GetCode() | (rm.GetCode() << 8));
13457 return;
13458 }
13459 }
13460 Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
13461}
13462
13463void Assembler::usada8(
13464 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013465 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013466 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013467 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013468 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013469 if (!ra.Is(pc) &&
13470 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013471 EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13472 rm.GetCode() | (ra.GetCode() << 12));
13473 AdvanceIT();
13474 return;
13475 }
13476 } else {
13477 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013478 if (cond.IsNotNever() && !ra.Is(pc) &&
13479 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013480 EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13481 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
13482 return;
13483 }
13484 }
13485 Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
13486}
13487
13488void Assembler::usat(Condition cond,
13489 Register rd,
13490 uint32_t imm,
13491 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013493 CheckIT(cond);
13494 if (operand.IsImmediateShiftedRegister()) {
13495 Register rn = operand.GetBaseRegister();
13496 Shift shift = operand.GetShift();
13497 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013498 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013499 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013500 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31) &&
13501 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013502 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13503 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13504 ((amount & 0x1c) << 10));
13505 AdvanceIT();
13506 return;
13507 }
13508 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013509 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) &&
13510 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013511 EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
13512 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13513 ((amount & 0x1c) << 10));
13514 AdvanceIT();
13515 return;
13516 }
13517 } else {
13518 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
13519 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013520 cond.IsNotNever() &&
13521 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013522 uint32_t amount_ = amount % 32;
13523 EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
13524 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13525 (amount_ << 7));
13526 return;
13527 }
13528 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013529 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever() &&
13530 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013531 EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
13532 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13533 (amount << 7));
13534 return;
13535 }
13536 }
13537 }
13538 Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
13539}
13540
13541void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013542 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013543 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013544 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013545 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013546 if ((imm <= 15) && ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013547 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13548 (rn.GetCode() << 16));
13549 AdvanceIT();
13550 return;
13551 }
13552 } else {
13553 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013554 if ((imm <= 15) && cond.IsNotNever() &&
13555 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013556 EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13557 (imm << 16) | rn.GetCode());
13558 return;
13559 }
13560 }
13561 Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
13562}
13563
13564void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013565 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013566 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013567 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013568 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013569 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13570 EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13571 rm.GetCode());
13572 AdvanceIT();
13573 return;
13574 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013575 } else {
13576 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013577 if (cond.IsNotNever() &&
13578 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013579 EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13580 (rn.GetCode() << 16) | rm.GetCode());
13581 return;
13582 }
13583 }
13584 Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
13585}
13586
13587void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013588 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013589 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013590 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013591 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013592 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13593 EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13594 rm.GetCode());
13595 AdvanceIT();
13596 return;
13597 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013598 } else {
13599 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013600 if (cond.IsNotNever() &&
13601 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013602 EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13603 (rn.GetCode() << 16) | rm.GetCode());
13604 return;
13605 }
13606 }
13607 Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
13608}
13609
13610void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013611 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013612 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013613 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013614 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013615 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13616 EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13617 rm.GetCode());
13618 AdvanceIT();
13619 return;
13620 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013621 } else {
13622 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013623 if (cond.IsNotNever() &&
13624 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013625 EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13626 (rn.GetCode() << 16) | rm.GetCode());
13627 return;
13628 }
13629 }
13630 Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
13631}
13632
13633void Assembler::uxtab(Condition cond,
13634 Register rd,
13635 Register rn,
13636 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013637 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013638 CheckIT(cond);
13639 if (operand.IsImmediateShiftedRegister()) {
13640 Register rm = operand.GetBaseRegister();
13641 Shift shift = operand.GetShift();
13642 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013643 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013644 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13645 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013646 ((amount % 8) == 0) && !rn.Is(pc) &&
13647 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013648 uint32_t amount_ = amount / 8;
13649 EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13650 rm.GetCode() | (amount_ << 4));
13651 AdvanceIT();
13652 return;
13653 }
13654 } else {
13655 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13656 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013657 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13658 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013659 uint32_t amount_ = amount / 8;
13660 EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
13661 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13662 (amount_ << 10));
13663 return;
13664 }
13665 }
13666 }
13667 Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
13668}
13669
13670void Assembler::uxtab16(Condition cond,
13671 Register rd,
13672 Register rn,
13673 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013674 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013675 CheckIT(cond);
13676 if (operand.IsImmediateShiftedRegister()) {
13677 Register rm = operand.GetBaseRegister();
13678 Shift shift = operand.GetShift();
13679 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013680 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013681 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13682 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013683 ((amount % 8) == 0) && !rn.Is(pc) &&
13684 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013685 uint32_t amount_ = amount / 8;
13686 EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13687 rm.GetCode() | (amount_ << 4));
13688 AdvanceIT();
13689 return;
13690 }
13691 } else {
13692 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13693 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013694 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13695 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013696 uint32_t amount_ = amount / 8;
13697 EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
13698 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13699 (amount_ << 10));
13700 return;
13701 }
13702 }
13703 }
13704 Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
13705}
13706
13707void Assembler::uxtah(Condition cond,
13708 Register rd,
13709 Register rn,
13710 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013711 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013712 CheckIT(cond);
13713 if (operand.IsImmediateShiftedRegister()) {
13714 Register rm = operand.GetBaseRegister();
13715 Shift shift = operand.GetShift();
13716 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013717 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013718 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13719 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013720 ((amount % 8) == 0) && !rn.Is(pc) &&
13721 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013722 uint32_t amount_ = amount / 8;
13723 EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13724 rm.GetCode() | (amount_ << 4));
13725 AdvanceIT();
13726 return;
13727 }
13728 } else {
13729 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13730 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013731 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13732 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013733 uint32_t amount_ = amount / 8;
13734 EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
13735 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13736 (amount_ << 10));
13737 return;
13738 }
13739 }
13740 }
13741 Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
13742}
13743
13744void Assembler::uxtb(Condition cond,
13745 EncodingSize size,
13746 Register rd,
13747 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013748 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013749 CheckIT(cond);
13750 if (operand.IsImmediateShiftedRegister()) {
13751 Register rm = operand.GetBaseRegister();
13752 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013754 // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
13755 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13756 EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
13757 AdvanceIT();
13758 return;
13759 }
13760 }
13761 }
13762 Shift shift = operand.GetShift();
13763 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013764 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013765 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13766 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013767 (amount <= 24) && ((amount % 8) == 0) &&
13768 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013769 uint32_t amount_ = amount / 8;
13770 EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13771 (amount_ << 4));
13772 AdvanceIT();
13773 return;
13774 }
13775 } else {
13776 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13777 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013778 ((amount % 8) == 0) && cond.IsNotNever() &&
13779 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013780 uint32_t amount_ = amount / 8;
13781 EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
13782 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13783 return;
13784 }
13785 }
13786 }
13787 Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
13788}
13789
13790void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013791 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013792 CheckIT(cond);
13793 if (operand.IsImmediateShiftedRegister()) {
13794 Register rm = operand.GetBaseRegister();
13795 Shift shift = operand.GetShift();
13796 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013797 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013798 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
13799 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013800 ((amount % 8) == 0) &&
13801 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013802 uint32_t amount_ = amount / 8;
13803 EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13804 (amount_ << 4));
13805 AdvanceIT();
13806 return;
13807 }
13808 } else {
13809 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13810 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013811 ((amount % 8) == 0) && cond.IsNotNever() &&
13812 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013813 uint32_t amount_ = amount / 8;
13814 EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
13815 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13816 return;
13817 }
13818 }
13819 }
13820 Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
13821}
13822
13823void Assembler::uxth(Condition cond,
13824 EncodingSize size,
13825 Register rd,
13826 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013827 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013828 CheckIT(cond);
13829 if (operand.IsImmediateShiftedRegister()) {
13830 Register rm = operand.GetBaseRegister();
13831 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013833 // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
13834 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13835 EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
13836 AdvanceIT();
13837 return;
13838 }
13839 }
13840 }
13841 Shift shift = operand.GetShift();
13842 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013844 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13845 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013846 (amount <= 24) && ((amount % 8) == 0) &&
13847 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013848 uint32_t amount_ = amount / 8;
13849 EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13850 (amount_ << 4));
13851 AdvanceIT();
13852 return;
13853 }
13854 } else {
13855 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13856 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013857 ((amount % 8) == 0) && cond.IsNotNever() &&
13858 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013859 uint32_t amount_ = amount / 8;
13860 EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
13861 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13862 return;
13863 }
13864 }
13865 }
13866 Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
13867}
13868
13869void Assembler::vaba(
13870 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013871 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013872 CheckIT(cond);
13873 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013874 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013875 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
13876 if (encoded_dt.IsValid()) {
13877 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13878 EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13879 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13880 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13881 AdvanceIT();
13882 return;
13883 }
13884 }
13885 } else {
13886 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
13887 if (encoded_dt.IsValid()) {
13888 if (cond.Is(al)) {
13889 EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13890 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13891 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13892 return;
13893 }
13894 }
13895 }
13896 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13897}
13898
13899void Assembler::vaba(
13900 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013901 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013902 CheckIT(cond);
13903 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013904 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013905 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
13906 if (encoded_dt.IsValid()) {
13907 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13908 EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13909 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13910 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13911 AdvanceIT();
13912 return;
13913 }
13914 }
13915 } else {
13916 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
13917 if (encoded_dt.IsValid()) {
13918 if (cond.Is(al)) {
13919 EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13920 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13921 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13922 return;
13923 }
13924 }
13925 }
13926 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13927}
13928
13929void Assembler::vabal(
13930 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013931 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013932 CheckIT(cond);
13933 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013934 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013935 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13936 if (encoded_dt.IsValid()) {
13937 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13938 EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13939 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13940 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13941 AdvanceIT();
13942 return;
13943 }
13944 }
13945 } else {
13946 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13947 if (encoded_dt.IsValid()) {
13948 if (cond.Is(al)) {
13949 EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13950 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13951 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13952 return;
13953 }
13954 }
13955 }
13956 Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
13957}
13958
13959void Assembler::vabd(
13960 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013961 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013962 CheckIT(cond);
13963 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013964 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013965 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13966 if (dt.Is(F32)) {
13967 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13968 EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13969 rm.Encode(5, 0));
13970 AdvanceIT();
13971 return;
13972 }
13973 }
13974 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13975 if (encoded_dt.IsValid()) {
13976 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13977 EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13978 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13979 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13980 AdvanceIT();
13981 return;
13982 }
13983 }
13984 } else {
13985 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13986 if (dt.Is(F32)) {
13987 if (cond.Is(al)) {
13988 EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13989 rm.Encode(5, 0));
13990 return;
13991 }
13992 }
13993 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13994 if (encoded_dt.IsValid()) {
13995 if (cond.Is(al)) {
13996 EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13997 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13998 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13999 return;
14000 }
14001 }
14002 }
14003 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14004}
14005
14006void Assembler::vabd(
14007 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014008 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014009 CheckIT(cond);
14010 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014011 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014012 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14013 if (dt.Is(F32)) {
14014 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14015 EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14016 rm.Encode(5, 0));
14017 AdvanceIT();
14018 return;
14019 }
14020 }
14021 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14022 if (encoded_dt.IsValid()) {
14023 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14024 EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14025 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14026 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14027 AdvanceIT();
14028 return;
14029 }
14030 }
14031 } else {
14032 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14033 if (dt.Is(F32)) {
14034 if (cond.Is(al)) {
14035 EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14036 rm.Encode(5, 0));
14037 return;
14038 }
14039 }
14040 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14041 if (encoded_dt.IsValid()) {
14042 if (cond.Is(al)) {
14043 EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14044 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14045 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14046 return;
14047 }
14048 }
14049 }
14050 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14051}
14052
14053void Assembler::vabdl(
14054 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014055 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014056 CheckIT(cond);
14057 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014058 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014059 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14060 if (encoded_dt.IsValid()) {
14061 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14062 EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14063 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14064 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14065 AdvanceIT();
14066 return;
14067 }
14068 }
14069 } else {
14070 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14071 if (encoded_dt.IsValid()) {
14072 if (cond.Is(al)) {
14073 EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14074 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14075 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14076 return;
14077 }
14078 }
14079 }
14080 Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
14081}
14082
14083void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014084 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014085 CheckIT(cond);
14086 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014087 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014088 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14089 if (encoded_dt.IsValid()) {
14090 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14091 EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14092 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14093 rd.Encode(22, 12) | rm.Encode(5, 0));
14094 AdvanceIT();
14095 return;
14096 }
14097 }
14098 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
14099 if (dt.Is(F64)) {
14100 EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14101 AdvanceIT();
14102 return;
14103 }
14104 } else {
14105 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14106 if (encoded_dt.IsValid()) {
14107 if (cond.Is(al)) {
14108 EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14109 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14110 rd.Encode(22, 12) | rm.Encode(5, 0));
14111 return;
14112 }
14113 }
14114 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
14115 if (dt.Is(F64) && cond.IsNotNever()) {
14116 EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14117 rm.Encode(5, 0));
14118 return;
14119 }
14120 }
14121 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14122}
14123
14124void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014125 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014126 CheckIT(cond);
14127 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014128 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014129 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14130 if (encoded_dt.IsValid()) {
14131 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14132 EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14133 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14134 rd.Encode(22, 12) | rm.Encode(5, 0));
14135 AdvanceIT();
14136 return;
14137 }
14138 }
14139 } else {
14140 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14141 if (encoded_dt.IsValid()) {
14142 if (cond.Is(al)) {
14143 EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14144 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14145 rd.Encode(22, 12) | rm.Encode(5, 0));
14146 return;
14147 }
14148 }
14149 }
14150 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14151}
14152
14153void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014154 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014155 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014156 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014157 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
14158 if (dt.Is(F32)) {
14159 EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14160 AdvanceIT();
14161 return;
14162 }
14163 } else {
14164 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
14165 if (dt.Is(F32) && cond.IsNotNever()) {
14166 EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14167 rm.Encode(5, 0));
14168 return;
14169 }
14170 }
14171 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14172}
14173
14174void Assembler::vacge(
14175 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014176 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014177 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014178 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014179 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14180 if (dt.Is(F32)) {
14181 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14182 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14183 rm.Encode(5, 0));
14184 AdvanceIT();
14185 return;
14186 }
14187 }
14188 } else {
14189 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14190 if (dt.Is(F32)) {
14191 if (cond.Is(al)) {
14192 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14193 rm.Encode(5, 0));
14194 return;
14195 }
14196 }
14197 }
14198 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14199}
14200
14201void Assembler::vacge(
14202 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014203 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014204 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014205 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014206 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14207 if (dt.Is(F32)) {
14208 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14209 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14210 rm.Encode(5, 0));
14211 AdvanceIT();
14212 return;
14213 }
14214 }
14215 } else {
14216 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14217 if (dt.Is(F32)) {
14218 if (cond.Is(al)) {
14219 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14220 rm.Encode(5, 0));
14221 return;
14222 }
14223 }
14224 }
14225 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14226}
14227
14228void Assembler::vacgt(
14229 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014230 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014231 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014232 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014233 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14234 if (dt.Is(F32)) {
14235 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14236 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14237 rm.Encode(5, 0));
14238 AdvanceIT();
14239 return;
14240 }
14241 }
14242 } else {
14243 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14244 if (dt.Is(F32)) {
14245 if (cond.Is(al)) {
14246 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14247 rm.Encode(5, 0));
14248 return;
14249 }
14250 }
14251 }
14252 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14253}
14254
14255void Assembler::vacgt(
14256 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014257 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014258 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014259 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014260 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14261 if (dt.Is(F32)) {
14262 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14263 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14264 rm.Encode(5, 0));
14265 AdvanceIT();
14266 return;
14267 }
14268 }
14269 } else {
14270 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14271 if (dt.Is(F32)) {
14272 if (cond.Is(al)) {
14273 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14274 rm.Encode(5, 0));
14275 return;
14276 }
14277 }
14278 }
14279 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14280}
14281
14282void Assembler::vacle(
14283 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014284 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014285 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014286 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014287 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14288 if (dt.Is(F32)) {
14289 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14290 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14291 rm.Encode(5, 0));
14292 AdvanceIT();
14293 return;
14294 }
14295 }
14296 } else {
14297 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14298 if (dt.Is(F32)) {
14299 if (cond.Is(al)) {
14300 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14301 rm.Encode(5, 0));
14302 return;
14303 }
14304 }
14305 }
14306 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14307}
14308
14309void Assembler::vacle(
14310 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014311 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014312 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014313 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014314 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14315 if (dt.Is(F32)) {
14316 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14317 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14318 rm.Encode(5, 0));
14319 AdvanceIT();
14320 return;
14321 }
14322 }
14323 } else {
14324 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14325 if (dt.Is(F32)) {
14326 if (cond.Is(al)) {
14327 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14328 rm.Encode(5, 0));
14329 return;
14330 }
14331 }
14332 }
14333 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14334}
14335
14336void Assembler::vaclt(
14337 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014338 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014339 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014340 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014341 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14342 if (dt.Is(F32)) {
14343 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14344 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14345 rm.Encode(5, 0));
14346 AdvanceIT();
14347 return;
14348 }
14349 }
14350 } else {
14351 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14352 if (dt.Is(F32)) {
14353 if (cond.Is(al)) {
14354 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14355 rm.Encode(5, 0));
14356 return;
14357 }
14358 }
14359 }
14360 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14361}
14362
14363void Assembler::vaclt(
14364 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014365 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014366 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014367 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014368 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14369 if (dt.Is(F32)) {
14370 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14371 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14372 rm.Encode(5, 0));
14373 AdvanceIT();
14374 return;
14375 }
14376 }
14377 } else {
14378 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14379 if (dt.Is(F32)) {
14380 if (cond.Is(al)) {
14381 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14382 rm.Encode(5, 0));
14383 return;
14384 }
14385 }
14386 }
14387 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14388}
14389
14390void Assembler::vadd(
14391 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014392 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014393 CheckIT(cond);
14394 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014396 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14397 if (dt.Is(F32)) {
14398 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14399 EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14400 rm.Encode(5, 0));
14401 AdvanceIT();
14402 return;
14403 }
14404 }
14405 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
14406 if (dt.Is(F64)) {
14407 EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14408 rm.Encode(5, 0));
14409 AdvanceIT();
14410 return;
14411 }
14412 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14413 if (encoded_dt.IsValid()) {
14414 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14415 EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
14416 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14417 AdvanceIT();
14418 return;
14419 }
14420 }
14421 } else {
14422 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14423 if (dt.Is(F32)) {
14424 if (cond.Is(al)) {
14425 EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14426 rm.Encode(5, 0));
14427 return;
14428 }
14429 }
14430 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
14431 if (dt.Is(F64) && cond.IsNotNever()) {
14432 EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14433 rn.Encode(7, 16) | rm.Encode(5, 0));
14434 return;
14435 }
14436 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14437 if (encoded_dt.IsValid()) {
14438 if (cond.Is(al)) {
14439 EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
14440 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14441 return;
14442 }
14443 }
14444 }
14445 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14446}
14447
14448void Assembler::vadd(
14449 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014450 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014451 CheckIT(cond);
14452 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014453 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014454 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14455 if (dt.Is(F32)) {
14456 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14457 EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14458 rm.Encode(5, 0));
14459 AdvanceIT();
14460 return;
14461 }
14462 }
14463 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14464 if (encoded_dt.IsValid()) {
14465 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14466 EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
14467 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14468 AdvanceIT();
14469 return;
14470 }
14471 }
14472 } else {
14473 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14474 if (dt.Is(F32)) {
14475 if (cond.Is(al)) {
14476 EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14477 rm.Encode(5, 0));
14478 return;
14479 }
14480 }
14481 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14482 if (encoded_dt.IsValid()) {
14483 if (cond.Is(al)) {
14484 EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
14485 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14486 return;
14487 }
14488 }
14489 }
14490 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14491}
14492
14493void Assembler::vadd(
14494 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014495 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014496 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014497 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014498 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
14499 if (dt.Is(F32)) {
14500 EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14501 rm.Encode(5, 0));
14502 AdvanceIT();
14503 return;
14504 }
14505 } else {
14506 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
14507 if (dt.Is(F32) && cond.IsNotNever()) {
14508 EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14509 rn.Encode(7, 16) | rm.Encode(5, 0));
14510 return;
14511 }
14512 }
14513 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14514}
14515
14516void Assembler::vaddhn(
14517 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014518 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014519 CheckIT(cond);
14520 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014521 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014522 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
14523 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14524 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14525 EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
14526 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14527 AdvanceIT();
14528 return;
14529 }
14530 }
14531 } else {
14532 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
14533 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14534 if (cond.Is(al)) {
14535 EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
14536 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14537 return;
14538 }
14539 }
14540 }
14541 Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
14542}
14543
14544void Assembler::vaddl(
14545 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014546 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014547 CheckIT(cond);
14548 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014549 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014550 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14551 if (encoded_dt.IsValid()) {
14552 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14553 EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14554 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14555 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14556 AdvanceIT();
14557 return;
14558 }
14559 }
14560 } else {
14561 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14562 if (encoded_dt.IsValid()) {
14563 if (cond.Is(al)) {
14564 EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14565 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14566 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14567 return;
14568 }
14569 }
14570 }
14571 Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
14572}
14573
14574void Assembler::vaddw(
14575 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014576 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014577 CheckIT(cond);
14578 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014579 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014580 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
14581 if (encoded_dt.IsValid()) {
14582 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14583 EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14584 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14585 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14586 AdvanceIT();
14587 return;
14588 }
14589 }
14590 } else {
14591 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
14592 if (encoded_dt.IsValid()) {
14593 if (cond.Is(al)) {
14594 EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14595 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14596 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14597 return;
14598 }
14599 }
14600 }
14601 Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
14602}
14603
14604void Assembler::vand(Condition cond,
14605 DataType dt,
14606 DRegister rd,
14607 DRegister rn,
14608 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014609 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014610 CheckIT(cond);
14611 if (operand.IsImmediate()) {
14612 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014613 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014614 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14615 if (encoded_dt.IsValid() && rd.Is(rn)) {
14616 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14617 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14618 rd.Encode(22, 12) |
14619 (encoded_dt.GetEncodedImmediate() & 0xf) |
14620 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14621 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14622 AdvanceIT();
14623 return;
14624 }
14625 }
14626 } else {
14627 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14628 if (encoded_dt.IsValid() && rd.Is(rn)) {
14629 if (cond.Is(al)) {
14630 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14631 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14632 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14633 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14634 return;
14635 }
14636 }
14637 }
14638 }
14639 if (operand.IsRegister()) {
14640 DRegister rm = operand.GetRegister();
14641 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014642 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014643 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14644 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14645 EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14646 rm.Encode(5, 0));
14647 AdvanceIT();
14648 return;
14649 }
14650 } else {
14651 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14652 if (cond.Is(al)) {
14653 EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14654 rm.Encode(5, 0));
14655 return;
14656 }
14657 }
14658 }
14659 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14660}
14661
14662void Assembler::vand(Condition cond,
14663 DataType dt,
14664 QRegister rd,
14665 QRegister rn,
14666 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014667 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014668 CheckIT(cond);
14669 if (operand.IsImmediate()) {
14670 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014671 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014672 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14673 if (encoded_dt.IsValid() && rd.Is(rn)) {
14674 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14675 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14676 rd.Encode(22, 12) |
14677 (encoded_dt.GetEncodedImmediate() & 0xf) |
14678 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14679 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14680 AdvanceIT();
14681 return;
14682 }
14683 }
14684 } else {
14685 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14686 if (encoded_dt.IsValid() && rd.Is(rn)) {
14687 if (cond.Is(al)) {
14688 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14689 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14690 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14691 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14692 return;
14693 }
14694 }
14695 }
14696 }
14697 if (operand.IsRegister()) {
14698 QRegister rm = operand.GetRegister();
14699 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014700 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014701 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14702 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14703 EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14704 rm.Encode(5, 0));
14705 AdvanceIT();
14706 return;
14707 }
14708 } else {
14709 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14710 if (cond.Is(al)) {
14711 EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14712 rm.Encode(5, 0));
14713 return;
14714 }
14715 }
14716 }
14717 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14718}
14719
14720void Assembler::vbic(Condition cond,
14721 DataType dt,
14722 DRegister rd,
14723 DRegister rn,
14724 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014725 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014726 CheckIT(cond);
14727 if (operand.IsImmediate()) {
14728 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014729 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014730 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14731 if (encoded_dt.IsValid() && rd.Is(rn)) {
14732 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14733 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14734 rd.Encode(22, 12) |
14735 (encoded_dt.GetEncodedImmediate() & 0xf) |
14736 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14737 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14738 AdvanceIT();
14739 return;
14740 }
14741 }
14742 } else {
14743 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14744 if (encoded_dt.IsValid() && rd.Is(rn)) {
14745 if (cond.Is(al)) {
14746 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14747 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14748 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14749 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14750 return;
14751 }
14752 }
14753 }
14754 }
14755 if (operand.IsRegister()) {
14756 DRegister rm = operand.GetRegister();
14757 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014758 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014759 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14760 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14761 EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14762 rm.Encode(5, 0));
14763 AdvanceIT();
14764 return;
14765 }
14766 } else {
14767 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14768 if (cond.Is(al)) {
14769 EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14770 rm.Encode(5, 0));
14771 return;
14772 }
14773 }
14774 }
14775 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14776}
14777
14778void Assembler::vbic(Condition cond,
14779 DataType dt,
14780 QRegister rd,
14781 QRegister rn,
14782 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014783 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014784 CheckIT(cond);
14785 if (operand.IsImmediate()) {
14786 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014787 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014788 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14789 if (encoded_dt.IsValid() && rd.Is(rn)) {
14790 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14791 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14792 rd.Encode(22, 12) |
14793 (encoded_dt.GetEncodedImmediate() & 0xf) |
14794 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14795 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14796 AdvanceIT();
14797 return;
14798 }
14799 }
14800 } else {
14801 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14802 if (encoded_dt.IsValid() && rd.Is(rn)) {
14803 if (cond.Is(al)) {
14804 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14805 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14806 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14807 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14808 return;
14809 }
14810 }
14811 }
14812 }
14813 if (operand.IsRegister()) {
14814 QRegister rm = operand.GetRegister();
14815 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014816 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014817 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14818 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14819 EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14820 rm.Encode(5, 0));
14821 AdvanceIT();
14822 return;
14823 }
14824 } else {
14825 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14826 if (cond.Is(al)) {
14827 EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14828 rm.Encode(5, 0));
14829 return;
14830 }
14831 }
14832 }
14833 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14834}
14835
14836void Assembler::vbif(
14837 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014838 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014839 CheckIT(cond);
14840 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014841 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014842 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14843 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14844 EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14845 rm.Encode(5, 0));
14846 AdvanceIT();
14847 return;
14848 }
14849 } else {
14850 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14851 if (cond.Is(al)) {
14852 EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14853 rm.Encode(5, 0));
14854 return;
14855 }
14856 }
14857 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14858}
14859
14860void Assembler::vbif(
14861 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014863 CheckIT(cond);
14864 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014865 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014866 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14867 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14868 EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14869 rm.Encode(5, 0));
14870 AdvanceIT();
14871 return;
14872 }
14873 } else {
14874 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14875 if (cond.Is(al)) {
14876 EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14877 rm.Encode(5, 0));
14878 return;
14879 }
14880 }
14881 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14882}
14883
14884void Assembler::vbit(
14885 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014886 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014887 CheckIT(cond);
14888 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014889 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014890 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14891 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14892 EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14893 rm.Encode(5, 0));
14894 AdvanceIT();
14895 return;
14896 }
14897 } else {
14898 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14899 if (cond.Is(al)) {
14900 EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14901 rm.Encode(5, 0));
14902 return;
14903 }
14904 }
14905 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14906}
14907
14908void Assembler::vbit(
14909 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014910 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014911 CheckIT(cond);
14912 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014913 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014914 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14915 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14916 EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14917 rm.Encode(5, 0));
14918 AdvanceIT();
14919 return;
14920 }
14921 } else {
14922 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14923 if (cond.Is(al)) {
14924 EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14925 rm.Encode(5, 0));
14926 return;
14927 }
14928 }
14929 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14930}
14931
14932void Assembler::vbsl(
14933 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014934 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014935 CheckIT(cond);
14936 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014937 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014938 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14939 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14940 EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14941 rm.Encode(5, 0));
14942 AdvanceIT();
14943 return;
14944 }
14945 } else {
14946 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14947 if (cond.Is(al)) {
14948 EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14949 rm.Encode(5, 0));
14950 return;
14951 }
14952 }
14953 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14954}
14955
14956void Assembler::vbsl(
14957 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014958 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014959 CheckIT(cond);
14960 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014961 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014962 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14963 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14964 EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14965 rm.Encode(5, 0));
14966 AdvanceIT();
14967 return;
14968 }
14969 } else {
14970 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14971 if (cond.Is(al)) {
14972 EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14973 rm.Encode(5, 0));
14974 return;
14975 }
14976 }
14977 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14978}
14979
14980void Assembler::vceq(Condition cond,
14981 DataType dt,
14982 DRegister rd,
14983 DRegister rm,
14984 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014985 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014986 CheckIT(cond);
14987 if (operand.IsImmediate()) {
14988 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14989 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14990 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014991 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014992 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14993 if (encoded_dt.IsValid() && (imm == 0)) {
14994 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14995 EmitT32_32(0xffb10100U |
14996 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14997 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14998 rd.Encode(22, 12) | rm.Encode(5, 0));
14999 AdvanceIT();
15000 return;
15001 }
15002 }
15003 } else {
15004 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15005 if (encoded_dt.IsValid() && (imm == 0)) {
15006 if (cond.Is(al)) {
15007 EmitA32(0xf3b10100U |
15008 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15009 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15010 rd.Encode(22, 12) | rm.Encode(5, 0));
15011 return;
15012 }
15013 }
15014 }
15015 }
15016 }
15017 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15018}
15019
15020void Assembler::vceq(Condition cond,
15021 DataType dt,
15022 QRegister rd,
15023 QRegister rm,
15024 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015025 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015026 CheckIT(cond);
15027 if (operand.IsImmediate()) {
15028 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15029 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15030 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015031 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015032 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15033 if (encoded_dt.IsValid() && (imm == 0)) {
15034 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15035 EmitT32_32(0xffb10140U |
15036 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15037 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15038 rd.Encode(22, 12) | rm.Encode(5, 0));
15039 AdvanceIT();
15040 return;
15041 }
15042 }
15043 } else {
15044 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15045 if (encoded_dt.IsValid() && (imm == 0)) {
15046 if (cond.Is(al)) {
15047 EmitA32(0xf3b10140U |
15048 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15049 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15050 rd.Encode(22, 12) | rm.Encode(5, 0));
15051 return;
15052 }
15053 }
15054 }
15055 }
15056 }
15057 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15058}
15059
15060void Assembler::vceq(
15061 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015062 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015063 CheckIT(cond);
15064 Dt_size_4 encoded_dt(dt);
15065 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015066 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015067 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15068 if (encoded_dt.IsValid()) {
15069 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15070 EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
15071 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15072 AdvanceIT();
15073 return;
15074 }
15075 }
15076 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
15077 if (encoded_dt_2.IsValid()) {
15078 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15079 EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15080 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15081 AdvanceIT();
15082 return;
15083 }
15084 }
15085 } else {
15086 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15087 if (encoded_dt.IsValid()) {
15088 if (cond.Is(al)) {
15089 EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
15090 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15091 return;
15092 }
15093 }
15094 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
15095 if (encoded_dt_2.IsValid()) {
15096 if (cond.Is(al)) {
15097 EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15098 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15099 return;
15100 }
15101 }
15102 }
15103 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15104}
15105
15106void Assembler::vceq(
15107 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015108 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015109 CheckIT(cond);
15110 Dt_size_4 encoded_dt(dt);
15111 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015112 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015113 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15114 if (encoded_dt.IsValid()) {
15115 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15116 EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
15117 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15118 AdvanceIT();
15119 return;
15120 }
15121 }
15122 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
15123 if (encoded_dt_2.IsValid()) {
15124 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15125 EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15126 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15127 AdvanceIT();
15128 return;
15129 }
15130 }
15131 } else {
15132 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15133 if (encoded_dt.IsValid()) {
15134 if (cond.Is(al)) {
15135 EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
15136 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15137 return;
15138 }
15139 }
15140 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
15141 if (encoded_dt_2.IsValid()) {
15142 if (cond.Is(al)) {
15143 EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15144 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15145 return;
15146 }
15147 }
15148 }
15149 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15150}
15151
15152void Assembler::vcge(Condition cond,
15153 DataType dt,
15154 DRegister rd,
15155 DRegister rm,
15156 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015157 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015158 CheckIT(cond);
15159 if (operand.IsImmediate()) {
15160 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15161 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15162 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015163 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015164 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15165 if (encoded_dt.IsValid() && (imm == 0)) {
15166 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15167 EmitT32_32(0xffb10080U |
15168 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15169 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15170 rd.Encode(22, 12) | rm.Encode(5, 0));
15171 AdvanceIT();
15172 return;
15173 }
15174 }
15175 } else {
15176 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15177 if (encoded_dt.IsValid() && (imm == 0)) {
15178 if (cond.Is(al)) {
15179 EmitA32(0xf3b10080U |
15180 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15181 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15182 rd.Encode(22, 12) | rm.Encode(5, 0));
15183 return;
15184 }
15185 }
15186 }
15187 }
15188 }
15189 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15190}
15191
15192void Assembler::vcge(Condition cond,
15193 DataType dt,
15194 QRegister rd,
15195 QRegister rm,
15196 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015197 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015198 CheckIT(cond);
15199 if (operand.IsImmediate()) {
15200 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15201 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15202 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015203 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015204 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15205 if (encoded_dt.IsValid() && (imm == 0)) {
15206 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15207 EmitT32_32(0xffb100c0U |
15208 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15209 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15210 rd.Encode(22, 12) | rm.Encode(5, 0));
15211 AdvanceIT();
15212 return;
15213 }
15214 }
15215 } else {
15216 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15217 if (encoded_dt.IsValid() && (imm == 0)) {
15218 if (cond.Is(al)) {
15219 EmitA32(0xf3b100c0U |
15220 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15221 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15222 rd.Encode(22, 12) | rm.Encode(5, 0));
15223 return;
15224 }
15225 }
15226 }
15227 }
15228 }
15229 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15230}
15231
15232void Assembler::vcge(
15233 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015234 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015235 CheckIT(cond);
15236 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015237 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015238 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15239 if (encoded_dt.IsValid()) {
15240 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15241 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15242 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015243 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015244 AdvanceIT();
15245 return;
15246 }
15247 }
15248 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15249 if (dt.Is(F32)) {
15250 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15251 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15252 rm.Encode(5, 0));
15253 AdvanceIT();
15254 return;
15255 }
15256 }
15257 } else {
15258 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15259 if (encoded_dt.IsValid()) {
15260 if (cond.Is(al)) {
15261 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15262 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15263 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15264 return;
15265 }
15266 }
15267 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15268 if (dt.Is(F32)) {
15269 if (cond.Is(al)) {
15270 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15271 rm.Encode(5, 0));
15272 return;
15273 }
15274 }
15275 }
15276 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15277}
15278
15279void Assembler::vcge(
15280 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015281 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015282 CheckIT(cond);
15283 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015285 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15286 if (encoded_dt.IsValid()) {
15287 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15288 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15289 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015290 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015291 AdvanceIT();
15292 return;
15293 }
15294 }
15295 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15296 if (dt.Is(F32)) {
15297 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15298 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15299 rm.Encode(5, 0));
15300 AdvanceIT();
15301 return;
15302 }
15303 }
15304 } else {
15305 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15306 if (encoded_dt.IsValid()) {
15307 if (cond.Is(al)) {
15308 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15309 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15310 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15311 return;
15312 }
15313 }
15314 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15315 if (dt.Is(F32)) {
15316 if (cond.Is(al)) {
15317 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15318 rm.Encode(5, 0));
15319 return;
15320 }
15321 }
15322 }
15323 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15324}
15325
15326void Assembler::vcgt(Condition cond,
15327 DataType dt,
15328 DRegister rd,
15329 DRegister rm,
15330 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015331 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015332 CheckIT(cond);
15333 if (operand.IsImmediate()) {
15334 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15335 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15336 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015337 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015338 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15339 if (encoded_dt.IsValid() && (imm == 0)) {
15340 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15341 EmitT32_32(0xffb10000U |
15342 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15343 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15344 rd.Encode(22, 12) | rm.Encode(5, 0));
15345 AdvanceIT();
15346 return;
15347 }
15348 }
15349 } else {
15350 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15351 if (encoded_dt.IsValid() && (imm == 0)) {
15352 if (cond.Is(al)) {
15353 EmitA32(0xf3b10000U |
15354 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15355 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15356 rd.Encode(22, 12) | rm.Encode(5, 0));
15357 return;
15358 }
15359 }
15360 }
15361 }
15362 }
15363 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15364}
15365
15366void Assembler::vcgt(Condition cond,
15367 DataType dt,
15368 QRegister rd,
15369 QRegister rm,
15370 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015371 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015372 CheckIT(cond);
15373 if (operand.IsImmediate()) {
15374 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15375 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15376 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015377 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015378 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15379 if (encoded_dt.IsValid() && (imm == 0)) {
15380 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15381 EmitT32_32(0xffb10040U |
15382 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15383 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15384 rd.Encode(22, 12) | rm.Encode(5, 0));
15385 AdvanceIT();
15386 return;
15387 }
15388 }
15389 } else {
15390 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15391 if (encoded_dt.IsValid() && (imm == 0)) {
15392 if (cond.Is(al)) {
15393 EmitA32(0xf3b10040U |
15394 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15395 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15396 rd.Encode(22, 12) | rm.Encode(5, 0));
15397 return;
15398 }
15399 }
15400 }
15401 }
15402 }
15403 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15404}
15405
15406void Assembler::vcgt(
15407 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015408 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015409 CheckIT(cond);
15410 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015411 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015412 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15413 if (encoded_dt.IsValid()) {
15414 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15415 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15416 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015417 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015418 AdvanceIT();
15419 return;
15420 }
15421 }
15422 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15423 if (dt.Is(F32)) {
15424 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15425 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15426 rm.Encode(5, 0));
15427 AdvanceIT();
15428 return;
15429 }
15430 }
15431 } else {
15432 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15433 if (encoded_dt.IsValid()) {
15434 if (cond.Is(al)) {
15435 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15436 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15437 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15438 return;
15439 }
15440 }
15441 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15442 if (dt.Is(F32)) {
15443 if (cond.Is(al)) {
15444 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15445 rm.Encode(5, 0));
15446 return;
15447 }
15448 }
15449 }
15450 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15451}
15452
15453void Assembler::vcgt(
15454 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015455 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015456 CheckIT(cond);
15457 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015458 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015459 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15460 if (encoded_dt.IsValid()) {
15461 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15462 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15463 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015464 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015465 AdvanceIT();
15466 return;
15467 }
15468 }
15469 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15470 if (dt.Is(F32)) {
15471 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15472 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15473 rm.Encode(5, 0));
15474 AdvanceIT();
15475 return;
15476 }
15477 }
15478 } else {
15479 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15480 if (encoded_dt.IsValid()) {
15481 if (cond.Is(al)) {
15482 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15483 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15484 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15485 return;
15486 }
15487 }
15488 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15489 if (dt.Is(F32)) {
15490 if (cond.Is(al)) {
15491 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15492 rm.Encode(5, 0));
15493 return;
15494 }
15495 }
15496 }
15497 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15498}
15499
15500void Assembler::vcle(Condition cond,
15501 DataType dt,
15502 DRegister rd,
15503 DRegister rm,
15504 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015505 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015506 CheckIT(cond);
15507 if (operand.IsImmediate()) {
15508 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15509 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15510 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015511 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015512 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15513 if (encoded_dt.IsValid() && (imm == 0)) {
15514 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15515 EmitT32_32(0xffb10180U |
15516 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15517 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15518 rd.Encode(22, 12) | rm.Encode(5, 0));
15519 AdvanceIT();
15520 return;
15521 }
15522 }
15523 } else {
15524 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15525 if (encoded_dt.IsValid() && (imm == 0)) {
15526 if (cond.Is(al)) {
15527 EmitA32(0xf3b10180U |
15528 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15529 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15530 rd.Encode(22, 12) | rm.Encode(5, 0));
15531 return;
15532 }
15533 }
15534 }
15535 }
15536 }
15537 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15538}
15539
15540void Assembler::vcle(Condition cond,
15541 DataType dt,
15542 QRegister rd,
15543 QRegister rm,
15544 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015545 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015546 CheckIT(cond);
15547 if (operand.IsImmediate()) {
15548 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15549 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15550 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015551 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015552 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15553 if (encoded_dt.IsValid() && (imm == 0)) {
15554 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15555 EmitT32_32(0xffb101c0U |
15556 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15557 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15558 rd.Encode(22, 12) | rm.Encode(5, 0));
15559 AdvanceIT();
15560 return;
15561 }
15562 }
15563 } else {
15564 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15565 if (encoded_dt.IsValid() && (imm == 0)) {
15566 if (cond.Is(al)) {
15567 EmitA32(0xf3b101c0U |
15568 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15569 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15570 rd.Encode(22, 12) | rm.Encode(5, 0));
15571 return;
15572 }
15573 }
15574 }
15575 }
15576 }
15577 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15578}
15579
15580void Assembler::vcle(
15581 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015582 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015583 CheckIT(cond);
15584 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015585 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015586 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15587 if (encoded_dt.IsValid()) {
15588 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15589 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15590 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015591 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015592 AdvanceIT();
15593 return;
15594 }
15595 }
15596 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15597 if (dt.Is(F32)) {
15598 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015599 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15600 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015601 AdvanceIT();
15602 return;
15603 }
15604 }
15605 } else {
15606 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15607 if (encoded_dt.IsValid()) {
15608 if (cond.Is(al)) {
15609 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15610 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015611 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015612 return;
15613 }
15614 }
15615 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15616 if (dt.Is(F32)) {
15617 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015618 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15619 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015620 return;
15621 }
15622 }
15623 }
15624 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15625}
15626
15627void Assembler::vcle(
15628 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015629 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015630 CheckIT(cond);
15631 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015632 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015633 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15634 if (encoded_dt.IsValid()) {
15635 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15636 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15637 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015638 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015639 AdvanceIT();
15640 return;
15641 }
15642 }
15643 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15644 if (dt.Is(F32)) {
15645 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015646 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15647 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015648 AdvanceIT();
15649 return;
15650 }
15651 }
15652 } else {
15653 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15654 if (encoded_dt.IsValid()) {
15655 if (cond.Is(al)) {
15656 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15657 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015658 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015659 return;
15660 }
15661 }
15662 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15663 if (dt.Is(F32)) {
15664 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015665 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15666 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015667 return;
15668 }
15669 }
15670 }
15671 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15672}
15673
15674void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015675 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015676 CheckIT(cond);
15677 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015678 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015679 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15680 if (encoded_dt.IsValid()) {
15681 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15682 EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
15683 rd.Encode(22, 12) | rm.Encode(5, 0));
15684 AdvanceIT();
15685 return;
15686 }
15687 }
15688 } else {
15689 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15690 if (encoded_dt.IsValid()) {
15691 if (cond.Is(al)) {
15692 EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
15693 rd.Encode(22, 12) | rm.Encode(5, 0));
15694 return;
15695 }
15696 }
15697 }
15698 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15699}
15700
15701void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015702 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015703 CheckIT(cond);
15704 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015705 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015706 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15707 if (encoded_dt.IsValid()) {
15708 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15709 EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
15710 rd.Encode(22, 12) | rm.Encode(5, 0));
15711 AdvanceIT();
15712 return;
15713 }
15714 }
15715 } else {
15716 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15717 if (encoded_dt.IsValid()) {
15718 if (cond.Is(al)) {
15719 EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
15720 rd.Encode(22, 12) | rm.Encode(5, 0));
15721 return;
15722 }
15723 }
15724 }
15725 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15726}
15727
15728void Assembler::vclt(Condition cond,
15729 DataType dt,
15730 DRegister rd,
15731 DRegister rm,
15732 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015733 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015734 CheckIT(cond);
15735 if (operand.IsImmediate()) {
15736 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15737 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15738 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015739 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015740 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15741 if (encoded_dt.IsValid() && (imm == 0)) {
15742 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15743 EmitT32_32(0xffb10200U |
15744 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15745 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15746 rd.Encode(22, 12) | rm.Encode(5, 0));
15747 AdvanceIT();
15748 return;
15749 }
15750 }
15751 } else {
15752 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15753 if (encoded_dt.IsValid() && (imm == 0)) {
15754 if (cond.Is(al)) {
15755 EmitA32(0xf3b10200U |
15756 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15757 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15758 rd.Encode(22, 12) | rm.Encode(5, 0));
15759 return;
15760 }
15761 }
15762 }
15763 }
15764 }
15765 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15766}
15767
15768void Assembler::vclt(Condition cond,
15769 DataType dt,
15770 QRegister rd,
15771 QRegister rm,
15772 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015773 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015774 CheckIT(cond);
15775 if (operand.IsImmediate()) {
15776 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15777 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15778 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015779 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015780 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15781 if (encoded_dt.IsValid() && (imm == 0)) {
15782 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15783 EmitT32_32(0xffb10240U |
15784 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15785 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15786 rd.Encode(22, 12) | rm.Encode(5, 0));
15787 AdvanceIT();
15788 return;
15789 }
15790 }
15791 } else {
15792 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15793 if (encoded_dt.IsValid() && (imm == 0)) {
15794 if (cond.Is(al)) {
15795 EmitA32(0xf3b10240U |
15796 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15797 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15798 rd.Encode(22, 12) | rm.Encode(5, 0));
15799 return;
15800 }
15801 }
15802 }
15803 }
15804 }
15805 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15806}
15807
15808void Assembler::vclt(
15809 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015810 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015811 CheckIT(cond);
15812 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015813 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015814 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15815 if (encoded_dt.IsValid()) {
15816 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15817 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15818 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015819 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015820 AdvanceIT();
15821 return;
15822 }
15823 }
15824 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15825 if (dt.Is(F32)) {
15826 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015827 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15828 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015829 AdvanceIT();
15830 return;
15831 }
15832 }
15833 } else {
15834 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15835 if (encoded_dt.IsValid()) {
15836 if (cond.Is(al)) {
15837 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15838 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015839 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015840 return;
15841 }
15842 }
15843 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15844 if (dt.Is(F32)) {
15845 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015846 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15847 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015848 return;
15849 }
15850 }
15851 }
15852 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15853}
15854
15855void Assembler::vclt(
15856 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015857 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015858 CheckIT(cond);
15859 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015860 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015861 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15862 if (encoded_dt.IsValid()) {
15863 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15864 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15865 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015866 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015867 AdvanceIT();
15868 return;
15869 }
15870 }
15871 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15872 if (dt.Is(F32)) {
15873 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015874 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15875 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015876 AdvanceIT();
15877 return;
15878 }
15879 }
15880 } else {
15881 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15882 if (encoded_dt.IsValid()) {
15883 if (cond.Is(al)) {
15884 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15885 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015886 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015887 return;
15888 }
15889 }
15890 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15891 if (dt.Is(F32)) {
15892 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015893 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15894 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015895 return;
15896 }
15897 }
15898 }
15899 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15900}
15901
15902void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015903 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015904 CheckIT(cond);
15905 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015906 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015907 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15908 if (encoded_dt.IsValid()) {
15909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15910 EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
15911 rd.Encode(22, 12) | rm.Encode(5, 0));
15912 AdvanceIT();
15913 return;
15914 }
15915 }
15916 } else {
15917 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15918 if (encoded_dt.IsValid()) {
15919 if (cond.Is(al)) {
15920 EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
15921 rd.Encode(22, 12) | rm.Encode(5, 0));
15922 return;
15923 }
15924 }
15925 }
15926 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15927}
15928
15929void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015930 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015931 CheckIT(cond);
15932 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015933 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015934 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15935 if (encoded_dt.IsValid()) {
15936 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15937 EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
15938 rd.Encode(22, 12) | rm.Encode(5, 0));
15939 AdvanceIT();
15940 return;
15941 }
15942 }
15943 } else {
15944 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15945 if (encoded_dt.IsValid()) {
15946 if (cond.Is(al)) {
15947 EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
15948 rd.Encode(22, 12) | rm.Encode(5, 0));
15949 return;
15950 }
15951 }
15952 }
15953 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15954}
15955
Vincent Belliard07f9e742017-04-21 13:10:07 -070015956void Assembler::vcmp(Condition cond,
15957 DataType dt,
15958 SRegister rd,
15959 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015960 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015961 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070015962 if (operand.IsRegister()) {
15963 SRegister rm = operand.GetRegister();
15964 if (IsUsingT32()) {
15965 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
15966 if (dt.Is(F32)) {
15967 EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15968 AdvanceIT();
15969 return;
15970 }
15971 } else {
15972 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
15973 if (dt.Is(F32) && cond.IsNotNever()) {
15974 EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15975 rm.Encode(5, 0));
15976 return;
15977 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010015978 }
15979 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070015980 if (operand.IsImmediate()) {
15981 if (IsUsingT32()) {
15982 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
15983 if (dt.Is(F32) && (operand.IsFloatZero())) {
15984 EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
15985 AdvanceIT();
15986 return;
15987 }
15988 } else {
15989 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
15990 if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
15991 EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
15992 return;
15993 }
15994 }
15995 }
15996 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010015997}
15998
Vincent Belliard07f9e742017-04-21 13:10:07 -070015999void Assembler::vcmp(Condition cond,
16000 DataType dt,
16001 DRegister rd,
16002 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016003 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016004 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016005 if (operand.IsRegister()) {
16006 DRegister rm = operand.GetRegister();
16007 if (IsUsingT32()) {
16008 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16009 if (dt.Is(F64)) {
16010 EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16011 AdvanceIT();
16012 return;
16013 }
16014 } else {
16015 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16016 if (dt.Is(F64) && cond.IsNotNever()) {
16017 EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16018 rm.Encode(5, 0));
16019 return;
16020 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016021 }
16022 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016023 if (operand.IsImmediate()) {
16024 if (IsUsingT32()) {
16025 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16026 if (dt.Is(F64) && (operand.IsFloatZero())) {
16027 EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
16028 AdvanceIT();
16029 return;
16030 }
16031 } else {
16032 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16033 if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16034 EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16035 return;
16036 }
16037 }
16038 }
16039 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016040}
16041
Vincent Belliard07f9e742017-04-21 13:10:07 -070016042void Assembler::vcmpe(Condition cond,
16043 DataType dt,
16044 SRegister rd,
16045 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016046 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016047 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016048 if (operand.IsRegister()) {
16049 SRegister rm = operand.GetRegister();
16050 if (IsUsingT32()) {
16051 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16052 if (dt.Is(F32)) {
16053 EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16054 AdvanceIT();
16055 return;
16056 }
16057 } else {
16058 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16059 if (dt.Is(F32) && cond.IsNotNever()) {
16060 EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16061 rm.Encode(5, 0));
16062 return;
16063 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016064 }
16065 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016066 if (operand.IsImmediate()) {
16067 if (IsUsingT32()) {
16068 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16069 if (dt.Is(F32) && (operand.IsFloatZero())) {
16070 EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
16071 AdvanceIT();
16072 return;
16073 }
16074 } else {
16075 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16076 if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16077 EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16078 return;
16079 }
16080 }
16081 }
16082 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016083}
16084
Vincent Belliard07f9e742017-04-21 13:10:07 -070016085void Assembler::vcmpe(Condition cond,
16086 DataType dt,
16087 DRegister rd,
16088 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016089 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016090 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016091 if (operand.IsRegister()) {
16092 DRegister rm = operand.GetRegister();
16093 if (IsUsingT32()) {
16094 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16095 if (dt.Is(F64)) {
16096 EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16097 AdvanceIT();
16098 return;
16099 }
16100 } else {
16101 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16102 if (dt.Is(F64) && cond.IsNotNever()) {
16103 EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16104 rm.Encode(5, 0));
16105 return;
16106 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016107 }
16108 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016109 if (operand.IsImmediate()) {
16110 if (IsUsingT32()) {
16111 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16112 if (dt.Is(F64) && (operand.IsFloatZero())) {
16113 EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
16114 AdvanceIT();
16115 return;
16116 }
16117 } else {
16118 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16119 if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16120 EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16121 return;
16122 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016123 }
16124 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016125 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016126}
16127
16128void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016129 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016130 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016131 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016132 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
16133 if (dt.Is(Untyped8)) {
16134 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16135 EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16136 AdvanceIT();
16137 return;
16138 }
16139 }
16140 } else {
16141 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
16142 if (dt.Is(Untyped8)) {
16143 if (cond.Is(al)) {
16144 EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16145 return;
16146 }
16147 }
16148 }
16149 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16150}
16151
16152void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016153 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016154 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016155 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016156 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
16157 if (dt.Is(Untyped8)) {
16158 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16159 EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16160 AdvanceIT();
16161 return;
16162 }
16163 }
16164 } else {
16165 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
16166 if (dt.Is(Untyped8)) {
16167 if (cond.Is(al)) {
16168 EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16169 return;
16170 }
16171 }
16172 }
16173 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16174}
16175
16176void Assembler::vcvt(
16177 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016178 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016179 CheckIT(cond);
16180 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016181 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016182 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
16183 if (dt1.Is(F64) && dt2.Is(F32)) {
16184 EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16185 AdvanceIT();
16186 return;
16187 }
16188 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
16189 if (dt1.Is(F64) && encoded_dt.IsValid()) {
16190 EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
16191 rd.Encode(22, 12) | rm.Encode(5, 0));
16192 AdvanceIT();
16193 return;
16194 }
16195 } else {
16196 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
16197 if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
16198 EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16199 rm.Encode(5, 0));
16200 return;
16201 }
16202 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
16203 if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
16204 EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
16205 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16206 rm.Encode(5, 0));
16207 return;
16208 }
16209 }
16210 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16211}
16212
16213void Assembler::vcvt(
16214 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016215 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016216 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016217 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016218 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
16219 if (dt1.Is(F32) && dt2.Is(F64)) {
16220 EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16221 AdvanceIT();
16222 return;
16223 }
16224 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16225 if (dt1.Is(U32) && dt2.Is(F64)) {
16226 EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16227 AdvanceIT();
16228 return;
16229 }
16230 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16231 if (dt1.Is(S32) && dt2.Is(F64)) {
16232 EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16233 AdvanceIT();
16234 return;
16235 }
16236 } else {
16237 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
16238 if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
16239 EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16240 rm.Encode(5, 0));
16241 return;
16242 }
16243 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16244 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16245 EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16246 rm.Encode(5, 0));
16247 return;
16248 }
16249 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16250 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16251 EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16252 rm.Encode(5, 0));
16253 return;
16254 }
16255 }
16256 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16257}
16258
16259void Assembler::vcvt(Condition cond,
16260 DataType dt1,
16261 DataType dt2,
16262 DRegister rd,
16263 DRegister rm,
16264 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016265 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016266 CheckIT(cond);
16267 Dt_op_U_1 encoded_dt(dt1, dt2);
16268 Dt_U_sx_1 encoded_dt_2(dt2);
16269 Dt_U_sx_1 encoded_dt_3(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016270 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016271 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
16272 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16273 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16274 uint32_t fbits_ = 64 - fbits;
16275 EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16276 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16277 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16278 AdvanceIT();
16279 return;
16280 }
16281 }
16282 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
16283 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16284 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16285 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16286 unsigned offset = 32;
16287 if (dt2.Is(S16) || dt2.Is(U16)) {
16288 offset = 16;
16289 }
16290 uint32_t fbits_ = offset - fbits;
16291 EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16292 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16293 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16294 ((fbits_ & 0x1e) >> 1));
16295 AdvanceIT();
16296 return;
16297 }
16298 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
16299 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16300 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16301 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16302 unsigned offset = 32;
16303 if (dt1.Is(S16) || dt1.Is(U16)) {
16304 offset = 16;
16305 }
16306 uint32_t fbits_ = offset - fbits;
16307 EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16308 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16309 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16310 ((fbits_ & 0x1e) >> 1));
16311 AdvanceIT();
16312 return;
16313 }
16314 } else {
16315 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
16316 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16317 if (cond.Is(al)) {
16318 uint32_t fbits_ = 64 - fbits;
16319 EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16320 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16321 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16322 return;
16323 }
16324 }
16325 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
16326 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16327 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16328 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16329 cond.IsNotNever()) {
16330 unsigned offset = 32;
16331 if (dt2.Is(S16) || dt2.Is(U16)) {
16332 offset = 16;
16333 }
16334 uint32_t fbits_ = offset - fbits;
16335 EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
16336 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16337 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16338 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16339 ((fbits_ & 0x1e) >> 1));
16340 return;
16341 }
16342 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
16343 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16344 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16345 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16346 cond.IsNotNever()) {
16347 unsigned offset = 32;
16348 if (dt1.Is(S16) || dt1.Is(U16)) {
16349 offset = 16;
16350 }
16351 uint32_t fbits_ = offset - fbits;
16352 EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
16353 ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16354 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16355 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16356 ((fbits_ & 0x1e) >> 1));
16357 return;
16358 }
16359 }
16360 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16361}
16362
16363void Assembler::vcvt(Condition cond,
16364 DataType dt1,
16365 DataType dt2,
16366 QRegister rd,
16367 QRegister rm,
16368 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016369 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016370 CheckIT(cond);
16371 Dt_op_U_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016372 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016373 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
16374 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16375 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16376 uint32_t fbits_ = 64 - fbits;
16377 EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16378 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16379 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16380 AdvanceIT();
16381 return;
16382 }
16383 }
16384 } else {
16385 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
16386 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16387 if (cond.Is(al)) {
16388 uint32_t fbits_ = 64 - fbits;
16389 EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16390 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16391 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16392 return;
16393 }
16394 }
16395 }
16396 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16397}
16398
16399void Assembler::vcvt(Condition cond,
16400 DataType dt1,
16401 DataType dt2,
16402 SRegister rd,
16403 SRegister rm,
16404 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016405 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016406 CheckIT(cond);
16407 Dt_U_sx_1 encoded_dt(dt2);
16408 Dt_U_sx_1 encoded_dt_2(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016409 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016410 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
16411 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16412 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16413 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16414 unsigned offset = 32;
16415 if (dt2.Is(S16) || dt2.Is(U16)) {
16416 offset = 16;
16417 }
16418 uint32_t fbits_ = offset - fbits;
16419 EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16420 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16421 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16422 ((fbits_ & 0x1e) >> 1));
16423 AdvanceIT();
16424 return;
16425 }
16426 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
16427 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16428 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16429 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16430 unsigned offset = 32;
16431 if (dt1.Is(S16) || dt1.Is(U16)) {
16432 offset = 16;
16433 }
16434 uint32_t fbits_ = offset - fbits;
16435 EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16436 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16437 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16438 ((fbits_ & 0x1e) >> 1));
16439 AdvanceIT();
16440 return;
16441 }
16442 } else {
16443 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
16444 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16445 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16446 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16447 cond.IsNotNever()) {
16448 unsigned offset = 32;
16449 if (dt2.Is(S16) || dt2.Is(U16)) {
16450 offset = 16;
16451 }
16452 uint32_t fbits_ = offset - fbits;
16453 EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
16454 ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16455 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16456 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16457 ((fbits_ & 0x1e) >> 1));
16458 return;
16459 }
16460 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
16461 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16462 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16463 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16464 cond.IsNotNever()) {
16465 unsigned offset = 32;
16466 if (dt1.Is(S16) || dt1.Is(U16)) {
16467 offset = 16;
16468 }
16469 uint32_t fbits_ = offset - fbits;
16470 EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
16471 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16472 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16473 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16474 ((fbits_ & 0x1e) >> 1));
16475 return;
16476 }
16477 }
16478 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16479}
16480
16481void Assembler::vcvt(
16482 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016483 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016484 CheckIT(cond);
16485 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016486 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016487 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
16488 if (encoded_dt.IsValid()) {
16489 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16490 EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
16491 rd.Encode(22, 12) | rm.Encode(5, 0));
16492 AdvanceIT();
16493 return;
16494 }
16495 }
16496 } else {
16497 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
16498 if (encoded_dt.IsValid()) {
16499 if (cond.Is(al)) {
16500 EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
16501 rd.Encode(22, 12) | rm.Encode(5, 0));
16502 return;
16503 }
16504 }
16505 }
16506 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16507}
16508
16509void Assembler::vcvt(
16510 Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016511 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016512 CheckIT(cond);
16513 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016514 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016515 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
16516 if (encoded_dt.IsValid()) {
16517 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16518 EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
16519 rd.Encode(22, 12) | rm.Encode(5, 0));
16520 AdvanceIT();
16521 return;
16522 }
16523 }
16524 } else {
16525 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
16526 if (encoded_dt.IsValid()) {
16527 if (cond.Is(al)) {
16528 EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
16529 rd.Encode(22, 12) | rm.Encode(5, 0));
16530 return;
16531 }
16532 }
16533 }
16534 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16535}
16536
16537void Assembler::vcvt(
16538 Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016539 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016540 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016541 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016542 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
16543 if (dt1.Is(F16) && dt2.Is(F32)) {
16544 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16545 EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16546 AdvanceIT();
16547 return;
16548 }
16549 }
16550 } else {
16551 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
16552 if (dt1.Is(F16) && dt2.Is(F32)) {
16553 if (cond.Is(al)) {
16554 EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16555 return;
16556 }
16557 }
16558 }
16559 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16560}
16561
16562void Assembler::vcvt(
16563 Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016564 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016565 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016566 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016567 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
16568 if (dt1.Is(F32) && dt2.Is(F16)) {
16569 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16570 EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16571 AdvanceIT();
16572 return;
16573 }
16574 }
16575 } else {
16576 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
16577 if (dt1.Is(F32) && dt2.Is(F16)) {
16578 if (cond.Is(al)) {
16579 EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16580 return;
16581 }
16582 }
16583 }
16584 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16585}
16586
16587void Assembler::vcvt(
16588 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016589 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016590 CheckIT(cond);
16591 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016592 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016593 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
16594 if (dt1.Is(U32) && dt2.Is(F32)) {
16595 EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16596 AdvanceIT();
16597 return;
16598 }
16599 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
16600 if (dt1.Is(S32) && dt2.Is(F32)) {
16601 EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16602 AdvanceIT();
16603 return;
16604 }
16605 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
16606 if (dt1.Is(F32) && encoded_dt.IsValid()) {
16607 EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
16608 rd.Encode(22, 12) | rm.Encode(5, 0));
16609 AdvanceIT();
16610 return;
16611 }
16612 } else {
16613 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
16614 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
16615 EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16616 rm.Encode(5, 0));
16617 return;
16618 }
16619 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
16620 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
16621 EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16622 rm.Encode(5, 0));
16623 return;
16624 }
16625 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
16626 if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
16627 EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
16628 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16629 rm.Encode(5, 0));
16630 return;
16631 }
16632 }
16633 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16634}
16635
16636void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016637 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016638 CheckIT(al);
16639 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016640 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016641 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16642 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16643 EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
16644 rd.Encode(22, 12) | rm.Encode(5, 0));
16645 AdvanceIT();
16646 return;
16647 }
16648 } else {
16649 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16650 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16651 EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
16652 rd.Encode(22, 12) | rm.Encode(5, 0));
16653 return;
16654 }
16655 }
16656 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16657}
16658
16659void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016660 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016661 CheckIT(al);
16662 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016663 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016664 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16665 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16666 EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
16667 rd.Encode(22, 12) | rm.Encode(5, 0));
16668 AdvanceIT();
16669 return;
16670 }
16671 } else {
16672 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16673 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16674 EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
16675 rd.Encode(22, 12) | rm.Encode(5, 0));
16676 return;
16677 }
16678 }
16679 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16680}
16681
16682void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016683 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016684 CheckIT(al);
16685 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016686 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016687 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16688 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16689 EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16690 rd.Encode(22, 12) | rm.Encode(5, 0));
16691 AdvanceIT();
16692 return;
16693 }
16694 } else {
16695 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16696 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16697 EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16698 rd.Encode(22, 12) | rm.Encode(5, 0));
16699 return;
16700 }
16701 }
16702 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16703}
16704
16705void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016706 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016707 CheckIT(al);
16708 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016709 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016710 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16711 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16712 EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16713 rd.Encode(22, 12) | rm.Encode(5, 0));
16714 AdvanceIT();
16715 return;
16716 }
16717 } else {
16718 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16719 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16720 EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16721 rd.Encode(22, 12) | rm.Encode(5, 0));
16722 return;
16723 }
16724 }
16725 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16726}
16727
16728void Assembler::vcvtb(
16729 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016730 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016731 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016732 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016733 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16734 if (dt1.Is(F32) && dt2.Is(F16)) {
16735 EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16736 AdvanceIT();
16737 return;
16738 }
16739 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16740 if (dt1.Is(F16) && dt2.Is(F32)) {
16741 EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16742 AdvanceIT();
16743 return;
16744 }
16745 } else {
16746 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16747 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16748 EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16749 rm.Encode(5, 0));
16750 return;
16751 }
16752 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16753 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16754 EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16755 rm.Encode(5, 0));
16756 return;
16757 }
16758 }
16759 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16760}
16761
16762void Assembler::vcvtb(
16763 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016764 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016765 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016766 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016767 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16768 if (dt1.Is(F64) && dt2.Is(F16)) {
16769 EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16770 AdvanceIT();
16771 return;
16772 }
16773 } else {
16774 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16775 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16776 EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16777 rm.Encode(5, 0));
16778 return;
16779 }
16780 }
16781 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16782}
16783
16784void Assembler::vcvtb(
16785 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016786 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016787 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016788 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016789 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16790 if (dt1.Is(F16) && dt2.Is(F64)) {
16791 EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16792 AdvanceIT();
16793 return;
16794 }
16795 } else {
16796 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16797 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16798 EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16799 rm.Encode(5, 0));
16800 return;
16801 }
16802 }
16803 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16804}
16805
16806void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016807 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016808 CheckIT(al);
16809 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016810 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016811 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16812 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16813 EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
16814 rd.Encode(22, 12) | rm.Encode(5, 0));
16815 AdvanceIT();
16816 return;
16817 }
16818 } else {
16819 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16820 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16821 EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
16822 rd.Encode(22, 12) | rm.Encode(5, 0));
16823 return;
16824 }
16825 }
16826 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16827}
16828
16829void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016830 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016831 CheckIT(al);
16832 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016833 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016834 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16835 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16836 EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
16837 rd.Encode(22, 12) | rm.Encode(5, 0));
16838 AdvanceIT();
16839 return;
16840 }
16841 } else {
16842 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16843 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16844 EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
16845 rd.Encode(22, 12) | rm.Encode(5, 0));
16846 return;
16847 }
16848 }
16849 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16850}
16851
16852void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016853 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016854 CheckIT(al);
16855 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016856 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016857 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16858 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16859 EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16860 rd.Encode(22, 12) | rm.Encode(5, 0));
16861 AdvanceIT();
16862 return;
16863 }
16864 } else {
16865 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16866 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16867 EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16868 rd.Encode(22, 12) | rm.Encode(5, 0));
16869 return;
16870 }
16871 }
16872 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16873}
16874
16875void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016876 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016877 CheckIT(al);
16878 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016879 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016880 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16881 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16882 EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16883 rd.Encode(22, 12) | rm.Encode(5, 0));
16884 AdvanceIT();
16885 return;
16886 }
16887 } else {
16888 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16889 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16890 EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16891 rd.Encode(22, 12) | rm.Encode(5, 0));
16892 return;
16893 }
16894 }
16895 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16896}
16897
16898void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016899 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016900 CheckIT(al);
16901 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016902 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016903 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16904 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16905 EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
16906 rd.Encode(22, 12) | rm.Encode(5, 0));
16907 AdvanceIT();
16908 return;
16909 }
16910 } else {
16911 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16912 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16913 EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
16914 rd.Encode(22, 12) | rm.Encode(5, 0));
16915 return;
16916 }
16917 }
16918 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16919}
16920
16921void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016922 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016923 CheckIT(al);
16924 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016925 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016926 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16927 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16928 EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
16929 rd.Encode(22, 12) | rm.Encode(5, 0));
16930 AdvanceIT();
16931 return;
16932 }
16933 } else {
16934 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16935 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16936 EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
16937 rd.Encode(22, 12) | rm.Encode(5, 0));
16938 return;
16939 }
16940 }
16941 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16942}
16943
16944void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016946 CheckIT(al);
16947 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016948 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016949 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16950 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16951 EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16952 rd.Encode(22, 12) | rm.Encode(5, 0));
16953 AdvanceIT();
16954 return;
16955 }
16956 } else {
16957 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16958 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16959 EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16960 rd.Encode(22, 12) | rm.Encode(5, 0));
16961 return;
16962 }
16963 }
16964 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16965}
16966
16967void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016968 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016969 CheckIT(al);
16970 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016971 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016972 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16973 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16974 EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
16975 rd.Encode(22, 12) | rm.Encode(5, 0));
16976 AdvanceIT();
16977 return;
16978 }
16979 } else {
16980 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16981 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16982 EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
16983 rd.Encode(22, 12) | rm.Encode(5, 0));
16984 return;
16985 }
16986 }
16987 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16988}
16989
16990void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016991 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016992 CheckIT(al);
16993 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016994 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016995 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16996 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16997 EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
16998 rd.Encode(22, 12) | rm.Encode(5, 0));
16999 AdvanceIT();
17000 return;
17001 }
17002 } else {
17003 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
17004 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17005 EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
17006 rd.Encode(22, 12) | rm.Encode(5, 0));
17007 return;
17008 }
17009 }
17010 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17011}
17012
17013void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017014 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017015 CheckIT(al);
17016 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017017 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017018 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
17019 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17020 EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
17021 rd.Encode(22, 12) | rm.Encode(5, 0));
17022 AdvanceIT();
17023 return;
17024 }
17025 } else {
17026 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
17027 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17028 EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
17029 rd.Encode(22, 12) | rm.Encode(5, 0));
17030 return;
17031 }
17032 }
17033 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17034}
17035
17036void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017037 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017038 CheckIT(al);
17039 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017040 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017041 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
17042 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17043 EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17044 rd.Encode(22, 12) | rm.Encode(5, 0));
17045 AdvanceIT();
17046 return;
17047 }
17048 } else {
17049 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17050 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17051 EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17052 rd.Encode(22, 12) | rm.Encode(5, 0));
17053 return;
17054 }
17055 }
17056 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17057}
17058
17059void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017060 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017061 CheckIT(al);
17062 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017063 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017064 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17065 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17066 EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17067 rd.Encode(22, 12) | rm.Encode(5, 0));
17068 AdvanceIT();
17069 return;
17070 }
17071 } else {
17072 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17073 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17074 EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17075 rd.Encode(22, 12) | rm.Encode(5, 0));
17076 return;
17077 }
17078 }
17079 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17080}
17081
17082void Assembler::vcvtr(
17083 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017084 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017085 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017086 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017087 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
17088 if (dt1.Is(U32) && dt2.Is(F32)) {
17089 EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17090 AdvanceIT();
17091 return;
17092 }
17093 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
17094 if (dt1.Is(S32) && dt2.Is(F32)) {
17095 EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17096 AdvanceIT();
17097 return;
17098 }
17099 } else {
17100 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
17101 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
17102 EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17103 rm.Encode(5, 0));
17104 return;
17105 }
17106 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
17107 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
17108 EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17109 rm.Encode(5, 0));
17110 return;
17111 }
17112 }
17113 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17114}
17115
17116void Assembler::vcvtr(
17117 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017118 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017119 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017120 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017121 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
17122 if (dt1.Is(U32) && dt2.Is(F64)) {
17123 EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17124 AdvanceIT();
17125 return;
17126 }
17127 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
17128 if (dt1.Is(S32) && dt2.Is(F64)) {
17129 EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17130 AdvanceIT();
17131 return;
17132 }
17133 } else {
17134 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
17135 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
17136 EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17137 rm.Encode(5, 0));
17138 return;
17139 }
17140 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
17141 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
17142 EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17143 rm.Encode(5, 0));
17144 return;
17145 }
17146 }
17147 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17148}
17149
17150void Assembler::vcvtt(
17151 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017152 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017153 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017154 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017155 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
17156 if (dt1.Is(F32) && dt2.Is(F16)) {
17157 EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17158 AdvanceIT();
17159 return;
17160 }
17161 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
17162 if (dt1.Is(F16) && dt2.Is(F32)) {
17163 EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17164 AdvanceIT();
17165 return;
17166 }
17167 } else {
17168 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
17169 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
17170 EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17171 rm.Encode(5, 0));
17172 return;
17173 }
17174 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
17175 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
17176 EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17177 rm.Encode(5, 0));
17178 return;
17179 }
17180 }
17181 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17182}
17183
17184void Assembler::vcvtt(
17185 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017186 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017187 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017188 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017189 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
17190 if (dt1.Is(F64) && dt2.Is(F16)) {
17191 EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17192 AdvanceIT();
17193 return;
17194 }
17195 } else {
17196 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
17197 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
17198 EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17199 rm.Encode(5, 0));
17200 return;
17201 }
17202 }
17203 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17204}
17205
17206void Assembler::vcvtt(
17207 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017208 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017209 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017210 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017211 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
17212 if (dt1.Is(F16) && dt2.Is(F64)) {
17213 EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17214 AdvanceIT();
17215 return;
17216 }
17217 } else {
17218 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
17219 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
17220 EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17221 rm.Encode(5, 0));
17222 return;
17223 }
17224 }
17225 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17226}
17227
17228void Assembler::vdiv(
17229 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017230 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017231 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017232 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017233 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
17234 if (dt.Is(F32)) {
17235 EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17236 rm.Encode(5, 0));
17237 AdvanceIT();
17238 return;
17239 }
17240 } else {
17241 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
17242 if (dt.Is(F32) && cond.IsNotNever()) {
17243 EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17244 rn.Encode(7, 16) | rm.Encode(5, 0));
17245 return;
17246 }
17247 }
17248 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17249}
17250
17251void Assembler::vdiv(
17252 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017253 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017254 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017255 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017256 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
17257 if (dt.Is(F64)) {
17258 EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17259 rm.Encode(5, 0));
17260 AdvanceIT();
17261 return;
17262 }
17263 } else {
17264 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
17265 if (dt.Is(F64) && cond.IsNotNever()) {
17266 EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17267 rn.Encode(7, 16) | rm.Encode(5, 0));
17268 return;
17269 }
17270 }
17271 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17272}
17273
17274void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017275 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017276 CheckIT(cond);
17277 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017278 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017279 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017280 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017281 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17282 EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17283 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17284 rd.Encode(7, 16) | (rt.GetCode() << 12));
17285 AdvanceIT();
17286 return;
17287 }
17288 }
17289 } else {
17290 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017291 if (encoded_dt.IsValid() && cond.IsNotNever() &&
17292 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017293 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17294 EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
17295 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17296 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17297 rd.Encode(7, 16) | (rt.GetCode() << 12));
17298 return;
17299 }
17300 }
17301 }
17302 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17303}
17304
17305void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017306 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017307 CheckIT(cond);
17308 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017309 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017310 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017311 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017312 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17313 EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17314 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17315 rd.Encode(7, 16) | (rt.GetCode() << 12));
17316 AdvanceIT();
17317 return;
17318 }
17319 }
17320 } else {
17321 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017322 if (encoded_dt.IsValid() && cond.IsNotNever() &&
17323 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017324 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17325 EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
17326 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17327 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17328 rd.Encode(7, 16) | (rt.GetCode() << 12));
17329 return;
17330 }
17331 }
17332 }
17333 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17334}
17335
17336void Assembler::vdup(Condition cond,
17337 DataType dt,
17338 DRegister rd,
17339 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017340 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017341 CheckIT(cond);
17342 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017343 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017344 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
17345 if (encoded_dt.IsValid()) {
17346 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17347 EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
17348 rd.Encode(22, 12) | rm.Encode(5, 0));
17349 AdvanceIT();
17350 return;
17351 }
17352 }
17353 } else {
17354 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
17355 if (encoded_dt.IsValid()) {
17356 if (cond.Is(al)) {
17357 EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
17358 rd.Encode(22, 12) | rm.Encode(5, 0));
17359 return;
17360 }
17361 }
17362 }
17363 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17364}
17365
17366void Assembler::vdup(Condition cond,
17367 DataType dt,
17368 QRegister rd,
17369 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017370 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017371 CheckIT(cond);
17372 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017373 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017374 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
17375 if (encoded_dt.IsValid()) {
17376 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17377 EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
17378 rd.Encode(22, 12) | rm.Encode(5, 0));
17379 AdvanceIT();
17380 return;
17381 }
17382 }
17383 } else {
17384 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
17385 if (encoded_dt.IsValid()) {
17386 if (cond.Is(al)) {
17387 EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
17388 rd.Encode(22, 12) | rm.Encode(5, 0));
17389 return;
17390 }
17391 }
17392 }
17393 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17394}
17395
17396void Assembler::veor(
17397 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017398 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017399 CheckIT(cond);
17400 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017401 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017402 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
17403 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17404 EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17405 rm.Encode(5, 0));
17406 AdvanceIT();
17407 return;
17408 }
17409 } else {
17410 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
17411 if (cond.Is(al)) {
17412 EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17413 rm.Encode(5, 0));
17414 return;
17415 }
17416 }
17417 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17418}
17419
17420void Assembler::veor(
17421 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017422 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017423 CheckIT(cond);
17424 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017425 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017426 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
17427 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17428 EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17429 rm.Encode(5, 0));
17430 AdvanceIT();
17431 return;
17432 }
17433 } else {
17434 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
17435 if (cond.Is(al)) {
17436 EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17437 rm.Encode(5, 0));
17438 return;
17439 }
17440 }
17441 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17442}
17443
17444void Assembler::vext(Condition cond,
17445 DataType dt,
17446 DRegister rd,
17447 DRegister rn,
17448 DRegister rm,
17449 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017450 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017451 CheckIT(cond);
17452 if (operand.IsImmediate()) {
17453 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17454 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017455 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017456 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17457 if (dt.Is(Untyped8) && (imm <= 7)) {
17458 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17459 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17460 rm.Encode(5, 0) | (imm << 8));
17461 AdvanceIT();
17462 return;
17463 }
17464 }
17465 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17466 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17467 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17468 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17469 uint32_t imm4 = imm / dt.GetSize();
17470 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17471 rm.Encode(5, 0) | (imm4 << 8));
17472 AdvanceIT();
17473 return;
17474 }
17475 }
17476 } else {
17477 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17478 if (dt.Is(Untyped8) && (imm <= 7)) {
17479 if (cond.Is(al)) {
17480 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17481 rm.Encode(5, 0) | (imm << 8));
17482 return;
17483 }
17484 }
17485 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17486 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17487 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17488 if (cond.Is(al)) {
17489 uint32_t imm4 = imm / dt.GetSize();
17490 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17491 rm.Encode(5, 0) | (imm4 << 8));
17492 return;
17493 }
17494 }
17495 }
17496 }
17497 }
17498 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17499}
17500
17501void Assembler::vext(Condition cond,
17502 DataType dt,
17503 QRegister rd,
17504 QRegister rn,
17505 QRegister rm,
17506 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017507 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017508 CheckIT(cond);
17509 if (operand.IsImmediate()) {
17510 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17511 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017512 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017513 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17514 if (dt.Is(Untyped8) && (imm <= 15)) {
17515 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17516 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17517 rm.Encode(5, 0) | (imm << 8));
17518 AdvanceIT();
17519 return;
17520 }
17521 }
17522 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17523 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17524 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17525 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17526 uint32_t imm4 = imm / dt.GetSize();
17527 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17528 rm.Encode(5, 0) | (imm4 << 8));
17529 AdvanceIT();
17530 return;
17531 }
17532 }
17533 } else {
17534 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17535 if (dt.Is(Untyped8) && (imm <= 15)) {
17536 if (cond.Is(al)) {
17537 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17538 rm.Encode(5, 0) | (imm << 8));
17539 return;
17540 }
17541 }
17542 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17543 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17544 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17545 if (cond.Is(al)) {
17546 uint32_t imm4 = imm / dt.GetSize();
17547 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17548 rm.Encode(5, 0) | (imm4 << 8));
17549 return;
17550 }
17551 }
17552 }
17553 }
17554 }
17555 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17556}
17557
17558void Assembler::vfma(
17559 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017560 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017561 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017562 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017563 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17564 if (dt.Is(F32)) {
17565 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17566 EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17567 rm.Encode(5, 0));
17568 AdvanceIT();
17569 return;
17570 }
17571 }
17572 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17573 if (dt.Is(F64)) {
17574 EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17575 rm.Encode(5, 0));
17576 AdvanceIT();
17577 return;
17578 }
17579 } else {
17580 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17581 if (dt.Is(F32)) {
17582 if (cond.Is(al)) {
17583 EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17584 rm.Encode(5, 0));
17585 return;
17586 }
17587 }
17588 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17589 if (dt.Is(F64) && cond.IsNotNever()) {
17590 EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17591 rn.Encode(7, 16) | rm.Encode(5, 0));
17592 return;
17593 }
17594 }
17595 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17596}
17597
17598void Assembler::vfma(
17599 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017600 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017601 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017602 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017603 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17604 if (dt.Is(F32)) {
17605 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17606 EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17607 rm.Encode(5, 0));
17608 AdvanceIT();
17609 return;
17610 }
17611 }
17612 } else {
17613 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17614 if (dt.Is(F32)) {
17615 if (cond.Is(al)) {
17616 EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17617 rm.Encode(5, 0));
17618 return;
17619 }
17620 }
17621 }
17622 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17623}
17624
17625void Assembler::vfma(
17626 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017627 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017628 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017629 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017630 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17631 if (dt.Is(F32)) {
17632 EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17633 rm.Encode(5, 0));
17634 AdvanceIT();
17635 return;
17636 }
17637 } else {
17638 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17639 if (dt.Is(F32) && cond.IsNotNever()) {
17640 EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17641 rn.Encode(7, 16) | rm.Encode(5, 0));
17642 return;
17643 }
17644 }
17645 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17646}
17647
17648void Assembler::vfms(
17649 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017650 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017651 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017652 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017653 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17654 if (dt.Is(F32)) {
17655 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17656 EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17657 rm.Encode(5, 0));
17658 AdvanceIT();
17659 return;
17660 }
17661 }
17662 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17663 if (dt.Is(F64)) {
17664 EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17665 rm.Encode(5, 0));
17666 AdvanceIT();
17667 return;
17668 }
17669 } else {
17670 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17671 if (dt.Is(F32)) {
17672 if (cond.Is(al)) {
17673 EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17674 rm.Encode(5, 0));
17675 return;
17676 }
17677 }
17678 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17679 if (dt.Is(F64) && cond.IsNotNever()) {
17680 EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17681 rn.Encode(7, 16) | rm.Encode(5, 0));
17682 return;
17683 }
17684 }
17685 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17686}
17687
17688void Assembler::vfms(
17689 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017690 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017691 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017692 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017693 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17694 if (dt.Is(F32)) {
17695 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17696 EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17697 rm.Encode(5, 0));
17698 AdvanceIT();
17699 return;
17700 }
17701 }
17702 } else {
17703 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17704 if (dt.Is(F32)) {
17705 if (cond.Is(al)) {
17706 EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17707 rm.Encode(5, 0));
17708 return;
17709 }
17710 }
17711 }
17712 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17713}
17714
17715void Assembler::vfms(
17716 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017717 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017718 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017719 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017720 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17721 if (dt.Is(F32)) {
17722 EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17723 rm.Encode(5, 0));
17724 AdvanceIT();
17725 return;
17726 }
17727 } else {
17728 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17729 if (dt.Is(F32) && cond.IsNotNever()) {
17730 EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17731 rn.Encode(7, 16) | rm.Encode(5, 0));
17732 return;
17733 }
17734 }
17735 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17736}
17737
17738void Assembler::vfnma(
17739 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017740 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017741 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017743 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17744 if (dt.Is(F32)) {
17745 EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17746 rm.Encode(5, 0));
17747 AdvanceIT();
17748 return;
17749 }
17750 } else {
17751 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17752 if (dt.Is(F32) && cond.IsNotNever()) {
17753 EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17754 rn.Encode(7, 16) | rm.Encode(5, 0));
17755 return;
17756 }
17757 }
17758 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17759}
17760
17761void Assembler::vfnma(
17762 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017763 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017764 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017765 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017766 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17767 if (dt.Is(F64)) {
17768 EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17769 rm.Encode(5, 0));
17770 AdvanceIT();
17771 return;
17772 }
17773 } else {
17774 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17775 if (dt.Is(F64) && cond.IsNotNever()) {
17776 EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17777 rn.Encode(7, 16) | rm.Encode(5, 0));
17778 return;
17779 }
17780 }
17781 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17782}
17783
17784void Assembler::vfnms(
17785 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017786 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017787 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017788 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017789 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17790 if (dt.Is(F32)) {
17791 EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17792 rm.Encode(5, 0));
17793 AdvanceIT();
17794 return;
17795 }
17796 } else {
17797 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17798 if (dt.Is(F32) && cond.IsNotNever()) {
17799 EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17800 rn.Encode(7, 16) | rm.Encode(5, 0));
17801 return;
17802 }
17803 }
17804 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17805}
17806
17807void Assembler::vfnms(
17808 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017809 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017810 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017811 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017812 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17813 if (dt.Is(F64)) {
17814 EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17815 rm.Encode(5, 0));
17816 AdvanceIT();
17817 return;
17818 }
17819 } else {
17820 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17821 if (dt.Is(F64) && cond.IsNotNever()) {
17822 EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17823 rn.Encode(7, 16) | rm.Encode(5, 0));
17824 return;
17825 }
17826 }
17827 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17828}
17829
17830void Assembler::vhadd(
17831 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017832 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017833 CheckIT(cond);
17834 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017835 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017836 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17837 if (encoded_dt.IsValid()) {
17838 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17839 EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17840 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17841 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17842 AdvanceIT();
17843 return;
17844 }
17845 }
17846 } else {
17847 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17848 if (encoded_dt.IsValid()) {
17849 if (cond.Is(al)) {
17850 EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17851 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17852 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17853 return;
17854 }
17855 }
17856 }
17857 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17858}
17859
17860void Assembler::vhadd(
17861 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017863 CheckIT(cond);
17864 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017865 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017866 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17867 if (encoded_dt.IsValid()) {
17868 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17869 EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17870 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17871 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17872 AdvanceIT();
17873 return;
17874 }
17875 }
17876 } else {
17877 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17878 if (encoded_dt.IsValid()) {
17879 if (cond.Is(al)) {
17880 EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17881 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17882 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17883 return;
17884 }
17885 }
17886 }
17887 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17888}
17889
17890void Assembler::vhsub(
17891 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017892 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017893 CheckIT(cond);
17894 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017896 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17897 if (encoded_dt.IsValid()) {
17898 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17899 EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17900 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17901 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17902 AdvanceIT();
17903 return;
17904 }
17905 }
17906 } else {
17907 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17908 if (encoded_dt.IsValid()) {
17909 if (cond.Is(al)) {
17910 EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17911 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17912 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17913 return;
17914 }
17915 }
17916 }
17917 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17918}
17919
17920void Assembler::vhsub(
17921 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017922 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017923 CheckIT(cond);
17924 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017925 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017926 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17927 if (encoded_dt.IsValid()) {
17928 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17929 EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17930 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17931 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17932 AdvanceIT();
17933 return;
17934 }
17935 }
17936 } else {
17937 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17938 if (encoded_dt.IsValid()) {
17939 if (cond.Is(al)) {
17940 EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17941 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17942 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17943 return;
17944 }
17945 }
17946 }
17947 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17948}
17949
17950void Assembler::vld1(Condition cond,
17951 DataType dt,
17952 const NeonRegisterList& nreglist,
17953 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017954 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017955 CheckIT(cond);
17956 if (operand.IsImmediateZero()) {
17957 Register rn = operand.GetBaseRegister();
17958 Alignment align = operand.GetAlignment();
17959 Dt_size_6 encoded_dt(dt);
17960 Dt_size_7 encoded_dt_2(dt);
17961 Align_align_1 encoded_align_1(align, nreglist);
17962 Align_a_1 encoded_align_2(align, dt);
17963 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017964 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017965 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17966 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17967 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080017968 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080017969 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017970 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17971 const DRegister& first = nreglist.GetFirstDRegister();
17972 uint32_t len_encoding;
17973 switch (nreglist.GetLength()) {
17974 default:
17975 VIXL_UNREACHABLE_OR_FALLTHROUGH();
17976 case 1:
17977 len_encoding = 0x7;
17978 break;
17979 case 2:
17980 len_encoding = 0xa;
17981 break;
17982 case 3:
17983 len_encoding = 0x6;
17984 break;
17985 case 4:
17986 len_encoding = 0x2;
17987 break;
17988 }
17989 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17990 (encoded_align_1.GetEncodingValue() << 4) |
17991 first.Encode(22, 12) | (len_encoding << 8) |
17992 (rn.GetCode() << 16));
17993 AdvanceIT();
17994 return;
17995 }
17996 }
17997 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17998 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17999 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018000 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018001 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018002 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18003 const DRegister& first = nreglist.GetFirstDRegister();
18004 uint32_t len_encoding;
18005 switch (nreglist.GetLength()) {
18006 default:
18007 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18008 case 1:
18009 len_encoding = 0x7;
18010 break;
18011 case 2:
18012 len_encoding = 0xa;
18013 break;
18014 case 3:
18015 len_encoding = 0x6;
18016 break;
18017 case 4:
18018 len_encoding = 0x2;
18019 break;
18020 }
18021 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18022 (encoded_align_1.GetEncodingValue() << 4) |
18023 first.Encode(22, 12) | (len_encoding << 8) |
18024 (rn.GetCode() << 16));
18025 AdvanceIT();
18026 return;
18027 }
18028 }
18029 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18030 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18031 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018032 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018033 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018034 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18035 const DRegister& first = nreglist.GetFirstDRegister();
18036 uint32_t len_encoding = nreglist.GetLength() - 1;
18037 EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18038 (encoded_align_2.GetEncodingValue() << 4) |
18039 first.Encode(22, 12) | (len_encoding << 5) |
18040 (rn.GetCode() << 16));
18041 AdvanceIT();
18042 return;
18043 }
18044 }
18045 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18046 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18047 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018048 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018049 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018050 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18051 const DRegister& first = nreglist.GetFirstDRegister();
18052 uint32_t len_encoding = nreglist.GetLength() - 1;
18053 EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18054 (encoded_align_2.GetEncodingValue() << 4) |
18055 first.Encode(22, 12) | (len_encoding << 5) |
18056 (rn.GetCode() << 16));
18057 AdvanceIT();
18058 return;
18059 }
18060 }
18061 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18062 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018063 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018064 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018065 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18066 const DRegister& first = nreglist.GetFirstDRegister();
18067 EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18068 (encoded_align_3.GetEncodingValue() << 4) |
18069 first.Encode(22, 12) | (rn.GetCode() << 16));
18070 AdvanceIT();
18071 return;
18072 }
18073 }
18074 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18075 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018076 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018077 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018078 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18079 const DRegister& first = nreglist.GetFirstDRegister();
18080 EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18081 (encoded_align_3.GetEncodingValue() << 4) |
18082 first.Encode(22, 12) | (rn.GetCode() << 16));
18083 AdvanceIT();
18084 return;
18085 }
18086 }
18087 } else {
18088 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18089 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18090 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018091 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018092 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018093 if (cond.Is(al)) {
18094 const DRegister& first = nreglist.GetFirstDRegister();
18095 uint32_t len_encoding;
18096 switch (nreglist.GetLength()) {
18097 default:
18098 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18099 case 1:
18100 len_encoding = 0x7;
18101 break;
18102 case 2:
18103 len_encoding = 0xa;
18104 break;
18105 case 3:
18106 len_encoding = 0x6;
18107 break;
18108 case 4:
18109 len_encoding = 0x2;
18110 break;
18111 }
18112 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18113 (encoded_align_1.GetEncodingValue() << 4) |
18114 first.Encode(22, 12) | (len_encoding << 8) |
18115 (rn.GetCode() << 16));
18116 return;
18117 }
18118 }
18119 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18120 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18121 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018122 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018123 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018124 if (cond.Is(al)) {
18125 const DRegister& first = nreglist.GetFirstDRegister();
18126 uint32_t len_encoding;
18127 switch (nreglist.GetLength()) {
18128 default:
18129 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18130 case 1:
18131 len_encoding = 0x7;
18132 break;
18133 case 2:
18134 len_encoding = 0xa;
18135 break;
18136 case 3:
18137 len_encoding = 0x6;
18138 break;
18139 case 4:
18140 len_encoding = 0x2;
18141 break;
18142 }
18143 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18144 (encoded_align_1.GetEncodingValue() << 4) |
18145 first.Encode(22, 12) | (len_encoding << 8) |
18146 (rn.GetCode() << 16));
18147 return;
18148 }
18149 }
18150 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18151 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18152 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018153 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018154 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018155 if (cond.Is(al)) {
18156 const DRegister& first = nreglist.GetFirstDRegister();
18157 uint32_t len_encoding = nreglist.GetLength() - 1;
18158 EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18159 (encoded_align_2.GetEncodingValue() << 4) |
18160 first.Encode(22, 12) | (len_encoding << 5) |
18161 (rn.GetCode() << 16));
18162 return;
18163 }
18164 }
18165 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18166 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18167 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018168 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018169 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018170 if (cond.Is(al)) {
18171 const DRegister& first = nreglist.GetFirstDRegister();
18172 uint32_t len_encoding = nreglist.GetLength() - 1;
18173 EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18174 (encoded_align_2.GetEncodingValue() << 4) |
18175 first.Encode(22, 12) | (len_encoding << 5) |
18176 (rn.GetCode() << 16));
18177 return;
18178 }
18179 }
18180 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18181 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018182 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018183 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018184 if (cond.Is(al)) {
18185 const DRegister& first = nreglist.GetFirstDRegister();
18186 EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18187 (encoded_align_3.GetEncodingValue() << 4) |
18188 first.Encode(22, 12) | (rn.GetCode() << 16));
18189 return;
18190 }
18191 }
18192 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18193 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018194 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018195 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018196 if (cond.Is(al)) {
18197 const DRegister& first = nreglist.GetFirstDRegister();
18198 EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18199 (encoded_align_3.GetEncodingValue() << 4) |
18200 first.Encode(22, 12) | (rn.GetCode() << 16));
18201 return;
18202 }
18203 }
18204 }
18205 }
18206 if (operand.IsPlainRegister()) {
18207 Register rn = operand.GetBaseRegister();
18208 Alignment align = operand.GetAlignment();
18209 Register rm = operand.GetOffsetRegister();
18210 Dt_size_6 encoded_dt(dt);
18211 Dt_size_7 encoded_dt_2(dt);
18212 Align_align_1 encoded_align_1(align, nreglist);
18213 Align_a_1 encoded_align_2(align, dt);
18214 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018215 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018216 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18217 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18218 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018219 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018220 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18221 const DRegister& first = nreglist.GetFirstDRegister();
18222 uint32_t len_encoding;
18223 switch (nreglist.GetLength()) {
18224 default:
18225 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18226 case 1:
18227 len_encoding = 0x7;
18228 break;
18229 case 2:
18230 len_encoding = 0xa;
18231 break;
18232 case 3:
18233 len_encoding = 0x6;
18234 break;
18235 case 4:
18236 len_encoding = 0x2;
18237 break;
18238 }
18239 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18240 (encoded_align_1.GetEncodingValue() << 4) |
18241 first.Encode(22, 12) | (len_encoding << 8) |
18242 (rn.GetCode() << 16) | rm.GetCode());
18243 AdvanceIT();
18244 return;
18245 }
18246 }
18247 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18248 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18249 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018250 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018251 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18252 const DRegister& first = nreglist.GetFirstDRegister();
18253 uint32_t len_encoding = nreglist.GetLength() - 1;
18254 EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18255 (encoded_align_2.GetEncodingValue() << 4) |
18256 first.Encode(22, 12) | (len_encoding << 5) |
18257 (rn.GetCode() << 16) | rm.GetCode());
18258 AdvanceIT();
18259 return;
18260 }
18261 }
18262 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18263 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018264 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18265 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018266 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18267 const DRegister& first = nreglist.GetFirstDRegister();
18268 EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18269 (encoded_align_3.GetEncodingValue() << 4) |
18270 first.Encode(22, 12) | (rn.GetCode() << 16) |
18271 rm.GetCode());
18272 AdvanceIT();
18273 return;
18274 }
18275 }
18276 } else {
18277 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18278 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18279 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018280 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018281 if (cond.Is(al)) {
18282 const DRegister& first = nreglist.GetFirstDRegister();
18283 uint32_t len_encoding;
18284 switch (nreglist.GetLength()) {
18285 default:
18286 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18287 case 1:
18288 len_encoding = 0x7;
18289 break;
18290 case 2:
18291 len_encoding = 0xa;
18292 break;
18293 case 3:
18294 len_encoding = 0x6;
18295 break;
18296 case 4:
18297 len_encoding = 0x2;
18298 break;
18299 }
18300 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18301 (encoded_align_1.GetEncodingValue() << 4) |
18302 first.Encode(22, 12) | (len_encoding << 8) |
18303 (rn.GetCode() << 16) | rm.GetCode());
18304 return;
18305 }
18306 }
18307 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18308 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18309 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018310 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018311 if (cond.Is(al)) {
18312 const DRegister& first = nreglist.GetFirstDRegister();
18313 uint32_t len_encoding = nreglist.GetLength() - 1;
18314 EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18315 (encoded_align_2.GetEncodingValue() << 4) |
18316 first.Encode(22, 12) | (len_encoding << 5) |
18317 (rn.GetCode() << 16) | rm.GetCode());
18318 return;
18319 }
18320 }
18321 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18322 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018323 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18324 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018325 if (cond.Is(al)) {
18326 const DRegister& first = nreglist.GetFirstDRegister();
18327 EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18328 (encoded_align_3.GetEncodingValue() << 4) |
18329 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18330 return;
18331 }
18332 }
18333 }
18334 }
18335 Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
18336}
18337
18338void Assembler::vld2(Condition cond,
18339 DataType dt,
18340 const NeonRegisterList& nreglist,
18341 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018342 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018343 CheckIT(cond);
18344 if (operand.IsImmediateZero()) {
18345 Register rn = operand.GetBaseRegister();
18346 Alignment align = operand.GetAlignment();
18347 Dt_size_7 encoded_dt(dt);
18348 Align_align_2 encoded_align_1(align, nreglist);
18349 Align_a_2 encoded_align_2(align, dt);
18350 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018352 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18353 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18354 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18355 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18356 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018357 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018358 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018359 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18360 const DRegister& first = nreglist.GetFirstDRegister();
18361 uint32_t len_encoding;
18362 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18363 len_encoding = 0x8;
18364 }
18365 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18366 len_encoding = 0x9;
18367 }
18368 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18369 len_encoding = 0x3;
18370 }
18371 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18372 (encoded_align_1.GetEncodingValue() << 4) |
18373 first.Encode(22, 12) | (len_encoding << 8) |
18374 (rn.GetCode() << 16));
18375 AdvanceIT();
18376 return;
18377 }
18378 }
18379 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18380 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18381 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18382 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18383 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018384 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018385 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018386 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18387 const DRegister& first = nreglist.GetFirstDRegister();
18388 uint32_t len_encoding;
18389 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18390 len_encoding = 0x8;
18391 }
18392 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18393 len_encoding = 0x9;
18394 }
18395 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18396 len_encoding = 0x3;
18397 }
18398 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18399 (encoded_align_1.GetEncodingValue() << 4) |
18400 first.Encode(22, 12) | (len_encoding << 8) |
18401 (rn.GetCode() << 16));
18402 AdvanceIT();
18403 return;
18404 }
18405 }
18406 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18407 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18408 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18409 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018410 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018411 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018412 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18413 const DRegister& first = nreglist.GetFirstDRegister();
18414 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18415 EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18416 (encoded_align_2.GetEncodingValue() << 4) |
18417 first.Encode(22, 12) | (len_encoding << 5) |
18418 (rn.GetCode() << 16));
18419 AdvanceIT();
18420 return;
18421 }
18422 }
18423 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18424 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18425 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18426 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018427 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018428 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018429 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18430 const DRegister& first = nreglist.GetFirstDRegister();
18431 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18432 EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18433 (encoded_align_2.GetEncodingValue() << 4) |
18434 first.Encode(22, 12) | (len_encoding << 5) |
18435 (rn.GetCode() << 16));
18436 AdvanceIT();
18437 return;
18438 }
18439 }
18440 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18441 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18442 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18443 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018444 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018445 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018446 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18447 const DRegister& first = nreglist.GetFirstDRegister();
18448 EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18449 (encoded_align_3.GetEncodingValue() << 4) |
18450 first.Encode(22, 12) | (rn.GetCode() << 16));
18451 AdvanceIT();
18452 return;
18453 }
18454 }
18455 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18456 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18457 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18458 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018459 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018460 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018461 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18462 const DRegister& first = nreglist.GetFirstDRegister();
18463 EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18464 (encoded_align_3.GetEncodingValue() << 4) |
18465 first.Encode(22, 12) | (rn.GetCode() << 16));
18466 AdvanceIT();
18467 return;
18468 }
18469 }
18470 } else {
18471 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18472 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18473 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18474 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18475 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018476 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018477 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018478 if (cond.Is(al)) {
18479 const DRegister& first = nreglist.GetFirstDRegister();
18480 uint32_t len_encoding;
18481 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18482 len_encoding = 0x8;
18483 }
18484 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18485 len_encoding = 0x9;
18486 }
18487 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18488 len_encoding = 0x3;
18489 }
18490 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18491 (encoded_align_1.GetEncodingValue() << 4) |
18492 first.Encode(22, 12) | (len_encoding << 8) |
18493 (rn.GetCode() << 16));
18494 return;
18495 }
18496 }
18497 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18498 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18499 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18500 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18501 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018502 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018503 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018504 if (cond.Is(al)) {
18505 const DRegister& first = nreglist.GetFirstDRegister();
18506 uint32_t len_encoding;
18507 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18508 len_encoding = 0x8;
18509 }
18510 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18511 len_encoding = 0x9;
18512 }
18513 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18514 len_encoding = 0x3;
18515 }
18516 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18517 (encoded_align_1.GetEncodingValue() << 4) |
18518 first.Encode(22, 12) | (len_encoding << 8) |
18519 (rn.GetCode() << 16));
18520 return;
18521 }
18522 }
18523 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18524 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18525 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18526 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018527 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018528 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018529 if (cond.Is(al)) {
18530 const DRegister& first = nreglist.GetFirstDRegister();
18531 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18532 EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18533 (encoded_align_2.GetEncodingValue() << 4) |
18534 first.Encode(22, 12) | (len_encoding << 5) |
18535 (rn.GetCode() << 16));
18536 return;
18537 }
18538 }
18539 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18540 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18541 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18542 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018543 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018544 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018545 if (cond.Is(al)) {
18546 const DRegister& first = nreglist.GetFirstDRegister();
18547 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18548 EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18549 (encoded_align_2.GetEncodingValue() << 4) |
18550 first.Encode(22, 12) | (len_encoding << 5) |
18551 (rn.GetCode() << 16));
18552 return;
18553 }
18554 }
18555 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18556 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18557 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18558 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018559 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018560 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018561 if (cond.Is(al)) {
18562 const DRegister& first = nreglist.GetFirstDRegister();
18563 EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18564 (encoded_align_3.GetEncodingValue() << 4) |
18565 first.Encode(22, 12) | (rn.GetCode() << 16));
18566 return;
18567 }
18568 }
18569 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18570 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18571 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18572 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018573 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018574 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018575 if (cond.Is(al)) {
18576 const DRegister& first = nreglist.GetFirstDRegister();
18577 EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18578 (encoded_align_3.GetEncodingValue() << 4) |
18579 first.Encode(22, 12) | (rn.GetCode() << 16));
18580 return;
18581 }
18582 }
18583 }
18584 }
18585 if (operand.IsPlainRegister()) {
18586 Register rn = operand.GetBaseRegister();
18587 Alignment align = operand.GetAlignment();
18588 Register rm = operand.GetOffsetRegister();
18589 Dt_size_7 encoded_dt(dt);
18590 Align_align_2 encoded_align_1(align, nreglist);
18591 Align_a_2 encoded_align_2(align, dt);
18592 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018593 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018594 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18595 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18596 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18597 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18598 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018599 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018600 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18601 const DRegister& first = nreglist.GetFirstDRegister();
18602 uint32_t len_encoding;
18603 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18604 len_encoding = 0x8;
18605 }
18606 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18607 len_encoding = 0x9;
18608 }
18609 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18610 len_encoding = 0x3;
18611 }
18612 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18613 (encoded_align_1.GetEncodingValue() << 4) |
18614 first.Encode(22, 12) | (len_encoding << 8) |
18615 (rn.GetCode() << 16) | rm.GetCode());
18616 AdvanceIT();
18617 return;
18618 }
18619 }
18620 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18621 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18622 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18623 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018624 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018625 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18626 const DRegister& first = nreglist.GetFirstDRegister();
18627 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18628 EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18629 (encoded_align_2.GetEncodingValue() << 4) |
18630 first.Encode(22, 12) | (len_encoding << 5) |
18631 (rn.GetCode() << 16) | rm.GetCode());
18632 AdvanceIT();
18633 return;
18634 }
18635 }
18636 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18637 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18638 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18639 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018640 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018641 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18642 const DRegister& first = nreglist.GetFirstDRegister();
18643 EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
18644 (encoded_align_3.GetEncodingValue() << 4) |
18645 first.Encode(22, 12) | (rn.GetCode() << 16) |
18646 rm.GetCode());
18647 AdvanceIT();
18648 return;
18649 }
18650 }
18651 } else {
18652 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18653 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18654 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18655 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18656 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018657 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018658 if (cond.Is(al)) {
18659 const DRegister& first = nreglist.GetFirstDRegister();
18660 uint32_t len_encoding;
18661 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18662 len_encoding = 0x8;
18663 }
18664 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18665 len_encoding = 0x9;
18666 }
18667 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18668 len_encoding = 0x3;
18669 }
18670 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18671 (encoded_align_1.GetEncodingValue() << 4) |
18672 first.Encode(22, 12) | (len_encoding << 8) |
18673 (rn.GetCode() << 16) | rm.GetCode());
18674 return;
18675 }
18676 }
18677 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18678 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18679 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18680 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018681 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018682 if (cond.Is(al)) {
18683 const DRegister& first = nreglist.GetFirstDRegister();
18684 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18685 EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18686 (encoded_align_2.GetEncodingValue() << 4) |
18687 first.Encode(22, 12) | (len_encoding << 5) |
18688 (rn.GetCode() << 16) | rm.GetCode());
18689 return;
18690 }
18691 }
18692 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18693 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18694 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18695 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018696 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018697 if (cond.Is(al)) {
18698 const DRegister& first = nreglist.GetFirstDRegister();
18699 EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
18700 (encoded_align_3.GetEncodingValue() << 4) |
18701 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18702 return;
18703 }
18704 }
18705 }
18706 }
18707 Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
18708}
18709
18710void Assembler::vld3(Condition cond,
18711 DataType dt,
18712 const NeonRegisterList& nreglist,
18713 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018714 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018715 CheckIT(cond);
18716 if (operand.IsImmediateZero()) {
18717 Register rn = operand.GetBaseRegister();
18718 Alignment align = operand.GetAlignment();
18719 Dt_size_7 encoded_dt(dt);
18720 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018721 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018722 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18723 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18724 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18725 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018726 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018727 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018728 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18729 const DRegister& first = nreglist.GetFirstDRegister();
18730 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18731 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18732 (encoded_align_1.GetEncodingValue() << 4) |
18733 first.Encode(22, 12) | (len_encoding << 8) |
18734 (rn.GetCode() << 16));
18735 AdvanceIT();
18736 return;
18737 }
18738 }
18739 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18740 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18741 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18742 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018743 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018744 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018745 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18746 const DRegister& first = nreglist.GetFirstDRegister();
18747 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18748 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18749 (encoded_align_1.GetEncodingValue() << 4) |
18750 first.Encode(22, 12) | (len_encoding << 8) |
18751 (rn.GetCode() << 16));
18752 AdvanceIT();
18753 return;
18754 }
18755 }
18756 } else {
18757 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18758 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18759 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18760 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018761 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018762 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018763 if (cond.Is(al)) {
18764 const DRegister& first = nreglist.GetFirstDRegister();
18765 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18766 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18767 (encoded_align_1.GetEncodingValue() << 4) |
18768 first.Encode(22, 12) | (len_encoding << 8) |
18769 (rn.GetCode() << 16));
18770 return;
18771 }
18772 }
18773 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18774 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18775 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18776 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018777 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018778 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018779 if (cond.Is(al)) {
18780 const DRegister& first = nreglist.GetFirstDRegister();
18781 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18782 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18783 (encoded_align_1.GetEncodingValue() << 4) |
18784 first.Encode(22, 12) | (len_encoding << 8) |
18785 (rn.GetCode() << 16));
18786 return;
18787 }
18788 }
18789 }
18790 }
18791 if (operand.IsPlainRegister()) {
18792 Register rn = operand.GetBaseRegister();
18793 Alignment align = operand.GetAlignment();
18794 Register rm = operand.GetOffsetRegister();
18795 Dt_size_7 encoded_dt(dt);
18796 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018797 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018798 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18799 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18800 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18801 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018802 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018803 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18804 const DRegister& first = nreglist.GetFirstDRegister();
18805 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18806 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18807 (encoded_align_1.GetEncodingValue() << 4) |
18808 first.Encode(22, 12) | (len_encoding << 8) |
18809 (rn.GetCode() << 16) | rm.GetCode());
18810 AdvanceIT();
18811 return;
18812 }
18813 }
18814 } else {
18815 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18816 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18817 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18818 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018819 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018820 if (cond.Is(al)) {
18821 const DRegister& first = nreglist.GetFirstDRegister();
18822 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18823 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18824 (encoded_align_1.GetEncodingValue() << 4) |
18825 first.Encode(22, 12) | (len_encoding << 8) |
18826 (rn.GetCode() << 16) | rm.GetCode());
18827 return;
18828 }
18829 }
18830 }
18831 }
18832 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
18833}
18834
18835void Assembler::vld3(Condition cond,
18836 DataType dt,
18837 const NeonRegisterList& nreglist,
18838 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018839 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018840 CheckIT(cond);
18841 if (operand.IsImmediateZero()) {
18842 Register rn = operand.GetBaseRegister();
18843 Dt_size_7 encoded_dt(dt);
18844 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018845 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018846 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18847 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18848 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18849 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018850 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018851 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18852 const DRegister& first = nreglist.GetFirstDRegister();
18853 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18854 EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18855 first.Encode(22, 12) | (len_encoding << 5) |
18856 (rn.GetCode() << 16));
18857 AdvanceIT();
18858 return;
18859 }
18860 }
18861 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18862 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18863 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18864 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018865 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018866 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18867 const DRegister& first = nreglist.GetFirstDRegister();
18868 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18869 EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18870 first.Encode(22, 12) | (len_encoding << 5) |
18871 (rn.GetCode() << 16));
18872 AdvanceIT();
18873 return;
18874 }
18875 }
18876 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18877 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18878 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18879 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018880 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018881 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18882 const DRegister& first = nreglist.GetFirstDRegister();
18883 EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18884 (encoded_align_1.GetEncodingValue() << 4) |
18885 first.Encode(22, 12) | (rn.GetCode() << 16));
18886 AdvanceIT();
18887 return;
18888 }
18889 }
18890 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18891 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18892 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18893 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018894 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018895 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18896 const DRegister& first = nreglist.GetFirstDRegister();
18897 EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18898 (encoded_align_1.GetEncodingValue() << 4) |
18899 first.Encode(22, 12) | (rn.GetCode() << 16));
18900 AdvanceIT();
18901 return;
18902 }
18903 }
18904 } else {
18905 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18906 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18907 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18908 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018909 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018910 if (cond.Is(al)) {
18911 const DRegister& first = nreglist.GetFirstDRegister();
18912 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18913 EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18914 first.Encode(22, 12) | (len_encoding << 5) |
18915 (rn.GetCode() << 16));
18916 return;
18917 }
18918 }
18919 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18920 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18921 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18922 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018923 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018924 if (cond.Is(al)) {
18925 const DRegister& first = nreglist.GetFirstDRegister();
18926 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18927 EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18928 first.Encode(22, 12) | (len_encoding << 5) |
18929 (rn.GetCode() << 16));
18930 return;
18931 }
18932 }
18933 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18934 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18935 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18936 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018937 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018938 if (cond.Is(al)) {
18939 const DRegister& first = nreglist.GetFirstDRegister();
18940 EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18941 (encoded_align_1.GetEncodingValue() << 4) |
18942 first.Encode(22, 12) | (rn.GetCode() << 16));
18943 return;
18944 }
18945 }
18946 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18947 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18948 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18949 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018950 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018951 if (cond.Is(al)) {
18952 const DRegister& first = nreglist.GetFirstDRegister();
18953 EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18954 (encoded_align_1.GetEncodingValue() << 4) |
18955 first.Encode(22, 12) | (rn.GetCode() << 16));
18956 return;
18957 }
18958 }
18959 }
18960 }
18961 if (operand.IsPlainRegister()) {
18962 Register rn = operand.GetBaseRegister();
18963 Sign sign = operand.GetSign();
18964 Register rm = operand.GetOffsetRegister();
18965 Dt_size_7 encoded_dt(dt);
18966 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018968 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
18969 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18970 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18971 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018972 sign.IsPlus() && operand.IsPostIndex() &&
18973 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018974 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18975 const DRegister& first = nreglist.GetFirstDRegister();
18976 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18977 EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
18978 first.Encode(22, 12) | (len_encoding << 5) |
18979 (rn.GetCode() << 16) | rm.GetCode());
18980 AdvanceIT();
18981 return;
18982 }
18983 }
18984 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
18985 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18986 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18987 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018988 sign.IsPlus() && operand.IsPostIndex() &&
18989 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018990 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18991 const DRegister& first = nreglist.GetFirstDRegister();
18992 EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
18993 (encoded_align_1.GetEncodingValue() << 4) |
18994 first.Encode(22, 12) | (rn.GetCode() << 16) |
18995 rm.GetCode());
18996 AdvanceIT();
18997 return;
18998 }
18999 }
19000 } else {
19001 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19002 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
19003 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19004 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019005 sign.IsPlus() && operand.IsPostIndex() &&
19006 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019007 if (cond.Is(al)) {
19008 const DRegister& first = nreglist.GetFirstDRegister();
19009 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19010 EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19011 first.Encode(22, 12) | (len_encoding << 5) |
19012 (rn.GetCode() << 16) | rm.GetCode());
19013 return;
19014 }
19015 }
19016 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19017 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19018 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19019 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019020 sign.IsPlus() && operand.IsPostIndex() &&
19021 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019022 if (cond.Is(al)) {
19023 const DRegister& first = nreglist.GetFirstDRegister();
19024 EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
19025 (encoded_align_1.GetEncodingValue() << 4) |
19026 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19027 return;
19028 }
19029 }
19030 }
19031 }
19032 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
19033}
19034
19035void Assembler::vld4(Condition cond,
19036 DataType dt,
19037 const NeonRegisterList& nreglist,
19038 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019039 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019040 CheckIT(cond);
19041 if (operand.IsImmediateZero()) {
19042 Register rn = operand.GetBaseRegister();
19043 Alignment align = operand.GetAlignment();
19044 Dt_size_7 encoded_dt(dt);
19045 Dt_size_8 encoded_dt_2(dt, align);
19046 Align_align_4 encoded_align_1(align);
19047 Align_a_3 encoded_align_2(align, dt);
19048 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019049 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019050 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19051 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19052 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19053 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019054 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019055 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019056 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19057 const DRegister& first = nreglist.GetFirstDRegister();
19058 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19059 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
19060 (encoded_align_1.GetEncodingValue() << 4) |
19061 first.Encode(22, 12) | (len_encoding << 8) |
19062 (rn.GetCode() << 16));
19063 AdvanceIT();
19064 return;
19065 }
19066 }
19067 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19068 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19069 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19070 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019071 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019072 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019073 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19074 const DRegister& first = nreglist.GetFirstDRegister();
19075 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19076 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
19077 (encoded_align_1.GetEncodingValue() << 4) |
19078 first.Encode(22, 12) | (len_encoding << 8) |
19079 (rn.GetCode() << 16));
19080 AdvanceIT();
19081 return;
19082 }
19083 }
19084 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19085 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19086 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19087 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019088 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019089 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019090 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19091 const DRegister& first = nreglist.GetFirstDRegister();
19092 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19093 EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19094 (encoded_align_2.GetEncodingValue() << 4) |
19095 first.Encode(22, 12) | (len_encoding << 5) |
19096 (rn.GetCode() << 16));
19097 AdvanceIT();
19098 return;
19099 }
19100 }
19101 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19102 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19103 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19104 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019105 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019106 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019107 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19108 const DRegister& first = nreglist.GetFirstDRegister();
19109 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19110 EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19111 (encoded_align_2.GetEncodingValue() << 4) |
19112 first.Encode(22, 12) | (len_encoding << 5) |
19113 (rn.GetCode() << 16));
19114 AdvanceIT();
19115 return;
19116 }
19117 }
19118 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19119 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19120 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19121 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019122 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019123 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019124 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19125 const DRegister& first = nreglist.GetFirstDRegister();
19126 EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19127 (encoded_align_3.GetEncodingValue() << 4) |
19128 first.Encode(22, 12) | (rn.GetCode() << 16));
19129 AdvanceIT();
19130 return;
19131 }
19132 }
19133 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19134 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19135 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19136 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019137 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019138 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019139 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19140 const DRegister& first = nreglist.GetFirstDRegister();
19141 EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19142 (encoded_align_3.GetEncodingValue() << 4) |
19143 first.Encode(22, 12) | (rn.GetCode() << 16));
19144 AdvanceIT();
19145 return;
19146 }
19147 }
19148 } else {
19149 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19150 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19151 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19152 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019153 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019154 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019155 if (cond.Is(al)) {
19156 const DRegister& first = nreglist.GetFirstDRegister();
19157 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19158 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
19159 (encoded_align_1.GetEncodingValue() << 4) |
19160 first.Encode(22, 12) | (len_encoding << 8) |
19161 (rn.GetCode() << 16));
19162 return;
19163 }
19164 }
19165 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19166 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19167 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19168 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019169 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019170 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019171 if (cond.Is(al)) {
19172 const DRegister& first = nreglist.GetFirstDRegister();
19173 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19174 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
19175 (encoded_align_1.GetEncodingValue() << 4) |
19176 first.Encode(22, 12) | (len_encoding << 8) |
19177 (rn.GetCode() << 16));
19178 return;
19179 }
19180 }
19181 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19182 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19183 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19184 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019185 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019186 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019187 if (cond.Is(al)) {
19188 const DRegister& first = nreglist.GetFirstDRegister();
19189 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19190 EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19191 (encoded_align_2.GetEncodingValue() << 4) |
19192 first.Encode(22, 12) | (len_encoding << 5) |
19193 (rn.GetCode() << 16));
19194 return;
19195 }
19196 }
19197 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19198 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19199 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19200 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019201 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019202 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019203 if (cond.Is(al)) {
19204 const DRegister& first = nreglist.GetFirstDRegister();
19205 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19206 EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19207 (encoded_align_2.GetEncodingValue() << 4) |
19208 first.Encode(22, 12) | (len_encoding << 5) |
19209 (rn.GetCode() << 16));
19210 return;
19211 }
19212 }
19213 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19214 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19215 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19216 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019217 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019218 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019219 if (cond.Is(al)) {
19220 const DRegister& first = nreglist.GetFirstDRegister();
19221 EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19222 (encoded_align_3.GetEncodingValue() << 4) |
19223 first.Encode(22, 12) | (rn.GetCode() << 16));
19224 return;
19225 }
19226 }
19227 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19228 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19229 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19230 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019231 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019232 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019233 if (cond.Is(al)) {
19234 const DRegister& first = nreglist.GetFirstDRegister();
19235 EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19236 (encoded_align_3.GetEncodingValue() << 4) |
19237 first.Encode(22, 12) | (rn.GetCode() << 16));
19238 return;
19239 }
19240 }
19241 }
19242 }
19243 if (operand.IsPlainRegister()) {
19244 Register rn = operand.GetBaseRegister();
19245 Alignment align = operand.GetAlignment();
19246 Register rm = operand.GetOffsetRegister();
19247 Dt_size_7 encoded_dt(dt);
19248 Dt_size_8 encoded_dt_2(dt, align);
19249 Align_align_4 encoded_align_1(align);
19250 Align_a_3 encoded_align_2(align, dt);
19251 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019252 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019253 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19254 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19255 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19256 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019257 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019258 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19259 const DRegister& first = nreglist.GetFirstDRegister();
19260 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19261 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
19262 (encoded_align_1.GetEncodingValue() << 4) |
19263 first.Encode(22, 12) | (len_encoding << 8) |
19264 (rn.GetCode() << 16) | rm.GetCode());
19265 AdvanceIT();
19266 return;
19267 }
19268 }
19269 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19270 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19271 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19272 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019273 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019274 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19275 const DRegister& first = nreglist.GetFirstDRegister();
19276 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19277 EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19278 (encoded_align_2.GetEncodingValue() << 4) |
19279 first.Encode(22, 12) | (len_encoding << 5) |
19280 (rn.GetCode() << 16) | rm.GetCode());
19281 AdvanceIT();
19282 return;
19283 }
19284 }
19285 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19286 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19287 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19288 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019289 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019290 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19291 const DRegister& first = nreglist.GetFirstDRegister();
19292 EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
19293 (encoded_align_3.GetEncodingValue() << 4) |
19294 first.Encode(22, 12) | (rn.GetCode() << 16) |
19295 rm.GetCode());
19296 AdvanceIT();
19297 return;
19298 }
19299 }
19300 } else {
19301 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19302 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19303 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19304 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019305 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019306 if (cond.Is(al)) {
19307 const DRegister& first = nreglist.GetFirstDRegister();
19308 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19309 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
19310 (encoded_align_1.GetEncodingValue() << 4) |
19311 first.Encode(22, 12) | (len_encoding << 8) |
19312 (rn.GetCode() << 16) | rm.GetCode());
19313 return;
19314 }
19315 }
19316 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19317 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19318 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19319 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019320 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019321 if (cond.Is(al)) {
19322 const DRegister& first = nreglist.GetFirstDRegister();
19323 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19324 EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19325 (encoded_align_2.GetEncodingValue() << 4) |
19326 first.Encode(22, 12) | (len_encoding << 5) |
19327 (rn.GetCode() << 16) | rm.GetCode());
19328 return;
19329 }
19330 }
19331 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19332 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19333 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19334 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019335 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019336 if (cond.Is(al)) {
19337 const DRegister& first = nreglist.GetFirstDRegister();
19338 EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
19339 (encoded_align_3.GetEncodingValue() << 4) |
19340 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19341 return;
19342 }
19343 }
19344 }
19345 }
19346 Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
19347}
19348
19349void Assembler::vldm(Condition cond,
19350 DataType dt,
19351 Register rn,
19352 WriteBack write_back,
19353 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019354 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019355 CheckIT(cond);
19356 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019357 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019358 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019359 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19360 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019361 const DRegister& dreg = dreglist.GetFirstDRegister();
19362 unsigned len = dreglist.GetLength() * 2;
19363 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19364 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19365 (len & 0xff));
19366 AdvanceIT();
19367 return;
19368 }
19369 } else {
19370 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019371 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19372 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19373 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019374 const DRegister& dreg = dreglist.GetFirstDRegister();
19375 unsigned len = dreglist.GetLength() * 2;
19376 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19377 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19378 (len & 0xff));
19379 return;
19380 }
19381 }
19382 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
19383}
19384
19385void Assembler::vldm(Condition cond,
19386 DataType dt,
19387 Register rn,
19388 WriteBack write_back,
19389 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019390 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019391 CheckIT(cond);
19392 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019393 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019394 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019395 if ((!rn.IsPC() || AllowUnpredictable())) {
19396 const SRegister& sreg = sreglist.GetFirstSRegister();
19397 unsigned len = sreglist.GetLength();
19398 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19399 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19400 (len & 0xff));
19401 AdvanceIT();
19402 return;
19403 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010019404 } else {
19405 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019406 if (cond.IsNotNever() &&
19407 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019408 const SRegister& sreg = sreglist.GetFirstSRegister();
19409 unsigned len = sreglist.GetLength();
19410 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19411 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19412 (len & 0xff));
19413 return;
19414 }
19415 }
19416 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
19417}
19418
19419void Assembler::vldmdb(Condition cond,
19420 DataType dt,
19421 Register rn,
19422 WriteBack write_back,
19423 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019424 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019425 CheckIT(cond);
19426 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019427 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019428 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
19429 if (write_back.DoesWriteBack() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019430 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19431 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019432 const DRegister& dreg = dreglist.GetFirstDRegister();
19433 unsigned len = dreglist.GetLength() * 2;
19434 EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
19435 (len & 0xff));
19436 AdvanceIT();
19437 return;
19438 }
19439 } else {
19440 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
19441 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019442 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19443 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019444 const DRegister& dreg = dreglist.GetFirstDRegister();
19445 unsigned len = dreglist.GetLength() * 2;
19446 EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19447 dreg.Encode(22, 12) | (len & 0xff));
19448 return;
19449 }
19450 }
19451 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
19452}
19453
19454void Assembler::vldmdb(Condition cond,
19455 DataType dt,
19456 Register rn,
19457 WriteBack write_back,
19458 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019459 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019460 CheckIT(cond);
19461 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019462 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019463 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019464 if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019465 const SRegister& sreg = sreglist.GetFirstSRegister();
19466 unsigned len = sreglist.GetLength();
19467 EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
19468 (len & 0xff));
19469 AdvanceIT();
19470 return;
19471 }
19472 } else {
19473 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019474 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
19475 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019476 const SRegister& sreg = sreglist.GetFirstSRegister();
19477 unsigned len = sreglist.GetLength();
19478 EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19479 sreg.Encode(22, 12) | (len & 0xff));
19480 return;
19481 }
19482 }
19483 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
19484}
19485
19486void Assembler::vldmia(Condition cond,
19487 DataType dt,
19488 Register rn,
19489 WriteBack write_back,
19490 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019491 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019492 CheckIT(cond);
19493 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019494 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019495 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019496 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19497 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019498 const DRegister& dreg = dreglist.GetFirstDRegister();
19499 unsigned len = dreglist.GetLength() * 2;
19500 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19501 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19502 (len & 0xff));
19503 AdvanceIT();
19504 return;
19505 }
19506 } else {
19507 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019508 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19509 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19510 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019511 const DRegister& dreg = dreglist.GetFirstDRegister();
19512 unsigned len = dreglist.GetLength() * 2;
19513 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19514 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19515 (len & 0xff));
19516 return;
19517 }
19518 }
19519 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
19520}
19521
19522void Assembler::vldmia(Condition cond,
19523 DataType dt,
19524 Register rn,
19525 WriteBack write_back,
19526 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019527 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019528 CheckIT(cond);
19529 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019530 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019531 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019532 if ((!rn.IsPC() || AllowUnpredictable())) {
19533 const SRegister& sreg = sreglist.GetFirstSRegister();
19534 unsigned len = sreglist.GetLength();
19535 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19536 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19537 (len & 0xff));
19538 AdvanceIT();
19539 return;
19540 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010019541 } else {
19542 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019543 if (cond.IsNotNever() &&
19544 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019545 const SRegister& sreg = sreglist.GetFirstSRegister();
19546 unsigned len = sreglist.GetLength();
19547 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19548 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19549 (len & 0xff));
19550 return;
19551 }
19552 }
19553 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
19554}
19555
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019556void Assembler::vldr(Condition cond,
19557 DataType dt,
19558 DRegister rd,
19559 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019560 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019561 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019562 Location::Offset offset =
19563 location->IsBound()
19564 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +010019565 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19566 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019567 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019568 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19569 if (dt.IsNoneOr(Untyped64) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019570 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019571 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019572 !location->IsBound())) {
19573 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019574 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019575 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019576 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019577 Location::Offset pc,
19578 const Location* location) const VIXL_OVERRIDE {
19579 pc += kT32PcDelta;
19580 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019581 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19582 ((offset & 0x3) == 0));
19583 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019584 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019585 target = abs(target) | (U << 8);
19586 return instr | (target & 0xff) | ((target & 0x100) << 15);
19587 }
19588 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -070019589 EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12),
19590 location,
19591 immop,
19592 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019593 AdvanceIT();
19594 return;
19595 }
19596 } else {
19597 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19598 if (dt.IsNoneOr(Untyped64) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019599 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019600 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019601 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019602 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019603 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019604 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019605 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019606 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019607 Location::Offset pc,
19608 const Location* location) const VIXL_OVERRIDE {
19609 pc += kA32PcDelta;
19610 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019611 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19612 ((offset & 0x3) == 0));
19613 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019614 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019615 target = abs(target) | (U << 8);
19616 return instr | (target & 0xff) | ((target & 0x100) << 15);
19617 }
19618 } immop;
19619 EmitA32(
19620 Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019621 location,
19622 immop,
Vincent Belliardac285442017-05-16 09:26:45 -070019623 &kA32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019624 return;
19625 }
19626 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019627 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019628}
19629
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019630bool Assembler::vldr_info(Condition cond,
19631 DataType dt,
19632 DRegister rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019633 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019634 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019635 VIXL_ASSERT(!location->IsBound());
19636 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019637 USE(rd);
19638 if (IsUsingT32()) {
19639 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19640 if (dt.IsNoneOr(Untyped64)) {
Vincent Belliardac285442017-05-16 09:26:45 -070019641 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019642 return true;
19643 }
19644 } else {
19645 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19646 if (dt.IsNoneOr(Untyped64) && cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -070019647 *info = &kA32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019648 return true;
19649 }
19650 }
19651 return false;
19652}
19653
Alexandre Ramesd3832962016-07-04 15:03:43 +010019654void Assembler::vldr(Condition cond,
19655 DataType dt,
19656 DRegister rd,
19657 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019658 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019659 CheckIT(cond);
19660 if (operand.IsImmediate()) {
19661 Register rn = operand.GetBaseRegister();
19662 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019663 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019664 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
19665 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019666 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019667 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19668 uint32_t offset_ = abs(offset) >> 2;
19669 EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19670 AdvanceIT();
19671 return;
19672 }
19673 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
19674 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019675 ((offset % 4) == 0) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019676 ((rn.GetCode() & 0xf) != 0xf)) {
19677 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19678 uint32_t offset_ = abs(offset) >> 2;
19679 EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19680 offset_ | (sign << 23));
19681 AdvanceIT();
19682 return;
19683 }
19684 } else {
19685 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
19686 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019687 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19688 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019689 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19690 uint32_t offset_ = abs(offset) >> 2;
19691 EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19692 offset_ | (sign << 23));
19693 return;
19694 }
19695 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
19696 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019697 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19698 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019699 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19700 uint32_t offset_ = abs(offset) >> 2;
19701 EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19702 (rn.GetCode() << 16) | offset_ | (sign << 23));
19703 return;
19704 }
19705 }
19706 }
19707 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19708}
19709
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019710void Assembler::vldr(Condition cond,
19711 DataType dt,
19712 SRegister rd,
19713 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019714 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019715 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019716 Location::Offset offset =
19717 location->IsBound()
19718 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +010019719 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19720 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019721 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019722 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19723 if (dt.IsNoneOr(Untyped32) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019724 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019725 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019726 !location->IsBound())) {
19727 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019728 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019729 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019730 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019731 Location::Offset pc,
19732 const Location* location) const VIXL_OVERRIDE {
19733 pc += kT32PcDelta;
19734 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019735 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19736 ((offset & 0x3) == 0));
19737 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019738 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019739 target = abs(target) | (U << 8);
19740 return instr | (target & 0xff) | ((target & 0x100) << 15);
19741 }
19742 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -070019743 EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12),
19744 location,
19745 immop,
19746 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019747 AdvanceIT();
19748 return;
19749 }
19750 } else {
19751 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19752 if (dt.IsNoneOr(Untyped32) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019753 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019754 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019755 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019756 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019757 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019758 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019759 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019760 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019761 Location::Offset pc,
19762 const Location* location) const VIXL_OVERRIDE {
19763 pc += kA32PcDelta;
19764 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019765 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19766 ((offset & 0x3) == 0));
19767 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019768 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019769 target = abs(target) | (U << 8);
19770 return instr | (target & 0xff) | ((target & 0x100) << 15);
19771 }
19772 } immop;
19773 EmitA32(
19774 Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019775 location,
19776 immop,
Vincent Belliardac285442017-05-16 09:26:45 -070019777 &kA32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019778 return;
19779 }
19780 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019781 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019782}
19783
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019784bool Assembler::vldr_info(Condition cond,
19785 DataType dt,
19786 SRegister rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019787 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019788 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019789 VIXL_ASSERT(!location->IsBound());
19790 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019791 USE(rd);
19792 if (IsUsingT32()) {
19793 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19794 if (dt.IsNoneOr(Untyped32)) {
Vincent Belliardac285442017-05-16 09:26:45 -070019795 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019796 return true;
19797 }
19798 } else {
19799 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19800 if (dt.IsNoneOr(Untyped32) && cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -070019801 *info = &kA32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019802 return true;
19803 }
19804 }
19805 return false;
19806}
19807
Alexandre Ramesd3832962016-07-04 15:03:43 +010019808void Assembler::vldr(Condition cond,
19809 DataType dt,
19810 SRegister rd,
19811 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019812 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019813 CheckIT(cond);
19814 if (operand.IsImmediate()) {
19815 Register rn = operand.GetBaseRegister();
19816 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019817 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019818 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
19819 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019820 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019821 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19822 uint32_t offset_ = abs(offset) >> 2;
19823 EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19824 AdvanceIT();
19825 return;
19826 }
19827 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
19828 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019829 ((offset % 4) == 0) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019830 ((rn.GetCode() & 0xf) != 0xf)) {
19831 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19832 uint32_t offset_ = abs(offset) >> 2;
19833 EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19834 offset_ | (sign << 23));
19835 AdvanceIT();
19836 return;
19837 }
19838 } else {
19839 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
19840 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019841 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19842 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019843 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19844 uint32_t offset_ = abs(offset) >> 2;
19845 EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19846 offset_ | (sign << 23));
19847 return;
19848 }
19849 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
19850 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019851 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19852 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019853 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19854 uint32_t offset_ = abs(offset) >> 2;
19855 EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19856 (rn.GetCode() << 16) | offset_ | (sign << 23));
19857 return;
19858 }
19859 }
19860 }
19861 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19862}
19863
19864void Assembler::vmax(
19865 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019866 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019867 CheckIT(cond);
19868 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019869 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019870 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
19871 if (dt.Is(F32)) {
19872 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19873 EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19874 rm.Encode(5, 0));
19875 AdvanceIT();
19876 return;
19877 }
19878 }
19879 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
19880 if (encoded_dt.IsValid()) {
19881 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19882 EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19883 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19884 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19885 AdvanceIT();
19886 return;
19887 }
19888 }
19889 } else {
19890 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
19891 if (dt.Is(F32)) {
19892 if (cond.Is(al)) {
19893 EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19894 rm.Encode(5, 0));
19895 return;
19896 }
19897 }
19898 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
19899 if (encoded_dt.IsValid()) {
19900 if (cond.Is(al)) {
19901 EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19902 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19903 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19904 return;
19905 }
19906 }
19907 }
19908 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19909}
19910
19911void Assembler::vmax(
19912 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019913 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019914 CheckIT(cond);
19915 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019916 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019917 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
19918 if (dt.Is(F32)) {
19919 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19920 EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19921 rm.Encode(5, 0));
19922 AdvanceIT();
19923 return;
19924 }
19925 }
19926 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
19927 if (encoded_dt.IsValid()) {
19928 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19929 EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19930 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19931 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19932 AdvanceIT();
19933 return;
19934 }
19935 }
19936 } else {
19937 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
19938 if (dt.Is(F32)) {
19939 if (cond.Is(al)) {
19940 EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19941 rm.Encode(5, 0));
19942 return;
19943 }
19944 }
19945 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
19946 if (encoded_dt.IsValid()) {
19947 if (cond.Is(al)) {
19948 EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19949 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19950 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19951 return;
19952 }
19953 }
19954 }
19955 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19956}
19957
19958void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019959 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019960 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019961 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019962 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19963 if (OutsideITBlock() && dt.Is(F32)) {
19964 EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19965 rm.Encode(5, 0));
19966 AdvanceIT();
19967 return;
19968 }
19969 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19970 if (OutsideITBlock() && dt.Is(F64)) {
19971 EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19972 rm.Encode(5, 0));
19973 AdvanceIT();
19974 return;
19975 }
19976 } else {
19977 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19978 if (dt.Is(F32)) {
19979 EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19980 rm.Encode(5, 0));
19981 return;
19982 }
19983 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19984 if (dt.Is(F64)) {
19985 EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19986 rm.Encode(5, 0));
19987 return;
19988 }
19989 }
19990 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
19991}
19992
19993void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019994 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019995 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019996 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019997 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19998 if (OutsideITBlock() && dt.Is(F32)) {
19999 EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20000 rm.Encode(5, 0));
20001 AdvanceIT();
20002 return;
20003 }
20004 } else {
20005 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20006 if (dt.Is(F32)) {
20007 EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20008 rm.Encode(5, 0));
20009 return;
20010 }
20011 }
20012 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20013}
20014
20015void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020016 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020017 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020018 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020019 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20020 if (OutsideITBlock() && dt.Is(F32)) {
20021 EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20022 rm.Encode(5, 0));
20023 AdvanceIT();
20024 return;
20025 }
20026 } else {
20027 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20028 if (dt.Is(F32)) {
20029 EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20030 rm.Encode(5, 0));
20031 return;
20032 }
20033 }
20034 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20035}
20036
20037void Assembler::vmin(
20038 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020039 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020040 CheckIT(cond);
20041 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020042 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020043 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20044 if (dt.Is(F32)) {
20045 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20046 EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20047 rm.Encode(5, 0));
20048 AdvanceIT();
20049 return;
20050 }
20051 }
20052 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20053 if (encoded_dt.IsValid()) {
20054 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20055 EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20056 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20057 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20058 AdvanceIT();
20059 return;
20060 }
20061 }
20062 } else {
20063 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20064 if (dt.Is(F32)) {
20065 if (cond.Is(al)) {
20066 EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20067 rm.Encode(5, 0));
20068 return;
20069 }
20070 }
20071 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20072 if (encoded_dt.IsValid()) {
20073 if (cond.Is(al)) {
20074 EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20075 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20076 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20077 return;
20078 }
20079 }
20080 }
20081 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20082}
20083
20084void Assembler::vmin(
20085 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020086 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020087 CheckIT(cond);
20088 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020089 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020090 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20091 if (dt.Is(F32)) {
20092 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20093 EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20094 rm.Encode(5, 0));
20095 AdvanceIT();
20096 return;
20097 }
20098 }
20099 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20100 if (encoded_dt.IsValid()) {
20101 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20102 EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20103 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20104 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20105 AdvanceIT();
20106 return;
20107 }
20108 }
20109 } else {
20110 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20111 if (dt.Is(F32)) {
20112 if (cond.Is(al)) {
20113 EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20114 rm.Encode(5, 0));
20115 return;
20116 }
20117 }
20118 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20119 if (encoded_dt.IsValid()) {
20120 if (cond.Is(al)) {
20121 EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20122 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20123 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20124 return;
20125 }
20126 }
20127 }
20128 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20129}
20130
20131void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020132 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020133 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020134 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020135 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20136 if (OutsideITBlock() && dt.Is(F32)) {
20137 EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20138 rm.Encode(5, 0));
20139 AdvanceIT();
20140 return;
20141 }
20142 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20143 if (OutsideITBlock() && dt.Is(F64)) {
20144 EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20145 rm.Encode(5, 0));
20146 AdvanceIT();
20147 return;
20148 }
20149 } else {
20150 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20151 if (dt.Is(F32)) {
20152 EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20153 rm.Encode(5, 0));
20154 return;
20155 }
20156 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20157 if (dt.Is(F64)) {
20158 EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20159 rm.Encode(5, 0));
20160 return;
20161 }
20162 }
20163 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20164}
20165
20166void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020167 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020168 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020169 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020170 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20171 if (OutsideITBlock() && dt.Is(F32)) {
20172 EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20173 rm.Encode(5, 0));
20174 AdvanceIT();
20175 return;
20176 }
20177 } else {
20178 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20179 if (dt.Is(F32)) {
20180 EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20181 rm.Encode(5, 0));
20182 return;
20183 }
20184 }
20185 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20186}
20187
20188void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020189 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020190 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020191 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020192 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20193 if (OutsideITBlock() && dt.Is(F32)) {
20194 EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20195 rm.Encode(5, 0));
20196 AdvanceIT();
20197 return;
20198 }
20199 } else {
20200 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20201 if (dt.Is(F32)) {
20202 EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20203 rm.Encode(5, 0));
20204 return;
20205 }
20206 }
20207 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20208}
20209
20210void Assembler::vmla(
20211 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020212 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020213 CheckIT(cond);
20214 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020215 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020216 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20217 if (encoded_dt.IsValid() &&
20218 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20219 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20220 (rm.GetLane() <= 1)))) {
20221 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20222 EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20223 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20224 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20225 AdvanceIT();
20226 return;
20227 }
20228 }
20229 } else {
20230 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20231 if (encoded_dt.IsValid() &&
20232 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20233 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20234 (rm.GetLane() <= 1)))) {
20235 if (cond.Is(al)) {
20236 EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20237 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20238 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20239 return;
20240 }
20241 }
20242 }
20243 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20244}
20245
20246void Assembler::vmla(
20247 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020248 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020249 CheckIT(cond);
20250 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020251 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020252 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20253 if (encoded_dt.IsValid() &&
20254 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20255 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20256 (rm.GetLane() <= 1)))) {
20257 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20258 EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20259 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20260 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20261 AdvanceIT();
20262 return;
20263 }
20264 }
20265 } else {
20266 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20267 if (encoded_dt.IsValid() &&
20268 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20269 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20270 (rm.GetLane() <= 1)))) {
20271 if (cond.Is(al)) {
20272 EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20273 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20274 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20275 return;
20276 }
20277 }
20278 }
20279 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20280}
20281
20282void Assembler::vmla(
20283 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020284 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020285 CheckIT(cond);
20286 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020287 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020288 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20289 if (dt.Is(F32)) {
20290 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20291 EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20292 rm.Encode(5, 0));
20293 AdvanceIT();
20294 return;
20295 }
20296 }
20297 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20298 if (dt.Is(F64)) {
20299 EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20300 rm.Encode(5, 0));
20301 AdvanceIT();
20302 return;
20303 }
20304 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20305 if (encoded_dt.IsValid()) {
20306 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20307 EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
20308 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20309 AdvanceIT();
20310 return;
20311 }
20312 }
20313 } else {
20314 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20315 if (dt.Is(F32)) {
20316 if (cond.Is(al)) {
20317 EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20318 rm.Encode(5, 0));
20319 return;
20320 }
20321 }
20322 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20323 if (dt.Is(F64) && cond.IsNotNever()) {
20324 EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20325 rn.Encode(7, 16) | rm.Encode(5, 0));
20326 return;
20327 }
20328 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20329 if (encoded_dt.IsValid()) {
20330 if (cond.Is(al)) {
20331 EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
20332 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20333 return;
20334 }
20335 }
20336 }
20337 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20338}
20339
20340void Assembler::vmla(
20341 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020342 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020343 CheckIT(cond);
20344 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020345 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020346 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20347 if (dt.Is(F32)) {
20348 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20349 EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20350 rm.Encode(5, 0));
20351 AdvanceIT();
20352 return;
20353 }
20354 }
20355 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20356 if (encoded_dt.IsValid()) {
20357 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20358 EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
20359 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20360 AdvanceIT();
20361 return;
20362 }
20363 }
20364 } else {
20365 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20366 if (dt.Is(F32)) {
20367 if (cond.Is(al)) {
20368 EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20369 rm.Encode(5, 0));
20370 return;
20371 }
20372 }
20373 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20374 if (encoded_dt.IsValid()) {
20375 if (cond.Is(al)) {
20376 EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
20377 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20378 return;
20379 }
20380 }
20381 }
20382 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20383}
20384
20385void Assembler::vmla(
20386 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020387 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020388 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020389 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020390 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20391 if (dt.Is(F32)) {
20392 EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20393 rm.Encode(5, 0));
20394 AdvanceIT();
20395 return;
20396 }
20397 } else {
20398 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20399 if (dt.Is(F32) && cond.IsNotNever()) {
20400 EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20401 rn.Encode(7, 16) | rm.Encode(5, 0));
20402 return;
20403 }
20404 }
20405 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20406}
20407
20408void Assembler::vmlal(
20409 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020410 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020411 CheckIT(cond);
20412 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020413 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020414 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20415 if (encoded_dt.IsValid() &&
20416 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20417 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20418 (rm.GetLane() <= 1)))) {
20419 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20420 EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
20421 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20422 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20423 AdvanceIT();
20424 return;
20425 }
20426 }
20427 } else {
20428 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20429 if (encoded_dt.IsValid() &&
20430 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20431 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20432 (rm.GetLane() <= 1)))) {
20433 if (cond.Is(al)) {
20434 EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
20435 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20436 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20437 return;
20438 }
20439 }
20440 }
20441 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20442}
20443
20444void Assembler::vmlal(
20445 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020446 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020447 CheckIT(cond);
20448 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020449 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020450 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20451 if (encoded_dt.IsValid()) {
20452 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20453 EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
20454 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20455 rn.Encode(7, 16) | rm.Encode(5, 0));
20456 AdvanceIT();
20457 return;
20458 }
20459 }
20460 } else {
20461 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20462 if (encoded_dt.IsValid()) {
20463 if (cond.Is(al)) {
20464 EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
20465 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20466 rn.Encode(7, 16) | rm.Encode(5, 0));
20467 return;
20468 }
20469 }
20470 }
20471 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20472}
20473
20474void Assembler::vmls(
20475 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020476 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020477 CheckIT(cond);
20478 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020479 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020480 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20481 if (encoded_dt.IsValid() &&
20482 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20483 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20484 (rm.GetLane() <= 1)))) {
20485 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20486 EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20487 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20488 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20489 AdvanceIT();
20490 return;
20491 }
20492 }
20493 } else {
20494 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20495 if (encoded_dt.IsValid() &&
20496 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20497 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20498 (rm.GetLane() <= 1)))) {
20499 if (cond.Is(al)) {
20500 EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20501 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20502 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20503 return;
20504 }
20505 }
20506 }
20507 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20508}
20509
20510void Assembler::vmls(
20511 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020512 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020513 CheckIT(cond);
20514 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020515 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020516 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20517 if (encoded_dt.IsValid() &&
20518 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20519 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20520 (rm.GetLane() <= 1)))) {
20521 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20522 EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20523 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20524 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20525 AdvanceIT();
20526 return;
20527 }
20528 }
20529 } else {
20530 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20531 if (encoded_dt.IsValid() &&
20532 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20533 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20534 (rm.GetLane() <= 1)))) {
20535 if (cond.Is(al)) {
20536 EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20537 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20538 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20539 return;
20540 }
20541 }
20542 }
20543 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20544}
20545
20546void Assembler::vmls(
20547 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020548 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020549 CheckIT(cond);
20550 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020551 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020552 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20553 if (dt.Is(F32)) {
20554 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20555 EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20556 rm.Encode(5, 0));
20557 AdvanceIT();
20558 return;
20559 }
20560 }
20561 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20562 if (dt.Is(F64)) {
20563 EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20564 rm.Encode(5, 0));
20565 AdvanceIT();
20566 return;
20567 }
20568 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20569 if (encoded_dt.IsValid()) {
20570 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20571 EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
20572 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20573 AdvanceIT();
20574 return;
20575 }
20576 }
20577 } else {
20578 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20579 if (dt.Is(F32)) {
20580 if (cond.Is(al)) {
20581 EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20582 rm.Encode(5, 0));
20583 return;
20584 }
20585 }
20586 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20587 if (dt.Is(F64) && cond.IsNotNever()) {
20588 EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20589 rn.Encode(7, 16) | rm.Encode(5, 0));
20590 return;
20591 }
20592 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20593 if (encoded_dt.IsValid()) {
20594 if (cond.Is(al)) {
20595 EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
20596 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20597 return;
20598 }
20599 }
20600 }
20601 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20602}
20603
20604void Assembler::vmls(
20605 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020606 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020607 CheckIT(cond);
20608 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020609 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020610 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20611 if (dt.Is(F32)) {
20612 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20613 EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20614 rm.Encode(5, 0));
20615 AdvanceIT();
20616 return;
20617 }
20618 }
20619 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20620 if (encoded_dt.IsValid()) {
20621 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20622 EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
20623 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20624 AdvanceIT();
20625 return;
20626 }
20627 }
20628 } else {
20629 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20630 if (dt.Is(F32)) {
20631 if (cond.Is(al)) {
20632 EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20633 rm.Encode(5, 0));
20634 return;
20635 }
20636 }
20637 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20638 if (encoded_dt.IsValid()) {
20639 if (cond.Is(al)) {
20640 EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
20641 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20642 return;
20643 }
20644 }
20645 }
20646 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20647}
20648
20649void Assembler::vmls(
20650 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020651 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020652 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020653 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020654 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20655 if (dt.Is(F32)) {
20656 EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20657 rm.Encode(5, 0));
20658 AdvanceIT();
20659 return;
20660 }
20661 } else {
20662 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20663 if (dt.Is(F32) && cond.IsNotNever()) {
20664 EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20665 rn.Encode(7, 16) | rm.Encode(5, 0));
20666 return;
20667 }
20668 }
20669 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20670}
20671
20672void Assembler::vmlsl(
20673 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020674 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020675 CheckIT(cond);
20676 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020677 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020678 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20679 if (encoded_dt.IsValid() &&
20680 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20681 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20682 (rm.GetLane() <= 1)))) {
20683 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20684 EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
20685 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20686 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20687 AdvanceIT();
20688 return;
20689 }
20690 }
20691 } else {
20692 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20693 if (encoded_dt.IsValid() &&
20694 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20695 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20696 (rm.GetLane() <= 1)))) {
20697 if (cond.Is(al)) {
20698 EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
20699 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20700 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20701 return;
20702 }
20703 }
20704 }
20705 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20706}
20707
20708void Assembler::vmlsl(
20709 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020710 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020711 CheckIT(cond);
20712 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020713 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020714 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20715 if (encoded_dt.IsValid()) {
20716 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20717 EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
20718 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20719 rn.Encode(7, 16) | rm.Encode(5, 0));
20720 AdvanceIT();
20721 return;
20722 }
20723 }
20724 } else {
20725 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20726 if (encoded_dt.IsValid()) {
20727 if (cond.Is(al)) {
20728 EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
20729 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20730 rn.Encode(7, 16) | rm.Encode(5, 0));
20731 return;
20732 }
20733 }
20734 }
20735 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20736}
20737
20738void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020739 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020740 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020741 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020742 // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020743 if ((!rt.IsPC() || AllowUnpredictable())) {
20744 EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
20745 AdvanceIT();
20746 return;
20747 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020748 } else {
20749 // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020750 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020751 EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20752 rn.Encode(7, 16));
20753 return;
20754 }
20755 }
20756 Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
20757}
20758
20759void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020760 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020761 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020762 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020763 // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020764 if ((!rt.IsPC() || AllowUnpredictable())) {
20765 EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
20766 AdvanceIT();
20767 return;
20768 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020769 } else {
20770 // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020771 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020772 EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
20773 (rt.GetCode() << 12));
20774 return;
20775 }
20776 }
20777 Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
20778}
20779
20780void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020781 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020782 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020783 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020784 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020785 if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20786 EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20787 rm.Encode(5, 0));
20788 AdvanceIT();
20789 return;
20790 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020791 } else {
20792 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020793 if (cond.IsNotNever() &&
20794 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020795 EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20796 (rt2.GetCode() << 16) | rm.Encode(5, 0));
20797 return;
20798 }
20799 }
20800 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
20801}
20802
20803void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020804 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020805 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020806 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020807 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020808 if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20809 EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20810 (rt2.GetCode() << 16));
20811 AdvanceIT();
20812 return;
20813 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020814 } else {
20815 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020816 if (cond.IsNotNever() &&
20817 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020818 EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20819 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20820 return;
20821 }
20822 }
20823 Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
20824}
20825
20826void Assembler::vmov(
20827 Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020828 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020829 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020831 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020832 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20833 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020834 EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20835 rm.Encode(5, 0));
20836 AdvanceIT();
20837 return;
20838 }
20839 } else {
20840 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
20841 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000020842 cond.IsNotNever() &&
20843 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020844 EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20845 (rt2.GetCode() << 16) | rm.Encode(5, 0));
20846 return;
20847 }
20848 }
20849 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
20850}
20851
20852void Assembler::vmov(
20853 Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020854 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020855 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020856 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020857 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020858 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20859 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020860 EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20861 (rt2.GetCode() << 16));
20862 AdvanceIT();
20863 return;
20864 }
20865 } else {
20866 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
20867 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000020868 cond.IsNotNever() &&
20869 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020870 EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20871 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20872 return;
20873 }
20874 }
20875 Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
20876}
20877
20878void Assembler::vmov(Condition cond,
20879 DataType dt,
20880 DRegisterLane rd,
20881 Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020882 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020883 CheckIT(cond);
20884 Dt_opc1_opc2_1 encoded_dt(dt, rd);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020885 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020886 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020887 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020888 EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20889 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
20890 rd.Encode(7, 16) | (rt.GetCode() << 12));
20891 AdvanceIT();
20892 return;
20893 }
20894 } else {
20895 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020896 if (encoded_dt.IsValid() && cond.IsNotNever() &&
20897 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020898 EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
20899 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20900 ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
20901 (rt.GetCode() << 12));
20902 return;
20903 }
20904 }
20905 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
20906}
20907
20908void Assembler::vmov(Condition cond,
20909 DataType dt,
20910 DRegister rd,
20911 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020912 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020913 CheckIT(cond);
20914 if (operand.IsImmediate()) {
20915 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020916 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020917 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20918 if (encoded_dt.IsValid()) {
20919 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20920 EmitT32_32(
20921 0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20922 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20923 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20924 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20925 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20926 AdvanceIT();
20927 return;
20928 }
20929 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020930 } else {
20931 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20932 if (encoded_dt.IsValid()) {
20933 if (cond.Is(al)) {
20934 EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20935 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20936 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20937 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20938 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20939 return;
20940 }
20941 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070020942 }
20943 }
20944 if (operand.IsImmediate()) {
20945 ImmediateVFP vfp(operand.GetNeonImmediate());
20946 if (IsUsingT32()) {
20947 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
20948 if (dt.Is(F64) && vfp.IsValid()) {
20949 EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
20950 (vfp.GetEncodingValue() & 0xf) |
20951 ((vfp.GetEncodingValue() & 0xf0) << 12));
20952 AdvanceIT();
20953 return;
20954 }
20955 } else {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020956 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
20957 if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
20958 EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20959 (vfp.GetEncodingValue() & 0xf) |
20960 ((vfp.GetEncodingValue() & 0xf0) << 12));
20961 return;
20962 }
20963 }
20964 }
20965 if (operand.IsRegister()) {
20966 DRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020968 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
20969 if (dt.Is(F64)) {
20970 EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20971 AdvanceIT();
20972 return;
20973 }
20974 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
20975 if (!dt.Is(F64)) {
20976 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20977 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
20978 rm.Encode(5, 0));
20979 AdvanceIT();
20980 return;
20981 }
20982 }
20983 } else {
20984 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
20985 if (dt.Is(F64) && cond.IsNotNever()) {
20986 EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20987 rm.Encode(5, 0));
20988 return;
20989 }
20990 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
20991 if (!dt.Is(F64)) {
20992 if (cond.Is(al)) {
20993 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
20994 rm.Encode(5, 0));
20995 return;
20996 }
20997 }
20998 }
20999 }
21000 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21001}
21002
21003void Assembler::vmov(Condition cond,
21004 DataType dt,
21005 QRegister rd,
21006 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021007 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021008 CheckIT(cond);
21009 if (operand.IsImmediate()) {
21010 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021011 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021012 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21013 if (encoded_dt.IsValid()) {
21014 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21015 EmitT32_32(
21016 0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21017 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21018 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21019 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21020 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21021 AdvanceIT();
21022 return;
21023 }
21024 }
21025 } else {
21026 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21027 if (encoded_dt.IsValid()) {
21028 if (cond.Is(al)) {
21029 EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21030 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21031 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21032 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21033 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21034 return;
21035 }
21036 }
21037 }
21038 }
21039 if (operand.IsRegister()) {
21040 QRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021041 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021042 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21043 if (!dt.Is(F64)) {
21044 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21045 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21046 rm.Encode(5, 0));
21047 AdvanceIT();
21048 return;
21049 }
21050 }
21051 } else {
21052 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21053 if (!dt.Is(F64)) {
21054 if (cond.Is(al)) {
21055 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21056 rm.Encode(5, 0));
21057 return;
21058 }
21059 }
21060 }
21061 }
21062 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21063}
21064
21065void Assembler::vmov(Condition cond,
21066 DataType dt,
21067 SRegister rd,
21068 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021069 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021070 CheckIT(cond);
21071 if (operand.IsImmediate()) {
21072 ImmediateVFP vfp(operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021074 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
21075 if (dt.Is(F32) && vfp.IsValid()) {
21076 EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
21077 (vfp.GetEncodingValue() & 0xf) |
21078 ((vfp.GetEncodingValue() & 0xf0) << 12));
21079 AdvanceIT();
21080 return;
21081 }
21082 } else {
21083 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
21084 if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
21085 EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21086 (vfp.GetEncodingValue() & 0xf) |
21087 ((vfp.GetEncodingValue() & 0xf0) << 12));
21088 return;
21089 }
21090 }
21091 }
21092 if (operand.IsRegister()) {
21093 SRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021094 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021095 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21096 if (dt.Is(F32)) {
21097 EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21098 AdvanceIT();
21099 return;
21100 }
21101 } else {
21102 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21103 if (dt.Is(F32) && cond.IsNotNever()) {
21104 EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21105 rm.Encode(5, 0));
21106 return;
21107 }
21108 }
21109 }
21110 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21111}
21112
21113void Assembler::vmov(Condition cond,
21114 DataType dt,
21115 Register rt,
21116 DRegisterLane rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021117 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021118 CheckIT(cond);
21119 Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021120 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021121 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021122 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021123 EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21124 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21125 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21126 (rt.GetCode() << 12) | rn.Encode(7, 16));
21127 AdvanceIT();
21128 return;
21129 }
21130 } else {
21131 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021132 if (encoded_dt.IsValid() && cond.IsNotNever() &&
21133 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021134 EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
21135 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21136 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21137 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21138 (rt.GetCode() << 12) | rn.Encode(7, 16));
21139 return;
21140 }
21141 }
21142 Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
21143}
21144
21145void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021146 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021147 CheckIT(cond);
21148 Dt_U_imm3H_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021149 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021150 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
21151 if (encoded_dt.IsValid()) {
21152 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21153 EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21154 ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
21155 rd.Encode(22, 12) | rm.Encode(5, 0));
21156 AdvanceIT();
21157 return;
21158 }
21159 }
21160 } else {
21161 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
21162 if (encoded_dt.IsValid()) {
21163 if (cond.Is(al)) {
21164 EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21165 ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
21166 rd.Encode(22, 12) | rm.Encode(5, 0));
21167 return;
21168 }
21169 }
21170 }
21171 Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
21172}
21173
21174void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021175 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021176 CheckIT(cond);
21177 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021178 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021179 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21180 if (encoded_dt.IsValid()) {
21181 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21182 EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
21183 rd.Encode(22, 12) | rm.Encode(5, 0));
21184 AdvanceIT();
21185 return;
21186 }
21187 }
21188 } else {
21189 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21190 if (encoded_dt.IsValid()) {
21191 if (cond.Is(al)) {
21192 EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
21193 rd.Encode(22, 12) | rm.Encode(5, 0));
21194 return;
21195 }
21196 }
21197 }
21198 Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
21199}
21200
21201void Assembler::vmrs(Condition cond,
21202 RegisterOrAPSR_nzcv rt,
21203 SpecialFPRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021204 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021205 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021206 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021207 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
21208 EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
21209 AdvanceIT();
21210 return;
21211 } else {
21212 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
21213 if (cond.IsNotNever()) {
21214 EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
21215 (spec_reg.GetReg() << 16));
21216 return;
21217 }
21218 }
21219 Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
21220}
21221
21222void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021223 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021224 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021225 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021226 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021227 if ((!rt.IsPC() || AllowUnpredictable())) {
21228 EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) |
21229 (rt.GetCode() << 12));
21230 AdvanceIT();
21231 return;
21232 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010021233 } else {
21234 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021235 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021236 EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
21237 (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
21238 return;
21239 }
21240 }
21241 Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
21242}
21243
21244void Assembler::vmul(Condition cond,
21245 DataType dt,
21246 DRegister rd,
21247 DRegister rn,
21248 DRegister dm,
21249 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021250 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021251 CheckIT(cond);
21252 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021253 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021254 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
21255 if (encoded_dt.IsValid() &&
21256 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021257 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021258 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21259 uint32_t shift = 4;
21260 if (dt.Is(I16)) {
21261 shift = 3;
21262 }
21263 uint32_t mvm = dm.GetCode() | index << shift;
21264 EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21265 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21266 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21267 ((mvm & 0x10) << 1));
21268 AdvanceIT();
21269 return;
21270 }
21271 }
21272 } else {
21273 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
21274 if (encoded_dt.IsValid() &&
21275 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021276 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021277 if (cond.Is(al)) {
21278 uint32_t shift = 4;
21279 if (dt.Is(I16)) {
21280 shift = 3;
21281 }
21282 uint32_t mvm = dm.GetCode() | index << shift;
21283 EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21284 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21285 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21286 ((mvm & 0x10) << 1));
21287 return;
21288 }
21289 }
21290 }
21291 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21292}
21293
21294void Assembler::vmul(Condition cond,
21295 DataType dt,
21296 QRegister rd,
21297 QRegister rn,
21298 DRegister dm,
21299 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021300 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021301 CheckIT(cond);
21302 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021303 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021304 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
21305 if (encoded_dt.IsValid() &&
21306 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021307 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021308 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21309 uint32_t shift = 4;
21310 if (dt.Is(I16)) {
21311 shift = 3;
21312 }
21313 uint32_t mvm = dm.GetCode() | index << shift;
21314 EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21315 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21316 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21317 ((mvm & 0x10) << 1));
21318 AdvanceIT();
21319 return;
21320 }
21321 }
21322 } else {
21323 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
21324 if (encoded_dt.IsValid() &&
21325 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021326 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021327 if (cond.Is(al)) {
21328 uint32_t shift = 4;
21329 if (dt.Is(I16)) {
21330 shift = 3;
21331 }
21332 uint32_t mvm = dm.GetCode() | index << shift;
21333 EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21334 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21335 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21336 ((mvm & 0x10) << 1));
21337 return;
21338 }
21339 }
21340 }
21341 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21342}
21343
21344void Assembler::vmul(
21345 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021346 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021347 CheckIT(cond);
21348 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021349 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021350 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21351 if (dt.Is(F32)) {
21352 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21353 EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21354 rm.Encode(5, 0));
21355 AdvanceIT();
21356 return;
21357 }
21358 }
21359 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
21360 if (dt.Is(F64)) {
21361 EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21362 rm.Encode(5, 0));
21363 AdvanceIT();
21364 return;
21365 }
21366 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21367 if (encoded_dt.IsValid()) {
21368 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21369 EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21370 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21371 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21372 AdvanceIT();
21373 return;
21374 }
21375 }
21376 } else {
21377 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21378 if (dt.Is(F32)) {
21379 if (cond.Is(al)) {
21380 EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21381 rm.Encode(5, 0));
21382 return;
21383 }
21384 }
21385 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
21386 if (dt.Is(F64) && cond.IsNotNever()) {
21387 EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21388 rn.Encode(7, 16) | rm.Encode(5, 0));
21389 return;
21390 }
21391 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21392 if (encoded_dt.IsValid()) {
21393 if (cond.Is(al)) {
21394 EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21395 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21396 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21397 return;
21398 }
21399 }
21400 }
21401 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21402}
21403
21404void Assembler::vmul(
21405 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021406 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021407 CheckIT(cond);
21408 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021409 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021410 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
21411 if (dt.Is(F32)) {
21412 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21413 EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21414 rm.Encode(5, 0));
21415 AdvanceIT();
21416 return;
21417 }
21418 }
21419 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21420 if (encoded_dt.IsValid()) {
21421 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21422 EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21423 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21424 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21425 AdvanceIT();
21426 return;
21427 }
21428 }
21429 } else {
21430 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
21431 if (dt.Is(F32)) {
21432 if (cond.Is(al)) {
21433 EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21434 rm.Encode(5, 0));
21435 return;
21436 }
21437 }
21438 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21439 if (encoded_dt.IsValid()) {
21440 if (cond.Is(al)) {
21441 EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21442 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21443 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21444 return;
21445 }
21446 }
21447 }
21448 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21449}
21450
21451void Assembler::vmul(
21452 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021453 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021454 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021455 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021456 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
21457 if (dt.Is(F32)) {
21458 EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21459 rm.Encode(5, 0));
21460 AdvanceIT();
21461 return;
21462 }
21463 } else {
21464 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
21465 if (dt.Is(F32) && cond.IsNotNever()) {
21466 EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21467 rn.Encode(7, 16) | rm.Encode(5, 0));
21468 return;
21469 }
21470 }
21471 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21472}
21473
21474void Assembler::vmull(Condition cond,
21475 DataType dt,
21476 QRegister rd,
21477 DRegister rn,
21478 DRegister dm,
21479 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021480 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021481 CheckIT(cond);
21482 Dt_U_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021483 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021484 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
21485 if (encoded_dt.IsValid() &&
21486 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021487 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21488 (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021489 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21490 uint32_t shift = 4;
21491 if (dt.Is(S16) || dt.Is(U16)) {
21492 shift = 3;
21493 }
21494 uint32_t mvm = dm.GetCode() | index << shift;
21495 EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21496 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21497 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21498 ((mvm & 0x10) << 1));
21499 AdvanceIT();
21500 return;
21501 }
21502 }
21503 } else {
21504 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
21505 if (encoded_dt.IsValid() &&
21506 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021507 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21508 (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021509 if (cond.Is(al)) {
21510 uint32_t shift = 4;
21511 if (dt.Is(S16) || dt.Is(U16)) {
21512 shift = 3;
21513 }
21514 uint32_t mvm = dm.GetCode() | index << shift;
21515 EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21516 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21517 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21518 ((mvm & 0x10) << 1));
21519 return;
21520 }
21521 }
21522 }
21523 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
21524}
21525
21526void Assembler::vmull(
21527 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021528 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021529 CheckIT(cond);
21530 Dt_op_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021531 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021532 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21533 if (encoded_dt.IsValid()) {
21534 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21535 EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21536 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21537 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21538 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21539 AdvanceIT();
21540 return;
21541 }
21542 }
21543 } else {
21544 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21545 if (encoded_dt.IsValid()) {
21546 if (cond.Is(al)) {
21547 EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21548 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21549 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21550 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21551 return;
21552 }
21553 }
21554 }
21555 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
21556}
21557
21558void Assembler::vmvn(Condition cond,
21559 DataType dt,
21560 DRegister rd,
21561 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021562 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021563 CheckIT(cond);
21564 if (operand.IsImmediate()) {
21565 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021566 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021567 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
21568 if (encoded_dt.IsValid()) {
21569 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21570 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
21571 rd.Encode(22, 12) |
21572 (encoded_dt.GetEncodedImmediate() & 0xf) |
21573 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21574 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21575 AdvanceIT();
21576 return;
21577 }
21578 }
21579 } else {
21580 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
21581 if (encoded_dt.IsValid()) {
21582 if (cond.Is(al)) {
21583 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
21584 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21585 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21586 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21587 return;
21588 }
21589 }
21590 }
21591 }
21592 if (operand.IsRegister()) {
21593 DRegister rm = operand.GetRegister();
21594 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021595 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021596 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21597 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21598 EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21599 AdvanceIT();
21600 return;
21601 }
21602 } else {
21603 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21604 if (cond.Is(al)) {
21605 EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21606 return;
21607 }
21608 }
21609 }
21610 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21611}
21612
21613void Assembler::vmvn(Condition cond,
21614 DataType dt,
21615 QRegister rd,
21616 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021617 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021618 CheckIT(cond);
21619 if (operand.IsImmediate()) {
21620 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021621 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021622 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21623 if (encoded_dt.IsValid()) {
21624 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21625 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
21626 rd.Encode(22, 12) |
21627 (encoded_dt.GetEncodedImmediate() & 0xf) |
21628 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21629 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21630 AdvanceIT();
21631 return;
21632 }
21633 }
21634 } else {
21635 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21636 if (encoded_dt.IsValid()) {
21637 if (cond.Is(al)) {
21638 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
21639 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21640 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21641 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21642 return;
21643 }
21644 }
21645 }
21646 }
21647 if (operand.IsRegister()) {
21648 QRegister rm = operand.GetRegister();
21649 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021650 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021651 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21652 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21653 EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21654 AdvanceIT();
21655 return;
21656 }
21657 } else {
21658 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21659 if (cond.Is(al)) {
21660 EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21661 return;
21662 }
21663 }
21664 }
21665 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21666}
21667
21668void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021669 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021670 CheckIT(cond);
21671 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021673 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21674 if (encoded_dt.IsValid()) {
21675 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21676 EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21677 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21678 rd.Encode(22, 12) | rm.Encode(5, 0));
21679 AdvanceIT();
21680 return;
21681 }
21682 }
21683 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21684 if (dt.Is(F64)) {
21685 EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21686 AdvanceIT();
21687 return;
21688 }
21689 } else {
21690 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21691 if (encoded_dt.IsValid()) {
21692 if (cond.Is(al)) {
21693 EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21694 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21695 rd.Encode(22, 12) | rm.Encode(5, 0));
21696 return;
21697 }
21698 }
21699 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21700 if (dt.Is(F64) && cond.IsNotNever()) {
21701 EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21702 rm.Encode(5, 0));
21703 return;
21704 }
21705 }
21706 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21707}
21708
21709void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021710 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021711 CheckIT(cond);
21712 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021713 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021714 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21715 if (encoded_dt.IsValid()) {
21716 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21717 EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21718 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21719 rd.Encode(22, 12) | rm.Encode(5, 0));
21720 AdvanceIT();
21721 return;
21722 }
21723 }
21724 } else {
21725 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21726 if (encoded_dt.IsValid()) {
21727 if (cond.Is(al)) {
21728 EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21729 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21730 rd.Encode(22, 12) | rm.Encode(5, 0));
21731 return;
21732 }
21733 }
21734 }
21735 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21736}
21737
21738void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021739 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021740 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021741 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021742 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21743 if (dt.Is(F32)) {
21744 EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21745 AdvanceIT();
21746 return;
21747 }
21748 } else {
21749 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21750 if (dt.Is(F32) && cond.IsNotNever()) {
21751 EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21752 rm.Encode(5, 0));
21753 return;
21754 }
21755 }
21756 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21757}
21758
21759void Assembler::vnmla(
21760 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021761 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021762 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021763 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021764 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21765 if (dt.Is(F32)) {
21766 EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21767 rm.Encode(5, 0));
21768 AdvanceIT();
21769 return;
21770 }
21771 } else {
21772 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21773 if (dt.Is(F32) && cond.IsNotNever()) {
21774 EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21775 rn.Encode(7, 16) | rm.Encode(5, 0));
21776 return;
21777 }
21778 }
21779 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21780}
21781
21782void Assembler::vnmla(
21783 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021784 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021785 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021786 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021787 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21788 if (dt.Is(F64)) {
21789 EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21790 rm.Encode(5, 0));
21791 AdvanceIT();
21792 return;
21793 }
21794 } else {
21795 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21796 if (dt.Is(F64) && cond.IsNotNever()) {
21797 EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21798 rn.Encode(7, 16) | rm.Encode(5, 0));
21799 return;
21800 }
21801 }
21802 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21803}
21804
21805void Assembler::vnmls(
21806 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021807 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021808 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021809 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021810 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21811 if (dt.Is(F32)) {
21812 EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21813 rm.Encode(5, 0));
21814 AdvanceIT();
21815 return;
21816 }
21817 } else {
21818 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21819 if (dt.Is(F32) && cond.IsNotNever()) {
21820 EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21821 rn.Encode(7, 16) | rm.Encode(5, 0));
21822 return;
21823 }
21824 }
21825 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21826}
21827
21828void Assembler::vnmls(
21829 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021830 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021831 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021833 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21834 if (dt.Is(F64)) {
21835 EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21836 rm.Encode(5, 0));
21837 AdvanceIT();
21838 return;
21839 }
21840 } else {
21841 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21842 if (dt.Is(F64) && cond.IsNotNever()) {
21843 EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21844 rn.Encode(7, 16) | rm.Encode(5, 0));
21845 return;
21846 }
21847 }
21848 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21849}
21850
21851void Assembler::vnmul(
21852 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021853 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021854 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021855 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021856 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
21857 if (dt.Is(F32)) {
21858 EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21859 rm.Encode(5, 0));
21860 AdvanceIT();
21861 return;
21862 }
21863 } else {
21864 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
21865 if (dt.Is(F32) && cond.IsNotNever()) {
21866 EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21867 rn.Encode(7, 16) | rm.Encode(5, 0));
21868 return;
21869 }
21870 }
21871 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21872}
21873
21874void Assembler::vnmul(
21875 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021876 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021877 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021878 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021879 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
21880 if (dt.Is(F64)) {
21881 EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21882 rm.Encode(5, 0));
21883 AdvanceIT();
21884 return;
21885 }
21886 } else {
21887 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
21888 if (dt.Is(F64) && cond.IsNotNever()) {
21889 EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21890 rn.Encode(7, 16) | rm.Encode(5, 0));
21891 return;
21892 }
21893 }
21894 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21895}
21896
21897void Assembler::vorn(Condition cond,
21898 DataType dt,
21899 DRegister rd,
21900 DRegister rn,
21901 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021902 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021903 CheckIT(cond);
21904 if (operand.IsImmediate()) {
21905 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021906 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021907 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
21908 if (encoded_dt.IsValid() && rd.Is(rn)) {
21909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21910 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
21911 rd.Encode(22, 12) |
21912 (encoded_dt.GetEncodedImmediate() & 0xf) |
21913 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21914 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21915 AdvanceIT();
21916 return;
21917 }
21918 }
21919 } else {
21920 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
21921 if (encoded_dt.IsValid() && rd.Is(rn)) {
21922 if (cond.Is(al)) {
21923 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
21924 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21925 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21926 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21927 return;
21928 }
21929 }
21930 }
21931 }
21932 if (operand.IsRegister()) {
21933 DRegister rm = operand.GetRegister();
21934 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021936 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
21937 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21938 EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21939 rm.Encode(5, 0));
21940 AdvanceIT();
21941 return;
21942 }
21943 } else {
21944 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
21945 if (cond.Is(al)) {
21946 EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21947 rm.Encode(5, 0));
21948 return;
21949 }
21950 }
21951 }
21952 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
21953}
21954
21955void Assembler::vorn(Condition cond,
21956 DataType dt,
21957 QRegister rd,
21958 QRegister rn,
21959 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021960 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021961 CheckIT(cond);
21962 if (operand.IsImmediate()) {
21963 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021964 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021965 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
21966 if (encoded_dt.IsValid() && rd.Is(rn)) {
21967 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21968 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
21969 rd.Encode(22, 12) |
21970 (encoded_dt.GetEncodedImmediate() & 0xf) |
21971 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21972 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21973 AdvanceIT();
21974 return;
21975 }
21976 }
21977 } else {
21978 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
21979 if (encoded_dt.IsValid() && rd.Is(rn)) {
21980 if (cond.Is(al)) {
21981 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
21982 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21983 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21984 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21985 return;
21986 }
21987 }
21988 }
21989 }
21990 if (operand.IsRegister()) {
21991 QRegister rm = operand.GetRegister();
21992 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021993 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021994 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
21995 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21996 EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21997 rm.Encode(5, 0));
21998 AdvanceIT();
21999 return;
22000 }
22001 } else {
22002 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22003 if (cond.Is(al)) {
22004 EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22005 rm.Encode(5, 0));
22006 return;
22007 }
22008 }
22009 }
22010 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
22011}
22012
22013void Assembler::vorr(Condition cond,
22014 DataType dt,
22015 DRegister rd,
22016 DRegister rn,
22017 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022018 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022019 CheckIT(cond);
22020 if (operand.IsRegister()) {
22021 DRegister rm = operand.GetRegister();
22022 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022023 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022024 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
22025 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22026 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22027 rm.Encode(5, 0));
22028 AdvanceIT();
22029 return;
22030 }
22031 } else {
22032 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
22033 if (cond.Is(al)) {
22034 EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22035 rm.Encode(5, 0));
22036 return;
22037 }
22038 }
22039 }
22040 if (operand.IsImmediate()) {
22041 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022042 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022043 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
22044 if (encoded_dt.IsValid() && rd.Is(rn)) {
22045 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22046 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
22047 rd.Encode(22, 12) |
22048 (encoded_dt.GetEncodedImmediate() & 0xf) |
22049 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22050 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22051 AdvanceIT();
22052 return;
22053 }
22054 }
22055 } else {
22056 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
22057 if (encoded_dt.IsValid() && rd.Is(rn)) {
22058 if (cond.Is(al)) {
22059 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
22060 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22061 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22062 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22063 return;
22064 }
22065 }
22066 }
22067 }
22068 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22069}
22070
22071void Assembler::vorr(Condition cond,
22072 DataType dt,
22073 QRegister rd,
22074 QRegister rn,
22075 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022076 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022077 CheckIT(cond);
22078 if (operand.IsRegister()) {
22079 QRegister rm = operand.GetRegister();
22080 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022081 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022082 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22083 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22084 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22085 rm.Encode(5, 0));
22086 AdvanceIT();
22087 return;
22088 }
22089 } else {
22090 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22091 if (cond.Is(al)) {
22092 EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22093 rm.Encode(5, 0));
22094 return;
22095 }
22096 }
22097 }
22098 if (operand.IsImmediate()) {
22099 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022100 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022101 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22102 if (encoded_dt.IsValid() && rd.Is(rn)) {
22103 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22104 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22105 rd.Encode(22, 12) |
22106 (encoded_dt.GetEncodedImmediate() & 0xf) |
22107 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22108 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22109 AdvanceIT();
22110 return;
22111 }
22112 }
22113 } else {
22114 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22115 if (encoded_dt.IsValid() && rd.Is(rn)) {
22116 if (cond.Is(al)) {
22117 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22118 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22119 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22120 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22121 return;
22122 }
22123 }
22124 }
22125 }
22126 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22127}
22128
22129void Assembler::vpadal(Condition cond,
22130 DataType dt,
22131 DRegister rd,
22132 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022133 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022134 CheckIT(cond);
22135 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022136 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022137 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22138 if (encoded_dt.IsValid()) {
22139 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22140 EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22141 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22142 rd.Encode(22, 12) | rm.Encode(5, 0));
22143 AdvanceIT();
22144 return;
22145 }
22146 }
22147 } else {
22148 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22149 if (encoded_dt.IsValid()) {
22150 if (cond.Is(al)) {
22151 EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22152 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22153 rd.Encode(22, 12) | rm.Encode(5, 0));
22154 return;
22155 }
22156 }
22157 }
22158 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22159}
22160
22161void Assembler::vpadal(Condition cond,
22162 DataType dt,
22163 QRegister rd,
22164 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022165 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022166 CheckIT(cond);
22167 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022168 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022169 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22170 if (encoded_dt.IsValid()) {
22171 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22172 EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22173 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22174 rd.Encode(22, 12) | rm.Encode(5, 0));
22175 AdvanceIT();
22176 return;
22177 }
22178 }
22179 } else {
22180 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22181 if (encoded_dt.IsValid()) {
22182 if (cond.Is(al)) {
22183 EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22184 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22185 rd.Encode(22, 12) | rm.Encode(5, 0));
22186 return;
22187 }
22188 }
22189 }
22190 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22191}
22192
22193void Assembler::vpadd(
22194 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022195 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022196 CheckIT(cond);
22197 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022198 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022199 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22200 if (dt.Is(F32)) {
22201 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22202 EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22203 rm.Encode(5, 0));
22204 AdvanceIT();
22205 return;
22206 }
22207 }
22208 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22209 if (encoded_dt.IsValid()) {
22210 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22211 EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
22212 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22213 AdvanceIT();
22214 return;
22215 }
22216 }
22217 } else {
22218 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22219 if (dt.Is(F32)) {
22220 if (cond.Is(al)) {
22221 EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22222 rm.Encode(5, 0));
22223 return;
22224 }
22225 }
22226 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22227 if (encoded_dt.IsValid()) {
22228 if (cond.Is(al)) {
22229 EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
22230 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22231 return;
22232 }
22233 }
22234 }
22235 Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
22236}
22237
22238void Assembler::vpaddl(Condition cond,
22239 DataType dt,
22240 DRegister rd,
22241 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022243 CheckIT(cond);
22244 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022245 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022246 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22247 if (encoded_dt.IsValid()) {
22248 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22249 EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22250 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22251 rd.Encode(22, 12) | rm.Encode(5, 0));
22252 AdvanceIT();
22253 return;
22254 }
22255 }
22256 } else {
22257 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22258 if (encoded_dt.IsValid()) {
22259 if (cond.Is(al)) {
22260 EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22261 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22262 rd.Encode(22, 12) | rm.Encode(5, 0));
22263 return;
22264 }
22265 }
22266 }
22267 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22268}
22269
22270void Assembler::vpaddl(Condition cond,
22271 DataType dt,
22272 QRegister rd,
22273 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022274 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022275 CheckIT(cond);
22276 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022277 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022278 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22279 if (encoded_dt.IsValid()) {
22280 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22281 EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22282 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22283 rd.Encode(22, 12) | rm.Encode(5, 0));
22284 AdvanceIT();
22285 return;
22286 }
22287 }
22288 } else {
22289 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22290 if (encoded_dt.IsValid()) {
22291 if (cond.Is(al)) {
22292 EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22293 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22294 rd.Encode(22, 12) | rm.Encode(5, 0));
22295 return;
22296 }
22297 }
22298 }
22299 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22300}
22301
22302void Assembler::vpmax(
22303 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022304 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022305 CheckIT(cond);
22306 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022307 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022308 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22309 if (dt.Is(F32)) {
22310 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22311 EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22312 rm.Encode(5, 0));
22313 AdvanceIT();
22314 return;
22315 }
22316 }
22317 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22318 if (encoded_dt.IsValid()) {
22319 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22320 EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22321 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22322 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22323 AdvanceIT();
22324 return;
22325 }
22326 }
22327 } else {
22328 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22329 if (dt.Is(F32)) {
22330 if (cond.Is(al)) {
22331 EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22332 rm.Encode(5, 0));
22333 return;
22334 }
22335 }
22336 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22337 if (encoded_dt.IsValid()) {
22338 if (cond.Is(al)) {
22339 EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22340 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22341 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22342 return;
22343 }
22344 }
22345 }
22346 Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
22347}
22348
22349void Assembler::vpmin(
22350 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022351 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022352 CheckIT(cond);
22353 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022354 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022355 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22356 if (dt.Is(F32)) {
22357 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22358 EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22359 rm.Encode(5, 0));
22360 AdvanceIT();
22361 return;
22362 }
22363 }
22364 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22365 if (encoded_dt.IsValid()) {
22366 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22367 EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22368 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22369 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22370 AdvanceIT();
22371 return;
22372 }
22373 }
22374 } else {
22375 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22376 if (dt.Is(F32)) {
22377 if (cond.Is(al)) {
22378 EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22379 rm.Encode(5, 0));
22380 return;
22381 }
22382 }
22383 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22384 if (encoded_dt.IsValid()) {
22385 if (cond.Is(al)) {
22386 EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22387 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22388 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22389 return;
22390 }
22391 }
22392 }
22393 Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
22394}
22395
22396void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022397 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022398 CheckIT(cond);
22399 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022400 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022401 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080022402 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022403 const DRegister& dreg = dreglist.GetFirstDRegister();
22404 unsigned len = dreglist.GetLength() * 2;
22405 EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
22406 AdvanceIT();
22407 return;
22408 }
22409 } else {
22410 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
22411 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080022412 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022413 const DRegister& dreg = dreglist.GetFirstDRegister();
22414 unsigned len = dreglist.GetLength() * 2;
22415 EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22416 (len & 0xff));
22417 return;
22418 }
22419 }
22420 Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
22421}
22422
22423void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022424 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022425 CheckIT(cond);
22426 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022427 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022428 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
22429 const SRegister& sreg = sreglist.GetFirstSRegister();
22430 unsigned len = sreglist.GetLength();
22431 EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
22432 AdvanceIT();
22433 return;
22434 } else {
22435 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
22436 if (cond.IsNotNever()) {
22437 const SRegister& sreg = sreglist.GetFirstSRegister();
22438 unsigned len = sreglist.GetLength();
22439 EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22440 (len & 0xff));
22441 return;
22442 }
22443 }
22444 Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
22445}
22446
22447void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022448 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022449 CheckIT(cond);
22450 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022451 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022452 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080022453 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022454 const DRegister& dreg = dreglist.GetFirstDRegister();
22455 unsigned len = dreglist.GetLength() * 2;
22456 EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
22457 AdvanceIT();
22458 return;
22459 }
22460 } else {
22461 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
22462 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080022463 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022464 const DRegister& dreg = dreglist.GetFirstDRegister();
22465 unsigned len = dreglist.GetLength() * 2;
22466 EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22467 (len & 0xff));
22468 return;
22469 }
22470 }
22471 Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
22472}
22473
22474void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022475 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022476 CheckIT(cond);
22477 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022478 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022479 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
22480 const SRegister& sreg = sreglist.GetFirstSRegister();
22481 unsigned len = sreglist.GetLength();
22482 EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
22483 AdvanceIT();
22484 return;
22485 } else {
22486 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
22487 if (cond.IsNotNever()) {
22488 const SRegister& sreg = sreglist.GetFirstSRegister();
22489 unsigned len = sreglist.GetLength();
22490 EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22491 (len & 0xff));
22492 return;
22493 }
22494 }
22495 Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
22496}
22497
22498void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022499 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022500 CheckIT(cond);
22501 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022502 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022503 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22504 if (encoded_dt.IsValid()) {
22505 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22506 EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
22507 rd.Encode(22, 12) | rm.Encode(5, 0));
22508 AdvanceIT();
22509 return;
22510 }
22511 }
22512 } else {
22513 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22514 if (encoded_dt.IsValid()) {
22515 if (cond.Is(al)) {
22516 EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
22517 rd.Encode(22, 12) | rm.Encode(5, 0));
22518 return;
22519 }
22520 }
22521 }
22522 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22523}
22524
22525void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022526 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022527 CheckIT(cond);
22528 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022529 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022530 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22531 if (encoded_dt.IsValid()) {
22532 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22533 EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
22534 rd.Encode(22, 12) | rm.Encode(5, 0));
22535 AdvanceIT();
22536 return;
22537 }
22538 }
22539 } else {
22540 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22541 if (encoded_dt.IsValid()) {
22542 if (cond.Is(al)) {
22543 EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
22544 rd.Encode(22, 12) | rm.Encode(5, 0));
22545 return;
22546 }
22547 }
22548 }
22549 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22550}
22551
22552void Assembler::vqadd(
22553 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022554 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022555 CheckIT(cond);
22556 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022557 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022558 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22559 if (encoded_dt.IsValid()) {
22560 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22561 EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22562 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22563 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22564 AdvanceIT();
22565 return;
22566 }
22567 }
22568 } else {
22569 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22570 if (encoded_dt.IsValid()) {
22571 if (cond.Is(al)) {
22572 EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22573 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22574 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22575 return;
22576 }
22577 }
22578 }
22579 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22580}
22581
22582void Assembler::vqadd(
22583 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022584 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022585 CheckIT(cond);
22586 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022587 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022588 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22589 if (encoded_dt.IsValid()) {
22590 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22591 EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22592 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22593 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22594 AdvanceIT();
22595 return;
22596 }
22597 }
22598 } else {
22599 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22600 if (encoded_dt.IsValid()) {
22601 if (cond.Is(al)) {
22602 EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22603 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22604 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22605 return;
22606 }
22607 }
22608 }
22609 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22610}
22611
22612void Assembler::vqdmlal(
22613 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022614 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022615 CheckIT(cond);
22616 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022617 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022618 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22619 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22620 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22621 EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
22622 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22623 AdvanceIT();
22624 return;
22625 }
22626 }
22627 } else {
22628 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22629 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22630 if (cond.Is(al)) {
22631 EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
22632 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22633 return;
22634 }
22635 }
22636 }
22637 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
22638}
22639
22640void Assembler::vqdmlal(Condition cond,
22641 DataType dt,
22642 QRegister rd,
22643 DRegister rn,
22644 DRegister dm,
22645 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022646 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022647 CheckIT(cond);
22648 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022649 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022650 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22651 if (encoded_dt.IsValid() &&
22652 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022653 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022654 (dt.Is(S16) || dt.Is(S32))) {
22655 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22656 uint32_t shift = 4;
22657 if (dt.Is(S16)) {
22658 shift = 3;
22659 }
22660 uint32_t mvm = dm.GetCode() | index << shift;
22661 EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
22662 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22663 ((mvm & 0x10) << 1));
22664 AdvanceIT();
22665 return;
22666 }
22667 }
22668 } else {
22669 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22670 if (encoded_dt.IsValid() &&
22671 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022672 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022673 (dt.Is(S16) || dt.Is(S32))) {
22674 if (cond.Is(al)) {
22675 uint32_t shift = 4;
22676 if (dt.Is(S16)) {
22677 shift = 3;
22678 }
22679 uint32_t mvm = dm.GetCode() | index << shift;
22680 EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
22681 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22682 ((mvm & 0x10) << 1));
22683 return;
22684 }
22685 }
22686 }
22687 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
22688}
22689
22690void Assembler::vqdmlsl(
22691 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022692 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022693 CheckIT(cond);
22694 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022695 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022696 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22697 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22698 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22699 EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
22700 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22701 AdvanceIT();
22702 return;
22703 }
22704 }
22705 } else {
22706 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22707 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22708 if (cond.Is(al)) {
22709 EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
22710 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22711 return;
22712 }
22713 }
22714 }
22715 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
22716}
22717
22718void Assembler::vqdmlsl(Condition cond,
22719 DataType dt,
22720 QRegister rd,
22721 DRegister rn,
22722 DRegister dm,
22723 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022724 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022725 CheckIT(cond);
22726 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022727 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022728 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22729 if (encoded_dt.IsValid() &&
22730 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022731 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022732 (dt.Is(S16) || dt.Is(S32))) {
22733 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22734 uint32_t shift = 4;
22735 if (dt.Is(S16)) {
22736 shift = 3;
22737 }
22738 uint32_t mvm = dm.GetCode() | index << shift;
22739 EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
22740 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22741 ((mvm & 0x10) << 1));
22742 AdvanceIT();
22743 return;
22744 }
22745 }
22746 } else {
22747 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22748 if (encoded_dt.IsValid() &&
22749 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022750 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022751 (dt.Is(S16) || dt.Is(S32))) {
22752 if (cond.Is(al)) {
22753 uint32_t shift = 4;
22754 if (dt.Is(S16)) {
22755 shift = 3;
22756 }
22757 uint32_t mvm = dm.GetCode() | index << shift;
22758 EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
22759 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22760 ((mvm & 0x10) << 1));
22761 return;
22762 }
22763 }
22764 }
22765 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
22766}
22767
22768void Assembler::vqdmulh(
22769 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022770 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022771 CheckIT(cond);
22772 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022773 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022774 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22775 if (encoded_dt.IsValid()) {
22776 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22777 EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
22778 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22779 AdvanceIT();
22780 return;
22781 }
22782 }
22783 } else {
22784 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22785 if (encoded_dt.IsValid()) {
22786 if (cond.Is(al)) {
22787 EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
22788 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22789 return;
22790 }
22791 }
22792 }
22793 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22794}
22795
22796void Assembler::vqdmulh(
22797 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022798 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022799 CheckIT(cond);
22800 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022801 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022802 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22803 if (encoded_dt.IsValid()) {
22804 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22805 EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
22806 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22807 AdvanceIT();
22808 return;
22809 }
22810 }
22811 } else {
22812 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22813 if (encoded_dt.IsValid()) {
22814 if (cond.Is(al)) {
22815 EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
22816 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22817 return;
22818 }
22819 }
22820 }
22821 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22822}
22823
22824void Assembler::vqdmulh(
22825 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022826 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022827 CheckIT(cond);
22828 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022829 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022830 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
22831 if (encoded_dt.IsValid() &&
22832 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22833 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22834 (rm.GetLane() <= 1))) &&
22835 (dt.Is(S16) || dt.Is(S32))) {
22836 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22837 EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
22838 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22839 AdvanceIT();
22840 return;
22841 }
22842 }
22843 } else {
22844 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
22845 if (encoded_dt.IsValid() &&
22846 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22847 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22848 (rm.GetLane() <= 1))) &&
22849 (dt.Is(S16) || dt.Is(S32))) {
22850 if (cond.Is(al)) {
22851 EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
22852 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22853 return;
22854 }
22855 }
22856 }
22857 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22858}
22859
22860void Assembler::vqdmulh(
22861 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022863 CheckIT(cond);
22864 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022865 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022866 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
22867 if (encoded_dt.IsValid() &&
22868 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22869 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22870 (rm.GetLane() <= 1))) &&
22871 (dt.Is(S16) || dt.Is(S32))) {
22872 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22873 EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
22874 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22875 AdvanceIT();
22876 return;
22877 }
22878 }
22879 } else {
22880 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
22881 if (encoded_dt.IsValid() &&
22882 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22883 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22884 (rm.GetLane() <= 1))) &&
22885 (dt.Is(S16) || dt.Is(S32))) {
22886 if (cond.Is(al)) {
22887 EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
22888 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22889 return;
22890 }
22891 }
22892 }
22893 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22894}
22895
22896void Assembler::vqdmull(
22897 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022898 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022899 CheckIT(cond);
22900 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022901 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022902 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22903 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22904 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22905 EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
22906 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22907 AdvanceIT();
22908 return;
22909 }
22910 }
22911 } else {
22912 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22913 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22914 if (cond.Is(al)) {
22915 EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
22916 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22917 return;
22918 }
22919 }
22920 }
22921 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22922}
22923
22924void Assembler::vqdmull(
22925 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022926 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022927 CheckIT(cond);
22928 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022929 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022930 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
22931 if (encoded_dt.IsValid() &&
22932 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22933 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22934 (rm.GetLane() <= 1))) &&
22935 (dt.Is(S16) || dt.Is(S32))) {
22936 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22937 EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
22938 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22939 AdvanceIT();
22940 return;
22941 }
22942 }
22943 } else {
22944 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
22945 if (encoded_dt.IsValid() &&
22946 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22947 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22948 (rm.GetLane() <= 1))) &&
22949 (dt.Is(S16) || dt.Is(S32))) {
22950 if (cond.Is(al)) {
22951 EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
22952 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22953 return;
22954 }
22955 }
22956 }
22957 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22958}
22959
22960void Assembler::vqmovn(Condition cond,
22961 DataType dt,
22962 DRegister rd,
22963 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022964 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022965 CheckIT(cond);
22966 Dt_op_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022968 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
22969 if (encoded_dt.IsValid()) {
22970 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22971 EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22972 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22973 rd.Encode(22, 12) | rm.Encode(5, 0));
22974 AdvanceIT();
22975 return;
22976 }
22977 }
22978 } else {
22979 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
22980 if (encoded_dt.IsValid()) {
22981 if (cond.Is(al)) {
22982 EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22983 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22984 rd.Encode(22, 12) | rm.Encode(5, 0));
22985 return;
22986 }
22987 }
22988 }
22989 Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
22990}
22991
22992void Assembler::vqmovun(Condition cond,
22993 DataType dt,
22994 DRegister rd,
22995 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022996 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022997 CheckIT(cond);
22998 Dt_size_14 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022999 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023000 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
23001 if (encoded_dt.IsValid()) {
23002 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23003 EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
23004 rd.Encode(22, 12) | rm.Encode(5, 0));
23005 AdvanceIT();
23006 return;
23007 }
23008 }
23009 } else {
23010 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
23011 if (encoded_dt.IsValid()) {
23012 if (cond.Is(al)) {
23013 EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
23014 rd.Encode(22, 12) | rm.Encode(5, 0));
23015 return;
23016 }
23017 }
23018 }
23019 Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
23020}
23021
23022void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023023 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023024 CheckIT(cond);
23025 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023026 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023027 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23028 if (encoded_dt.IsValid()) {
23029 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23030 EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
23031 rd.Encode(22, 12) | rm.Encode(5, 0));
23032 AdvanceIT();
23033 return;
23034 }
23035 }
23036 } else {
23037 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23038 if (encoded_dt.IsValid()) {
23039 if (cond.Is(al)) {
23040 EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
23041 rd.Encode(22, 12) | rm.Encode(5, 0));
23042 return;
23043 }
23044 }
23045 }
23046 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23047}
23048
23049void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023050 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023051 CheckIT(cond);
23052 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023053 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023054 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23055 if (encoded_dt.IsValid()) {
23056 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23057 EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
23058 rd.Encode(22, 12) | rm.Encode(5, 0));
23059 AdvanceIT();
23060 return;
23061 }
23062 }
23063 } else {
23064 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23065 if (encoded_dt.IsValid()) {
23066 if (cond.Is(al)) {
23067 EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
23068 rd.Encode(22, 12) | rm.Encode(5, 0));
23069 return;
23070 }
23071 }
23072 }
23073 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23074}
23075
23076void Assembler::vqrdmulh(
23077 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023078 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023079 CheckIT(cond);
23080 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023081 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023082 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23083 if (encoded_dt.IsValid()) {
23084 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23085 EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
23086 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23087 AdvanceIT();
23088 return;
23089 }
23090 }
23091 } else {
23092 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23093 if (encoded_dt.IsValid()) {
23094 if (cond.Is(al)) {
23095 EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
23096 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23097 return;
23098 }
23099 }
23100 }
23101 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23102}
23103
23104void Assembler::vqrdmulh(
23105 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023106 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023107 CheckIT(cond);
23108 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023109 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023110 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23111 if (encoded_dt.IsValid()) {
23112 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23113 EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
23114 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23115 AdvanceIT();
23116 return;
23117 }
23118 }
23119 } else {
23120 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23121 if (encoded_dt.IsValid()) {
23122 if (cond.Is(al)) {
23123 EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
23124 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23125 return;
23126 }
23127 }
23128 }
23129 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23130}
23131
23132void Assembler::vqrdmulh(
23133 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023134 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023135 CheckIT(cond);
23136 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023137 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023138 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
23139 if (encoded_dt.IsValid() &&
23140 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23141 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23142 (rm.GetLane() <= 1))) &&
23143 (dt.Is(S16) || dt.Is(S32))) {
23144 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23145 EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
23146 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23147 AdvanceIT();
23148 return;
23149 }
23150 }
23151 } else {
23152 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
23153 if (encoded_dt.IsValid() &&
23154 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23155 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23156 (rm.GetLane() <= 1))) &&
23157 (dt.Is(S16) || dt.Is(S32))) {
23158 if (cond.Is(al)) {
23159 EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
23160 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23161 return;
23162 }
23163 }
23164 }
23165 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23166}
23167
23168void Assembler::vqrdmulh(
23169 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023170 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023171 CheckIT(cond);
23172 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023173 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023174 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
23175 if (encoded_dt.IsValid() &&
23176 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23177 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23178 (rm.GetLane() <= 1))) &&
23179 (dt.Is(S16) || dt.Is(S32))) {
23180 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23181 EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
23182 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23183 AdvanceIT();
23184 return;
23185 }
23186 }
23187 } else {
23188 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
23189 if (encoded_dt.IsValid() &&
23190 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23191 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23192 (rm.GetLane() <= 1))) &&
23193 (dt.Is(S16) || dt.Is(S32))) {
23194 if (cond.Is(al)) {
23195 EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
23196 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23197 return;
23198 }
23199 }
23200 }
23201 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23202}
23203
23204void Assembler::vqrshl(
23205 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023206 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023207 CheckIT(cond);
23208 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023209 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023210 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23211 if (encoded_dt.IsValid()) {
23212 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23213 EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23214 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23215 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23216 AdvanceIT();
23217 return;
23218 }
23219 }
23220 } else {
23221 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23222 if (encoded_dt.IsValid()) {
23223 if (cond.Is(al)) {
23224 EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23225 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23226 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23227 return;
23228 }
23229 }
23230 }
23231 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23232}
23233
23234void Assembler::vqrshl(
23235 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023236 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023237 CheckIT(cond);
23238 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023239 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023240 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23241 if (encoded_dt.IsValid()) {
23242 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23243 EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23244 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23245 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23246 AdvanceIT();
23247 return;
23248 }
23249 }
23250 } else {
23251 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23252 if (encoded_dt.IsValid()) {
23253 if (cond.Is(al)) {
23254 EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23255 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23256 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23257 return;
23258 }
23259 }
23260 }
23261 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23262}
23263
23264void Assembler::vqrshrn(Condition cond,
23265 DataType dt,
23266 DRegister rd,
23267 QRegister rm,
23268 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023269 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023270 CheckIT(cond);
23271 if (operand.IsImmediate()) {
23272 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23273 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23274 Dt_op_size_3 encoded_dt(dt);
23275 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023276 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023277 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23278 if (encoded_dt.IsValid() && (imm == 0)) {
23279 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23280 EmitT32_32(0xffb20280U |
23281 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23282 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23283 rd.Encode(22, 12) | rm.Encode(5, 0));
23284 AdvanceIT();
23285 return;
23286 }
23287 }
23288 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23289 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23290 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23291 uint32_t imm6 = dt.GetSize() / 2 - imm;
23292 EmitT32_32(0xef800950U |
23293 (encoded_dt_2.GetTypeEncodingValue() << 28) |
23294 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23295 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23296 AdvanceIT();
23297 return;
23298 }
23299 }
23300 } else {
23301 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23302 if (encoded_dt.IsValid() && (imm == 0)) {
23303 if (cond.Is(al)) {
23304 EmitA32(0xf3b20280U |
23305 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23306 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23307 rd.Encode(22, 12) | rm.Encode(5, 0));
23308 return;
23309 }
23310 }
23311 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23312 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23313 if (cond.Is(al)) {
23314 uint32_t imm6 = dt.GetSize() / 2 - imm;
23315 EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23316 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23317 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23318 return;
23319 }
23320 }
23321 }
23322 }
23323 }
23324 Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
23325}
23326
23327void Assembler::vqrshrun(Condition cond,
23328 DataType dt,
23329 DRegister rd,
23330 QRegister rm,
23331 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023332 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023333 CheckIT(cond);
23334 if (operand.IsImmediate()) {
23335 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23336 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23337 Dt_imm6_2 encoded_dt(dt);
23338 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023339 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023340 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23341 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23342 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23343 uint32_t imm6 = dt.GetSize() / 2 - imm;
23344 EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
23345 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23346 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23347 AdvanceIT();
23348 return;
23349 }
23350 }
23351 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23352 if (encoded_dt_2.IsValid() && (imm == 0)) {
23353 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23354 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23355 rd.Encode(22, 12) | rm.Encode(5, 0));
23356 AdvanceIT();
23357 return;
23358 }
23359 }
23360 } else {
23361 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23362 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23363 if (cond.Is(al)) {
23364 uint32_t imm6 = dt.GetSize() / 2 - imm;
23365 EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
23366 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23367 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23368 return;
23369 }
23370 }
23371 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23372 if (encoded_dt_2.IsValid() && (imm == 0)) {
23373 if (cond.Is(al)) {
23374 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23375 rd.Encode(22, 12) | rm.Encode(5, 0));
23376 return;
23377 }
23378 }
23379 }
23380 }
23381 }
23382 Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
23383}
23384
23385void Assembler::vqshl(Condition cond,
23386 DataType dt,
23387 DRegister rd,
23388 DRegister rm,
23389 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023390 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023391 CheckIT(cond);
23392 if (operand.IsRegister()) {
23393 DRegister rn = operand.GetRegister();
23394 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023396 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23397 if (encoded_dt.IsValid()) {
23398 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23399 EmitT32_32(0xef000410U |
23400 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23401 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23402 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23403 AdvanceIT();
23404 return;
23405 }
23406 }
23407 } else {
23408 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23409 if (encoded_dt.IsValid()) {
23410 if (cond.Is(al)) {
23411 EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23412 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23413 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23414 return;
23415 }
23416 }
23417 }
23418 }
23419 if (operand.IsImmediate()) {
23420 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23421 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23422 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023423 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023424 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23425 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23426 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23427 uint32_t imm6 = imm;
23428 EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
23429 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23430 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23431 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23432 AdvanceIT();
23433 return;
23434 }
23435 }
23436 } else {
23437 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23438 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23439 if (cond.Is(al)) {
23440 uint32_t imm6 = imm;
23441 EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
23442 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23443 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23444 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23445 return;
23446 }
23447 }
23448 }
23449 }
23450 }
23451 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23452}
23453
23454void Assembler::vqshl(Condition cond,
23455 DataType dt,
23456 QRegister rd,
23457 QRegister rm,
23458 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023459 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023460 CheckIT(cond);
23461 if (operand.IsRegister()) {
23462 QRegister rn = operand.GetRegister();
23463 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023465 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23466 if (encoded_dt.IsValid()) {
23467 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23468 EmitT32_32(0xef000450U |
23469 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23470 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23471 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23472 AdvanceIT();
23473 return;
23474 }
23475 }
23476 } else {
23477 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23478 if (encoded_dt.IsValid()) {
23479 if (cond.Is(al)) {
23480 EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23481 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23482 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23483 return;
23484 }
23485 }
23486 }
23487 }
23488 if (operand.IsImmediate()) {
23489 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23490 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23491 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023492 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023493 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23494 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23495 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23496 uint32_t imm6 = imm;
23497 EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
23498 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23499 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23500 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23501 AdvanceIT();
23502 return;
23503 }
23504 }
23505 } else {
23506 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23507 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23508 if (cond.Is(al)) {
23509 uint32_t imm6 = imm;
23510 EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
23511 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23512 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23513 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23514 return;
23515 }
23516 }
23517 }
23518 }
23519 }
23520 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23521}
23522
23523void Assembler::vqshlu(Condition cond,
23524 DataType dt,
23525 DRegister rd,
23526 DRegister rm,
23527 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023528 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023529 CheckIT(cond);
23530 if (operand.IsImmediate()) {
23531 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23532 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23533 Dt_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023534 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023535 // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23536 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23537 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23538 uint32_t imm6 = imm;
23539 EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
23540 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23541 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23542 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23543 AdvanceIT();
23544 return;
23545 }
23546 }
23547 } else {
23548 // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23549 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23550 if (cond.Is(al)) {
23551 uint32_t imm6 = imm;
23552 EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
23553 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23554 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23555 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23556 return;
23557 }
23558 }
23559 }
23560 }
23561 }
23562 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23563}
23564
23565void Assembler::vqshlu(Condition cond,
23566 DataType dt,
23567 QRegister rd,
23568 QRegister rm,
23569 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023570 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023571 CheckIT(cond);
23572 if (operand.IsImmediate()) {
23573 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23574 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23575 Dt_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023576 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023577 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23578 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23579 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23580 uint32_t imm6 = imm;
23581 EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
23582 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23583 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23584 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23585 AdvanceIT();
23586 return;
23587 }
23588 }
23589 } else {
23590 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23591 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23592 if (cond.Is(al)) {
23593 uint32_t imm6 = imm;
23594 EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
23595 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23596 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23597 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23598 return;
23599 }
23600 }
23601 }
23602 }
23603 }
23604 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23605}
23606
23607void Assembler::vqshrn(Condition cond,
23608 DataType dt,
23609 DRegister rd,
23610 QRegister rm,
23611 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023612 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023613 CheckIT(cond);
23614 if (operand.IsImmediate()) {
23615 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23616 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23617 Dt_op_size_3 encoded_dt(dt);
23618 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023619 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023620 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23621 if (encoded_dt.IsValid() && (imm == 0)) {
23622 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23623 EmitT32_32(0xffb20280U |
23624 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23625 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23626 rd.Encode(22, 12) | rm.Encode(5, 0));
23627 AdvanceIT();
23628 return;
23629 }
23630 }
23631 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23632 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23633 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23634 uint32_t imm6 = dt.GetSize() / 2 - imm;
23635 EmitT32_32(0xef800910U |
23636 (encoded_dt_2.GetTypeEncodingValue() << 28) |
23637 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23638 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23639 AdvanceIT();
23640 return;
23641 }
23642 }
23643 } else {
23644 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23645 if (encoded_dt.IsValid() && (imm == 0)) {
23646 if (cond.Is(al)) {
23647 EmitA32(0xf3b20280U |
23648 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23649 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23650 rd.Encode(22, 12) | rm.Encode(5, 0));
23651 return;
23652 }
23653 }
23654 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23655 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23656 if (cond.Is(al)) {
23657 uint32_t imm6 = dt.GetSize() / 2 - imm;
23658 EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23659 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23660 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23661 return;
23662 }
23663 }
23664 }
23665 }
23666 }
23667 Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
23668}
23669
23670void Assembler::vqshrun(Condition cond,
23671 DataType dt,
23672 DRegister rd,
23673 QRegister rm,
23674 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023675 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023676 CheckIT(cond);
23677 if (operand.IsImmediate()) {
23678 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23679 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23680 Dt_imm6_2 encoded_dt(dt);
23681 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023682 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023683 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23684 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23685 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23686 uint32_t imm6 = dt.GetSize() / 2 - imm;
23687 EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
23688 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23689 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23690 AdvanceIT();
23691 return;
23692 }
23693 }
23694 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23695 if (encoded_dt_2.IsValid() && (imm == 0)) {
23696 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23697 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23698 rd.Encode(22, 12) | rm.Encode(5, 0));
23699 AdvanceIT();
23700 return;
23701 }
23702 }
23703 } else {
23704 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23705 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23706 if (cond.Is(al)) {
23707 uint32_t imm6 = dt.GetSize() / 2 - imm;
23708 EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
23709 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23710 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23711 return;
23712 }
23713 }
23714 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23715 if (encoded_dt_2.IsValid() && (imm == 0)) {
23716 if (cond.Is(al)) {
23717 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23718 rd.Encode(22, 12) | rm.Encode(5, 0));
23719 return;
23720 }
23721 }
23722 }
23723 }
23724 }
23725 Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
23726}
23727
23728void Assembler::vqsub(
23729 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023730 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023731 CheckIT(cond);
23732 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023733 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023734 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23735 if (encoded_dt.IsValid()) {
23736 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23737 EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23738 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23739 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23740 AdvanceIT();
23741 return;
23742 }
23743 }
23744 } else {
23745 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23746 if (encoded_dt.IsValid()) {
23747 if (cond.Is(al)) {
23748 EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23749 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23750 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23751 return;
23752 }
23753 }
23754 }
23755 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23756}
23757
23758void Assembler::vqsub(
23759 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023760 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023761 CheckIT(cond);
23762 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023763 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023764 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23765 if (encoded_dt.IsValid()) {
23766 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23767 EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23768 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23769 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23770 AdvanceIT();
23771 return;
23772 }
23773 }
23774 } else {
23775 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23776 if (encoded_dt.IsValid()) {
23777 if (cond.Is(al)) {
23778 EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23779 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23780 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23781 return;
23782 }
23783 }
23784 }
23785 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23786}
23787
23788void Assembler::vraddhn(
23789 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023790 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023791 CheckIT(cond);
23792 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023793 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023794 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23795 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23796 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23797 EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
23798 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23799 AdvanceIT();
23800 return;
23801 }
23802 }
23803 } else {
23804 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23805 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23806 if (cond.Is(al)) {
23807 EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
23808 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23809 return;
23810 }
23811 }
23812 }
23813 Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
23814}
23815
23816void Assembler::vrecpe(Condition cond,
23817 DataType dt,
23818 DRegister rd,
23819 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023820 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023821 CheckIT(cond);
23822 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023823 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023824 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23825 if (encoded_dt.IsValid()) {
23826 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23827 EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23828 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23829 rd.Encode(22, 12) | rm.Encode(5, 0));
23830 AdvanceIT();
23831 return;
23832 }
23833 }
23834 } else {
23835 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23836 if (encoded_dt.IsValid()) {
23837 if (cond.Is(al)) {
23838 EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23839 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23840 rd.Encode(22, 12) | rm.Encode(5, 0));
23841 return;
23842 }
23843 }
23844 }
23845 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23846}
23847
23848void Assembler::vrecpe(Condition cond,
23849 DataType dt,
23850 QRegister rd,
23851 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023852 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023853 CheckIT(cond);
23854 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023855 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023856 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23857 if (encoded_dt.IsValid()) {
23858 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23859 EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23860 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23861 rd.Encode(22, 12) | rm.Encode(5, 0));
23862 AdvanceIT();
23863 return;
23864 }
23865 }
23866 } else {
23867 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23868 if (encoded_dt.IsValid()) {
23869 if (cond.Is(al)) {
23870 EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23871 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23872 rd.Encode(22, 12) | rm.Encode(5, 0));
23873 return;
23874 }
23875 }
23876 }
23877 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23878}
23879
23880void Assembler::vrecps(
23881 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023882 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023883 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023884 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023885 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23886 if (dt.Is(F32)) {
23887 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23888 EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23889 rm.Encode(5, 0));
23890 AdvanceIT();
23891 return;
23892 }
23893 }
23894 } else {
23895 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23896 if (dt.Is(F32)) {
23897 if (cond.Is(al)) {
23898 EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23899 rm.Encode(5, 0));
23900 return;
23901 }
23902 }
23903 }
23904 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23905}
23906
23907void Assembler::vrecps(
23908 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023909 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023910 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023911 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023912 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23913 if (dt.Is(F32)) {
23914 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23915 EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23916 rm.Encode(5, 0));
23917 AdvanceIT();
23918 return;
23919 }
23920 }
23921 } else {
23922 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23923 if (dt.Is(F32)) {
23924 if (cond.Is(al)) {
23925 EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23926 rm.Encode(5, 0));
23927 return;
23928 }
23929 }
23930 }
23931 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23932}
23933
23934void Assembler::vrev16(Condition cond,
23935 DataType dt,
23936 DRegister rd,
23937 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023938 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023939 CheckIT(cond);
23940 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023941 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023942 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23943 if (encoded_dt.IsValid()) {
23944 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23945 EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
23946 rd.Encode(22, 12) | rm.Encode(5, 0));
23947 AdvanceIT();
23948 return;
23949 }
23950 }
23951 } else {
23952 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23953 if (encoded_dt.IsValid()) {
23954 if (cond.Is(al)) {
23955 EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
23956 rd.Encode(22, 12) | rm.Encode(5, 0));
23957 return;
23958 }
23959 }
23960 }
23961 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
23962}
23963
23964void Assembler::vrev16(Condition cond,
23965 DataType dt,
23966 QRegister rd,
23967 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023968 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023969 CheckIT(cond);
23970 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023971 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023972 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23973 if (encoded_dt.IsValid()) {
23974 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23975 EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
23976 rd.Encode(22, 12) | rm.Encode(5, 0));
23977 AdvanceIT();
23978 return;
23979 }
23980 }
23981 } else {
23982 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23983 if (encoded_dt.IsValid()) {
23984 if (cond.Is(al)) {
23985 EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
23986 rd.Encode(22, 12) | rm.Encode(5, 0));
23987 return;
23988 }
23989 }
23990 }
23991 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
23992}
23993
23994void Assembler::vrev32(Condition cond,
23995 DataType dt,
23996 DRegister rd,
23997 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023998 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023999 CheckIT(cond);
24000 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024001 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024002 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24003 if (encoded_dt.IsValid()) {
24004 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24005 EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
24006 rd.Encode(22, 12) | rm.Encode(5, 0));
24007 AdvanceIT();
24008 return;
24009 }
24010 }
24011 } else {
24012 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24013 if (encoded_dt.IsValid()) {
24014 if (cond.Is(al)) {
24015 EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
24016 rd.Encode(22, 12) | rm.Encode(5, 0));
24017 return;
24018 }
24019 }
24020 }
24021 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24022}
24023
24024void Assembler::vrev32(Condition cond,
24025 DataType dt,
24026 QRegister rd,
24027 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024028 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024029 CheckIT(cond);
24030 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024031 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024032 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24033 if (encoded_dt.IsValid()) {
24034 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24035 EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
24036 rd.Encode(22, 12) | rm.Encode(5, 0));
24037 AdvanceIT();
24038 return;
24039 }
24040 }
24041 } else {
24042 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24043 if (encoded_dt.IsValid()) {
24044 if (cond.Is(al)) {
24045 EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
24046 rd.Encode(22, 12) | rm.Encode(5, 0));
24047 return;
24048 }
24049 }
24050 }
24051 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24052}
24053
24054void Assembler::vrev64(Condition cond,
24055 DataType dt,
24056 DRegister rd,
24057 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024058 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024059 CheckIT(cond);
24060 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024061 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024062 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24063 if (encoded_dt.IsValid()) {
24064 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24065 EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
24066 rd.Encode(22, 12) | rm.Encode(5, 0));
24067 AdvanceIT();
24068 return;
24069 }
24070 }
24071 } else {
24072 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24073 if (encoded_dt.IsValid()) {
24074 if (cond.Is(al)) {
24075 EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
24076 rd.Encode(22, 12) | rm.Encode(5, 0));
24077 return;
24078 }
24079 }
24080 }
24081 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24082}
24083
24084void Assembler::vrev64(Condition cond,
24085 DataType dt,
24086 QRegister rd,
24087 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024088 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024089 CheckIT(cond);
24090 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024091 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024092 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24093 if (encoded_dt.IsValid()) {
24094 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24095 EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
24096 rd.Encode(22, 12) | rm.Encode(5, 0));
24097 AdvanceIT();
24098 return;
24099 }
24100 }
24101 } else {
24102 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24103 if (encoded_dt.IsValid()) {
24104 if (cond.Is(al)) {
24105 EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
24106 rd.Encode(22, 12) | rm.Encode(5, 0));
24107 return;
24108 }
24109 }
24110 }
24111 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24112}
24113
24114void Assembler::vrhadd(
24115 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024116 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024117 CheckIT(cond);
24118 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024119 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024120 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
24121 if (encoded_dt.IsValid()) {
24122 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24123 EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24124 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24125 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24126 AdvanceIT();
24127 return;
24128 }
24129 }
24130 } else {
24131 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
24132 if (encoded_dt.IsValid()) {
24133 if (cond.Is(al)) {
24134 EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24135 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24136 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24137 return;
24138 }
24139 }
24140 }
24141 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24142}
24143
24144void Assembler::vrhadd(
24145 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024146 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024147 CheckIT(cond);
24148 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024149 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024150 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
24151 if (encoded_dt.IsValid()) {
24152 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24153 EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24154 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24155 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24156 AdvanceIT();
24157 return;
24158 }
24159 }
24160 } else {
24161 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
24162 if (encoded_dt.IsValid()) {
24163 if (cond.Is(al)) {
24164 EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24165 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24166 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24167 return;
24168 }
24169 }
24170 }
24171 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24172}
24173
24174void Assembler::vrinta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024175 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024176 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024177 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024178 // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; T1
24179 if (dt1.Is(F32) && dt2.Is(F32)) {
24180 EmitT32_32(0xffba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
24181 AdvanceIT();
24182 return;
24183 }
24184 // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; T1
24185 if (dt1.Is(F64) && dt2.Is(F64)) {
24186 EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24187 AdvanceIT();
24188 return;
24189 }
24190 } else {
24191 // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; A1
24192 if (dt1.Is(F32) && dt2.Is(F32)) {
24193 EmitA32(0xf3ba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
24194 return;
24195 }
24196 // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; A1
24197 if (dt1.Is(F64) && dt2.Is(F64)) {
24198 EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24199 return;
24200 }
24201 }
24202 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24203}
24204
24205void Assembler::vrinta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024206 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024207 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024208 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024209 // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; T1
24210 if (dt1.Is(F32) && dt2.Is(F32)) {
24211 EmitT32_32(0xffba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
24212 AdvanceIT();
24213 return;
24214 }
24215 } else {
24216 // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; A1
24217 if (dt1.Is(F32) && dt2.Is(F32)) {
24218 EmitA32(0xf3ba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
24219 return;
24220 }
24221 }
24222 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24223}
24224
24225void Assembler::vrinta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024226 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024227 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024228 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024229 // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; T1
24230 if (dt1.Is(F32) && dt2.Is(F32)) {
24231 EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24232 AdvanceIT();
24233 return;
24234 }
24235 } else {
24236 // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; A1
24237 if (dt1.Is(F32) && dt2.Is(F32)) {
24238 EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24239 return;
24240 }
24241 }
24242 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24243}
24244
24245void Assembler::vrintm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024246 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024247 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024248 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024249 // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; T1
24250 if (dt1.Is(F32) && dt2.Is(F32)) {
24251 EmitT32_32(0xffba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
24252 AdvanceIT();
24253 return;
24254 }
24255 // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; T1
24256 if (dt1.Is(F64) && dt2.Is(F64)) {
24257 EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24258 AdvanceIT();
24259 return;
24260 }
24261 } else {
24262 // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; A1
24263 if (dt1.Is(F32) && dt2.Is(F32)) {
24264 EmitA32(0xf3ba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
24265 return;
24266 }
24267 // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; A1
24268 if (dt1.Is(F64) && dt2.Is(F64)) {
24269 EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24270 return;
24271 }
24272 }
24273 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24274}
24275
24276void Assembler::vrintm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024277 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024278 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024279 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024280 // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; T1
24281 if (dt1.Is(F32) && dt2.Is(F32)) {
24282 EmitT32_32(0xffba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24283 AdvanceIT();
24284 return;
24285 }
24286 } else {
24287 // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; A1
24288 if (dt1.Is(F32) && dt2.Is(F32)) {
24289 EmitA32(0xf3ba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24290 return;
24291 }
24292 }
24293 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24294}
24295
24296void Assembler::vrintm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024297 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024298 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024299 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024300 // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; T1
24301 if (dt1.Is(F32) && dt2.Is(F32)) {
24302 EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24303 AdvanceIT();
24304 return;
24305 }
24306 } else {
24307 // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; A1
24308 if (dt1.Is(F32) && dt2.Is(F32)) {
24309 EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24310 return;
24311 }
24312 }
24313 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24314}
24315
24316void Assembler::vrintn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024317 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024318 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024320 // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; T1
24321 if (dt1.Is(F32) && dt2.Is(F32)) {
24322 EmitT32_32(0xffba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
24323 AdvanceIT();
24324 return;
24325 }
24326 // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; T1
24327 if (dt1.Is(F64) && dt2.Is(F64)) {
24328 EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24329 AdvanceIT();
24330 return;
24331 }
24332 } else {
24333 // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; A1
24334 if (dt1.Is(F32) && dt2.Is(F32)) {
24335 EmitA32(0xf3ba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
24336 return;
24337 }
24338 // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; A1
24339 if (dt1.Is(F64) && dt2.Is(F64)) {
24340 EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24341 return;
24342 }
24343 }
24344 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24345}
24346
24347void Assembler::vrintn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024349 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024350 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024351 // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; T1
24352 if (dt1.Is(F32) && dt2.Is(F32)) {
24353 EmitT32_32(0xffba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
24354 AdvanceIT();
24355 return;
24356 }
24357 } else {
24358 // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; A1
24359 if (dt1.Is(F32) && dt2.Is(F32)) {
24360 EmitA32(0xf3ba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
24361 return;
24362 }
24363 }
24364 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24365}
24366
24367void Assembler::vrintn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024369 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024370 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024371 // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; T1
24372 if (dt1.Is(F32) && dt2.Is(F32)) {
24373 EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24374 AdvanceIT();
24375 return;
24376 }
24377 } else {
24378 // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; A1
24379 if (dt1.Is(F32) && dt2.Is(F32)) {
24380 EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24381 return;
24382 }
24383 }
24384 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24385}
24386
24387void Assembler::vrintp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024388 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024389 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024390 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024391 // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; T1
24392 if (dt1.Is(F32) && dt2.Is(F32)) {
24393 EmitT32_32(0xffba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
24394 AdvanceIT();
24395 return;
24396 }
24397 // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; T1
24398 if (dt1.Is(F64) && dt2.Is(F64)) {
24399 EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24400 AdvanceIT();
24401 return;
24402 }
24403 } else {
24404 // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; A1
24405 if (dt1.Is(F32) && dt2.Is(F32)) {
24406 EmitA32(0xf3ba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
24407 return;
24408 }
24409 // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; A1
24410 if (dt1.Is(F64) && dt2.Is(F64)) {
24411 EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24412 return;
24413 }
24414 }
24415 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24416}
24417
24418void Assembler::vrintp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024419 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024420 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024421 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024422 // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; T1
24423 if (dt1.Is(F32) && dt2.Is(F32)) {
24424 EmitT32_32(0xffba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24425 AdvanceIT();
24426 return;
24427 }
24428 } else {
24429 // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; A1
24430 if (dt1.Is(F32) && dt2.Is(F32)) {
24431 EmitA32(0xf3ba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24432 return;
24433 }
24434 }
24435 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24436}
24437
24438void Assembler::vrintp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024439 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024440 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024441 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024442 // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; T1
24443 if (dt1.Is(F32) && dt2.Is(F32)) {
24444 EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24445 AdvanceIT();
24446 return;
24447 }
24448 } else {
24449 // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; A1
24450 if (dt1.Is(F32) && dt2.Is(F32)) {
24451 EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24452 return;
24453 }
24454 }
24455 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24456}
24457
24458void Assembler::vrintr(
24459 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024460 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024461 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024462 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024463 // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24464 if (dt1.Is(F32) && dt2.Is(F32)) {
24465 EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24466 AdvanceIT();
24467 return;
24468 }
24469 } else {
24470 // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24471 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24472 EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24473 rm.Encode(5, 0));
24474 return;
24475 }
24476 }
24477 Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
24478}
24479
24480void Assembler::vrintr(
24481 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024482 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024483 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024484 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024485 // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24486 if (dt1.Is(F64) && dt2.Is(F64)) {
24487 EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24488 AdvanceIT();
24489 return;
24490 }
24491 } else {
24492 // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24493 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24494 EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24495 rm.Encode(5, 0));
24496 return;
24497 }
24498 }
24499 Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
24500}
24501
24502void Assembler::vrintx(
24503 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024504 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024505 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024506 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024507 // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; T1
24508 if (dt1.Is(F32) && dt2.Is(F32)) {
24509 EmitT32_32(0xffba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
24510 AdvanceIT();
24511 return;
24512 }
24513 // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24514 if (dt1.Is(F64) && dt2.Is(F64)) {
24515 EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24516 AdvanceIT();
24517 return;
24518 }
24519 } else {
24520 // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; A1
24521 if (dt1.Is(F32) && dt2.Is(F32)) {
24522 EmitA32(0xf3ba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
24523 return;
24524 }
24525 // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24526 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24527 EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24528 rm.Encode(5, 0));
24529 return;
24530 }
24531 }
24532 Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
24533}
24534
24535void Assembler::vrintx(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024536 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024537 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024538 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024539 // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; T1
24540 if (dt1.Is(F32) && dt2.Is(F32)) {
24541 EmitT32_32(0xffba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24542 AdvanceIT();
24543 return;
24544 }
24545 } else {
24546 // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; A1
24547 if (dt1.Is(F32) && dt2.Is(F32)) {
24548 EmitA32(0xf3ba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24549 return;
24550 }
24551 }
24552 Delegate(kVrintx, &Assembler::vrintx, dt1, dt2, rd, rm);
24553}
24554
24555void Assembler::vrintx(
24556 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024557 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024558 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024559 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024560 // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24561 if (dt1.Is(F32) && dt2.Is(F32)) {
24562 EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24563 AdvanceIT();
24564 return;
24565 }
24566 } else {
24567 // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24568 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24569 EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24570 rm.Encode(5, 0));
24571 return;
24572 }
24573 }
24574 Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
24575}
24576
24577void Assembler::vrintz(
24578 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024579 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024580 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024581 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024582 // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; T1
24583 if (dt1.Is(F32) && dt2.Is(F32)) {
24584 EmitT32_32(0xffba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
24585 AdvanceIT();
24586 return;
24587 }
24588 // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24589 if (dt1.Is(F64) && dt2.Is(F64)) {
24590 EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24591 AdvanceIT();
24592 return;
24593 }
24594 } else {
24595 // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; A1
24596 if (dt1.Is(F32) && dt2.Is(F32)) {
24597 EmitA32(0xf3ba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
24598 return;
24599 }
24600 // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24601 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24602 EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24603 rm.Encode(5, 0));
24604 return;
24605 }
24606 }
24607 Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
24608}
24609
24610void Assembler::vrintz(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024611 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024612 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024613 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024614 // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; T1
24615 if (dt1.Is(F32) && dt2.Is(F32)) {
24616 EmitT32_32(0xffba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24617 AdvanceIT();
24618 return;
24619 }
24620 } else {
24621 // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; A1
24622 if (dt1.Is(F32) && dt2.Is(F32)) {
24623 EmitA32(0xf3ba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24624 return;
24625 }
24626 }
24627 Delegate(kVrintz, &Assembler::vrintz, dt1, dt2, rd, rm);
24628}
24629
24630void Assembler::vrintz(
24631 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024632 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024633 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024634 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024635 // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24636 if (dt1.Is(F32) && dt2.Is(F32)) {
24637 EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24638 AdvanceIT();
24639 return;
24640 }
24641 } else {
24642 // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24643 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24644 EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24645 rm.Encode(5, 0));
24646 return;
24647 }
24648 }
24649 Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
24650}
24651
24652void Assembler::vrshl(
24653 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024654 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024655 CheckIT(cond);
24656 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024657 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024658 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24659 if (encoded_dt.IsValid()) {
24660 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24661 EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24662 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24663 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24664 AdvanceIT();
24665 return;
24666 }
24667 }
24668 } else {
24669 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24670 if (encoded_dt.IsValid()) {
24671 if (cond.Is(al)) {
24672 EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24673 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24674 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24675 return;
24676 }
24677 }
24678 }
24679 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24680}
24681
24682void Assembler::vrshl(
24683 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024684 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024685 CheckIT(cond);
24686 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024687 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024688 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24689 if (encoded_dt.IsValid()) {
24690 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24691 EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24692 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24693 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24694 AdvanceIT();
24695 return;
24696 }
24697 }
24698 } else {
24699 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24700 if (encoded_dt.IsValid()) {
24701 if (cond.Is(al)) {
24702 EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24703 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24704 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24705 return;
24706 }
24707 }
24708 }
24709 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24710}
24711
24712void Assembler::vrshr(Condition cond,
24713 DataType dt,
24714 DRegister rd,
24715 DRegister rm,
24716 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024717 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024718 CheckIT(cond);
24719 if (operand.IsImmediate()) {
24720 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24721 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24722 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024723 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024724 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24725 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24726 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24727 uint32_t imm6 = dt.GetSize() - imm;
24728 EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
24729 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24730 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24731 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24732 AdvanceIT();
24733 return;
24734 }
24735 }
24736 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24737 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24738 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24739 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24740 rm.Encode(5, 0));
24741 AdvanceIT();
24742 return;
24743 }
24744 }
24745 } else {
24746 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24747 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24748 if (cond.Is(al)) {
24749 uint32_t imm6 = dt.GetSize() - imm;
24750 EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
24751 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24752 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24753 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24754 return;
24755 }
24756 }
24757 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24758 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24759 if (cond.Is(al)) {
24760 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24761 rm.Encode(5, 0));
24762 return;
24763 }
24764 }
24765 }
24766 }
24767 }
24768 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24769}
24770
24771void Assembler::vrshr(Condition cond,
24772 DataType dt,
24773 QRegister rd,
24774 QRegister rm,
24775 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024776 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024777 CheckIT(cond);
24778 if (operand.IsImmediate()) {
24779 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24780 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24781 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024783 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24784 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24785 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24786 uint32_t imm6 = dt.GetSize() - imm;
24787 EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
24788 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24789 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24790 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24791 AdvanceIT();
24792 return;
24793 }
24794 }
24795 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24796 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24797 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24798 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24799 rm.Encode(5, 0));
24800 AdvanceIT();
24801 return;
24802 }
24803 }
24804 } else {
24805 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24806 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24807 if (cond.Is(al)) {
24808 uint32_t imm6 = dt.GetSize() - imm;
24809 EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
24810 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24811 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24812 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24813 return;
24814 }
24815 }
24816 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24817 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24818 if (cond.Is(al)) {
24819 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24820 rm.Encode(5, 0));
24821 return;
24822 }
24823 }
24824 }
24825 }
24826 }
24827 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24828}
24829
24830void Assembler::vrshrn(Condition cond,
24831 DataType dt,
24832 DRegister rd,
24833 QRegister rm,
24834 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024835 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024836 CheckIT(cond);
24837 if (operand.IsImmediate()) {
24838 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24839 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24840 Dt_imm6_3 encoded_dt(dt);
24841 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024842 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024843 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24844 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24845 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24846 uint32_t imm6 = dt.GetSize() / 2 - imm;
24847 EmitT32_32(0xef800850U |
24848 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24849 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24850 AdvanceIT();
24851 return;
24852 }
24853 }
24854 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24855 if (encoded_dt_2.IsValid() && (imm == 0)) {
24856 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24857 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24858 rd.Encode(22, 12) | rm.Encode(5, 0));
24859 AdvanceIT();
24860 return;
24861 }
24862 }
24863 } else {
24864 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24865 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24866 if (cond.Is(al)) {
24867 uint32_t imm6 = dt.GetSize() / 2 - imm;
24868 EmitA32(0xf2800850U |
24869 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24870 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24871 return;
24872 }
24873 }
24874 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24875 if (encoded_dt_2.IsValid() && (imm == 0)) {
24876 if (cond.Is(al)) {
24877 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24878 rd.Encode(22, 12) | rm.Encode(5, 0));
24879 return;
24880 }
24881 }
24882 }
24883 }
24884 }
24885 Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
24886}
24887
24888void Assembler::vrsqrte(Condition cond,
24889 DataType dt,
24890 DRegister rd,
24891 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024892 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024893 CheckIT(cond);
24894 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024896 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24897 if (encoded_dt.IsValid()) {
24898 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24899 EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24900 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24901 rd.Encode(22, 12) | rm.Encode(5, 0));
24902 AdvanceIT();
24903 return;
24904 }
24905 }
24906 } else {
24907 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24908 if (encoded_dt.IsValid()) {
24909 if (cond.Is(al)) {
24910 EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24911 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24912 rd.Encode(22, 12) | rm.Encode(5, 0));
24913 return;
24914 }
24915 }
24916 }
24917 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
24918}
24919
24920void Assembler::vrsqrte(Condition cond,
24921 DataType dt,
24922 QRegister rd,
24923 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024924 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024925 CheckIT(cond);
24926 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024927 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024928 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24929 if (encoded_dt.IsValid()) {
24930 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24931 EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24932 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24933 rd.Encode(22, 12) | rm.Encode(5, 0));
24934 AdvanceIT();
24935 return;
24936 }
24937 }
24938 } else {
24939 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24940 if (encoded_dt.IsValid()) {
24941 if (cond.Is(al)) {
24942 EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24943 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24944 rd.Encode(22, 12) | rm.Encode(5, 0));
24945 return;
24946 }
24947 }
24948 }
24949 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
24950}
24951
24952void Assembler::vrsqrts(
24953 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024954 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024955 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024956 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024957 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
24958 if (dt.Is(F32)) {
24959 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24960 EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24961 rm.Encode(5, 0));
24962 AdvanceIT();
24963 return;
24964 }
24965 }
24966 } else {
24967 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
24968 if (dt.Is(F32)) {
24969 if (cond.Is(al)) {
24970 EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24971 rm.Encode(5, 0));
24972 return;
24973 }
24974 }
24975 }
24976 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
24977}
24978
24979void Assembler::vrsqrts(
24980 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024981 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024982 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024983 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024984 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
24985 if (dt.Is(F32)) {
24986 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24987 EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24988 rm.Encode(5, 0));
24989 AdvanceIT();
24990 return;
24991 }
24992 }
24993 } else {
24994 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
24995 if (dt.Is(F32)) {
24996 if (cond.Is(al)) {
24997 EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24998 rm.Encode(5, 0));
24999 return;
25000 }
25001 }
25002 }
25003 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
25004}
25005
25006void Assembler::vrsra(Condition cond,
25007 DataType dt,
25008 DRegister rd,
25009 DRegister rm,
25010 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025011 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025012 CheckIT(cond);
25013 if (operand.IsImmediate()) {
25014 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25015 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25016 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025017 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025018 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25019 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25020 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25021 uint32_t imm6 = dt.GetSize() - imm;
25022 EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
25023 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25024 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25025 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25026 AdvanceIT();
25027 return;
25028 }
25029 }
25030 } else {
25031 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25032 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25033 if (cond.Is(al)) {
25034 uint32_t imm6 = dt.GetSize() - imm;
25035 EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
25036 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25037 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25038 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25039 return;
25040 }
25041 }
25042 }
25043 }
25044 }
25045 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25046}
25047
25048void Assembler::vrsra(Condition cond,
25049 DataType dt,
25050 QRegister rd,
25051 QRegister rm,
25052 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025053 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025054 CheckIT(cond);
25055 if (operand.IsImmediate()) {
25056 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25057 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25058 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025059 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025060 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25061 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25062 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25063 uint32_t imm6 = dt.GetSize() - imm;
25064 EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
25065 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25066 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25067 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25068 AdvanceIT();
25069 return;
25070 }
25071 }
25072 } else {
25073 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25074 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25075 if (cond.Is(al)) {
25076 uint32_t imm6 = dt.GetSize() - imm;
25077 EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
25078 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25079 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25080 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25081 return;
25082 }
25083 }
25084 }
25085 }
25086 }
25087 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25088}
25089
25090void Assembler::vrsubhn(
25091 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025092 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025093 CheckIT(cond);
25094 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025095 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025096 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
25097 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25098 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25099 EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
25100 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25101 AdvanceIT();
25102 return;
25103 }
25104 }
25105 } else {
25106 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
25107 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25108 if (cond.Is(al)) {
25109 EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
25110 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25111 return;
25112 }
25113 }
25114 }
25115 Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
25116}
25117
25118void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025119 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025120 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025121 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025122 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
25123 if (OutsideITBlock() && dt.Is(F64)) {
25124 EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25125 rm.Encode(5, 0));
25126 AdvanceIT();
25127 return;
25128 }
25129 } else {
25130 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
25131 if (dt.Is(F64)) {
25132 EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25133 rm.Encode(5, 0));
25134 return;
25135 }
25136 }
25137 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25138}
25139
25140void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025141 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025142 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025143 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025144 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
25145 if (OutsideITBlock() && dt.Is(F32)) {
25146 EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25147 rm.Encode(5, 0));
25148 AdvanceIT();
25149 return;
25150 }
25151 } else {
25152 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
25153 if (dt.Is(F32)) {
25154 EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25155 rm.Encode(5, 0));
25156 return;
25157 }
25158 }
25159 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25160}
25161
25162void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025163 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025164 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025165 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025166 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
25167 if (OutsideITBlock() && dt.Is(F64)) {
25168 EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25169 rm.Encode(5, 0));
25170 AdvanceIT();
25171 return;
25172 }
25173 } else {
25174 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
25175 if (dt.Is(F64)) {
25176 EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25177 rm.Encode(5, 0));
25178 return;
25179 }
25180 }
25181 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25182}
25183
25184void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025186 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025187 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025188 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
25189 if (OutsideITBlock() && dt.Is(F32)) {
25190 EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25191 rm.Encode(5, 0));
25192 AdvanceIT();
25193 return;
25194 }
25195 } else {
25196 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
25197 if (dt.Is(F32)) {
25198 EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25199 rm.Encode(5, 0));
25200 return;
25201 }
25202 }
25203 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25204}
25205
25206void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025207 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025208 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025209 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025210 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
25211 if (OutsideITBlock() && dt.Is(F64)) {
25212 EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25213 rm.Encode(5, 0));
25214 AdvanceIT();
25215 return;
25216 }
25217 } else {
25218 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
25219 if (dt.Is(F64)) {
25220 EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25221 rm.Encode(5, 0));
25222 return;
25223 }
25224 }
25225 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25226}
25227
25228void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025229 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025230 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025231 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025232 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
25233 if (OutsideITBlock() && dt.Is(F32)) {
25234 EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25235 rm.Encode(5, 0));
25236 AdvanceIT();
25237 return;
25238 }
25239 } else {
25240 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
25241 if (dt.Is(F32)) {
25242 EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25243 rm.Encode(5, 0));
25244 return;
25245 }
25246 }
25247 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25248}
25249
25250void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025251 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025252 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025253 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025254 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
25255 if (OutsideITBlock() && dt.Is(F64)) {
25256 EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25257 rm.Encode(5, 0));
25258 AdvanceIT();
25259 return;
25260 }
25261 } else {
25262 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
25263 if (dt.Is(F64)) {
25264 EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25265 rm.Encode(5, 0));
25266 return;
25267 }
25268 }
25269 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25270}
25271
25272void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025273 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025274 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025275 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025276 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
25277 if (OutsideITBlock() && dt.Is(F32)) {
25278 EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25279 rm.Encode(5, 0));
25280 AdvanceIT();
25281 return;
25282 }
25283 } else {
25284 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
25285 if (dt.Is(F32)) {
25286 EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25287 rm.Encode(5, 0));
25288 return;
25289 }
25290 }
25291 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25292}
25293
25294void Assembler::vshl(Condition cond,
25295 DataType dt,
25296 DRegister rd,
25297 DRegister rm,
25298 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025299 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025300 CheckIT(cond);
25301 if (operand.IsImmediate()) {
25302 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25303 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25304 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025305 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025306 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
25307 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25308 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25309 uint32_t imm6 = imm;
25310 EmitT32_32(0xef800510U |
25311 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25312 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25313 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25314 AdvanceIT();
25315 return;
25316 }
25317 }
25318 } else {
25319 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
25320 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25321 if (cond.Is(al)) {
25322 uint32_t imm6 = imm;
25323 EmitA32(0xf2800510U |
25324 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25325 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25326 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25327 return;
25328 }
25329 }
25330 }
25331 }
25332 }
25333 if (operand.IsRegister()) {
25334 DRegister rn = operand.GetRegister();
25335 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025336 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025337 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
25338 if (encoded_dt.IsValid()) {
25339 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25340 EmitT32_32(0xef000400U |
25341 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25342 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25343 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25344 AdvanceIT();
25345 return;
25346 }
25347 }
25348 } else {
25349 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
25350 if (encoded_dt.IsValid()) {
25351 if (cond.Is(al)) {
25352 EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25353 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25354 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25355 return;
25356 }
25357 }
25358 }
25359 }
25360 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25361}
25362
25363void Assembler::vshl(Condition cond,
25364 DataType dt,
25365 QRegister rd,
25366 QRegister rm,
25367 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025369 CheckIT(cond);
25370 if (operand.IsImmediate()) {
25371 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25372 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25373 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025374 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025375 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
25376 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25377 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25378 uint32_t imm6 = imm;
25379 EmitT32_32(0xef800550U |
25380 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25381 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25382 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25383 AdvanceIT();
25384 return;
25385 }
25386 }
25387 } else {
25388 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
25389 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25390 if (cond.Is(al)) {
25391 uint32_t imm6 = imm;
25392 EmitA32(0xf2800550U |
25393 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25394 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25395 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25396 return;
25397 }
25398 }
25399 }
25400 }
25401 }
25402 if (operand.IsRegister()) {
25403 QRegister rn = operand.GetRegister();
25404 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025405 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025406 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
25407 if (encoded_dt.IsValid()) {
25408 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25409 EmitT32_32(0xef000440U |
25410 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25411 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25412 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25413 AdvanceIT();
25414 return;
25415 }
25416 }
25417 } else {
25418 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
25419 if (encoded_dt.IsValid()) {
25420 if (cond.Is(al)) {
25421 EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25422 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25423 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25424 return;
25425 }
25426 }
25427 }
25428 }
25429 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25430}
25431
25432void Assembler::vshll(Condition cond,
25433 DataType dt,
25434 QRegister rd,
25435 DRegister rm,
25436 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025437 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025438 CheckIT(cond);
25439 if (operand.IsImmediate()) {
25440 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25441 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25442 Dt_imm6_4 encoded_dt(dt);
25443 Dt_size_16 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025444 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025445 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
25446 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25447 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25448 uint32_t imm6 = dt.GetSize() + imm;
25449 EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
25450 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25451 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25452 AdvanceIT();
25453 return;
25454 }
25455 }
25456 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
25457 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25458 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25459 EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25460 rd.Encode(22, 12) | rm.Encode(5, 0));
25461 AdvanceIT();
25462 return;
25463 }
25464 }
25465 } else {
25466 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
25467 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25468 if (cond.Is(al)) {
25469 uint32_t imm6 = dt.GetSize() + imm;
25470 EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
25471 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25472 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25473 return;
25474 }
25475 }
25476 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
25477 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25478 if (cond.Is(al)) {
25479 EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25480 rd.Encode(22, 12) | rm.Encode(5, 0));
25481 return;
25482 }
25483 }
25484 }
25485 }
25486 }
25487 Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
25488}
25489
25490void Assembler::vshr(Condition cond,
25491 DataType dt,
25492 DRegister rd,
25493 DRegister rm,
25494 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025495 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025496 CheckIT(cond);
25497 if (operand.IsImmediate()) {
25498 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25499 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25500 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025501 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025502 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25503 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25504 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25505 uint32_t imm6 = dt.GetSize() - imm;
25506 EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
25507 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25508 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25509 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25510 AdvanceIT();
25511 return;
25512 }
25513 }
25514 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
25515 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25516 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25517 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25518 rm.Encode(5, 0));
25519 AdvanceIT();
25520 return;
25521 }
25522 }
25523 } else {
25524 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25525 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25526 if (cond.Is(al)) {
25527 uint32_t imm6 = dt.GetSize() - imm;
25528 EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
25529 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25530 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25531 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25532 return;
25533 }
25534 }
25535 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
25536 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25537 if (cond.Is(al)) {
25538 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25539 rm.Encode(5, 0));
25540 return;
25541 }
25542 }
25543 }
25544 }
25545 }
25546 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25547}
25548
25549void Assembler::vshr(Condition cond,
25550 DataType dt,
25551 QRegister rd,
25552 QRegister rm,
25553 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025554 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025555 CheckIT(cond);
25556 if (operand.IsImmediate()) {
25557 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25558 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25559 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025560 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025561 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25562 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25563 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25564 uint32_t imm6 = dt.GetSize() - imm;
25565 EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
25566 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25567 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25568 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25569 AdvanceIT();
25570 return;
25571 }
25572 }
25573 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
25574 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25575 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25576 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25577 rm.Encode(5, 0));
25578 AdvanceIT();
25579 return;
25580 }
25581 }
25582 } else {
25583 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25584 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25585 if (cond.Is(al)) {
25586 uint32_t imm6 = dt.GetSize() - imm;
25587 EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
25588 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25589 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25590 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25591 return;
25592 }
25593 }
25594 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
25595 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25596 if (cond.Is(al)) {
25597 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25598 rm.Encode(5, 0));
25599 return;
25600 }
25601 }
25602 }
25603 }
25604 }
25605 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25606}
25607
25608void Assembler::vshrn(Condition cond,
25609 DataType dt,
25610 DRegister rd,
25611 QRegister rm,
25612 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025613 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025614 CheckIT(cond);
25615 if (operand.IsImmediate()) {
25616 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25617 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25618 Dt_imm6_3 encoded_dt(dt);
25619 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025620 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025621 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
25622 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25623 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25624 uint32_t imm6 = dt.GetSize() / 2 - imm;
25625 EmitT32_32(0xef800810U |
25626 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25627 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25628 AdvanceIT();
25629 return;
25630 }
25631 }
25632 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
25633 if (encoded_dt_2.IsValid() && (imm == 0)) {
25634 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25635 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25636 rd.Encode(22, 12) | rm.Encode(5, 0));
25637 AdvanceIT();
25638 return;
25639 }
25640 }
25641 } else {
25642 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
25643 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25644 if (cond.Is(al)) {
25645 uint32_t imm6 = dt.GetSize() / 2 - imm;
25646 EmitA32(0xf2800810U |
25647 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25648 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25649 return;
25650 }
25651 }
25652 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
25653 if (encoded_dt_2.IsValid() && (imm == 0)) {
25654 if (cond.Is(al)) {
25655 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25656 rd.Encode(22, 12) | rm.Encode(5, 0));
25657 return;
25658 }
25659 }
25660 }
25661 }
25662 }
25663 Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
25664}
25665
25666void Assembler::vsli(Condition cond,
25667 DataType dt,
25668 DRegister rd,
25669 DRegister rm,
25670 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025671 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025672 CheckIT(cond);
25673 if (operand.IsImmediate()) {
25674 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25675 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25676 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025677 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025678 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25679 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25680 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25681 uint32_t imm6 = imm;
25682 EmitT32_32(0xff800510U |
25683 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25684 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25685 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25686 AdvanceIT();
25687 return;
25688 }
25689 }
25690 } else {
25691 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25692 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25693 if (cond.Is(al)) {
25694 uint32_t imm6 = imm;
25695 EmitA32(0xf3800510U |
25696 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25697 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25698 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25699 return;
25700 }
25701 }
25702 }
25703 }
25704 }
25705 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25706}
25707
25708void Assembler::vsli(Condition cond,
25709 DataType dt,
25710 QRegister rd,
25711 QRegister rm,
25712 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025713 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025714 CheckIT(cond);
25715 if (operand.IsImmediate()) {
25716 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25717 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25718 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025719 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025720 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25721 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25722 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25723 uint32_t imm6 = imm;
25724 EmitT32_32(0xff800550U |
25725 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25726 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25727 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25728 AdvanceIT();
25729 return;
25730 }
25731 }
25732 } else {
25733 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25734 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25735 if (cond.Is(al)) {
25736 uint32_t imm6 = imm;
25737 EmitA32(0xf3800550U |
25738 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25739 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25740 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25741 return;
25742 }
25743 }
25744 }
25745 }
25746 }
25747 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25748}
25749
25750void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025751 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025752 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025754 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
25755 if (dt.Is(F32)) {
25756 EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25757 AdvanceIT();
25758 return;
25759 }
25760 } else {
25761 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
25762 if (dt.Is(F32) && cond.IsNotNever()) {
25763 EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25764 rm.Encode(5, 0));
25765 return;
25766 }
25767 }
25768 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25769}
25770
25771void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025772 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025773 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025774 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025775 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
25776 if (dt.Is(F64)) {
25777 EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25778 AdvanceIT();
25779 return;
25780 }
25781 } else {
25782 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
25783 if (dt.Is(F64) && cond.IsNotNever()) {
25784 EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25785 rm.Encode(5, 0));
25786 return;
25787 }
25788 }
25789 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25790}
25791
25792void Assembler::vsra(Condition cond,
25793 DataType dt,
25794 DRegister rd,
25795 DRegister rm,
25796 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025797 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025798 CheckIT(cond);
25799 if (operand.IsImmediate()) {
25800 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25801 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25802 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025803 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025804 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25805 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25806 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25807 uint32_t imm6 = dt.GetSize() - imm;
25808 EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
25809 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25810 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25811 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25812 AdvanceIT();
25813 return;
25814 }
25815 }
25816 } else {
25817 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25818 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25819 if (cond.Is(al)) {
25820 uint32_t imm6 = dt.GetSize() - imm;
25821 EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
25822 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25823 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25824 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25825 return;
25826 }
25827 }
25828 }
25829 }
25830 }
25831 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25832}
25833
25834void Assembler::vsra(Condition cond,
25835 DataType dt,
25836 QRegister rd,
25837 QRegister rm,
25838 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025839 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025840 CheckIT(cond);
25841 if (operand.IsImmediate()) {
25842 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25843 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25844 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025845 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025846 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25847 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25848 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25849 uint32_t imm6 = dt.GetSize() - imm;
25850 EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
25851 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25852 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25853 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25854 AdvanceIT();
25855 return;
25856 }
25857 }
25858 } else {
25859 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25860 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25861 if (cond.Is(al)) {
25862 uint32_t imm6 = dt.GetSize() - imm;
25863 EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
25864 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25865 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25866 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25867 return;
25868 }
25869 }
25870 }
25871 }
25872 }
25873 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25874}
25875
25876void Assembler::vsri(Condition cond,
25877 DataType dt,
25878 DRegister rd,
25879 DRegister rm,
25880 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025881 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025882 CheckIT(cond);
25883 if (operand.IsImmediate()) {
25884 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25885 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25886 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025887 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025888 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25889 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25890 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25891 uint32_t imm6 = dt.GetSize() - imm;
25892 EmitT32_32(0xff800410U |
25893 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25894 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25895 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25896 AdvanceIT();
25897 return;
25898 }
25899 }
25900 } else {
25901 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25902 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25903 if (cond.Is(al)) {
25904 uint32_t imm6 = dt.GetSize() - imm;
25905 EmitA32(0xf3800410U |
25906 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25907 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25908 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25909 return;
25910 }
25911 }
25912 }
25913 }
25914 }
25915 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
25916}
25917
25918void Assembler::vsri(Condition cond,
25919 DataType dt,
25920 QRegister rd,
25921 QRegister rm,
25922 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025923 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025924 CheckIT(cond);
25925 if (operand.IsImmediate()) {
25926 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25927 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25928 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025929 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025930 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25931 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25932 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25933 uint32_t imm6 = dt.GetSize() - imm;
25934 EmitT32_32(0xff800450U |
25935 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25936 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25937 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25938 AdvanceIT();
25939 return;
25940 }
25941 }
25942 } else {
25943 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25944 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25945 if (cond.Is(al)) {
25946 uint32_t imm6 = dt.GetSize() - imm;
25947 EmitA32(0xf3800450U |
25948 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25949 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25950 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25951 return;
25952 }
25953 }
25954 }
25955 }
25956 }
25957 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
25958}
25959
25960void Assembler::vst1(Condition cond,
25961 DataType dt,
25962 const NeonRegisterList& nreglist,
25963 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025964 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025965 CheckIT(cond);
25966 if (operand.IsImmediateZero()) {
25967 Register rn = operand.GetBaseRegister();
25968 Alignment align = operand.GetAlignment();
25969 Dt_size_6 encoded_dt(dt);
25970 Dt_size_7 encoded_dt_2(dt);
25971 Align_align_5 encoded_align_1(align, nreglist);
25972 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025973 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025974 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25975 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25976 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080025977 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080025978 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025979 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25980 const DRegister& first = nreglist.GetFirstDRegister();
25981 uint32_t len_encoding;
25982 switch (nreglist.GetLength()) {
25983 default:
25984 VIXL_UNREACHABLE_OR_FALLTHROUGH();
25985 case 1:
25986 len_encoding = 0x7;
25987 break;
25988 case 2:
25989 len_encoding = 0xa;
25990 break;
25991 case 3:
25992 len_encoding = 0x6;
25993 break;
25994 case 4:
25995 len_encoding = 0x2;
25996 break;
25997 }
25998 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25999 (encoded_align_1.GetEncodingValue() << 4) |
26000 first.Encode(22, 12) | (len_encoding << 8) |
26001 (rn.GetCode() << 16));
26002 AdvanceIT();
26003 return;
26004 }
26005 }
26006 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26007 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26008 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026009 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026010 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026011 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26012 const DRegister& first = nreglist.GetFirstDRegister();
26013 uint32_t len_encoding;
26014 switch (nreglist.GetLength()) {
26015 default:
26016 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26017 case 1:
26018 len_encoding = 0x7;
26019 break;
26020 case 2:
26021 len_encoding = 0xa;
26022 break;
26023 case 3:
26024 len_encoding = 0x6;
26025 break;
26026 case 4:
26027 len_encoding = 0x2;
26028 break;
26029 }
26030 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26031 (encoded_align_1.GetEncodingValue() << 4) |
26032 first.Encode(22, 12) | (len_encoding << 8) |
26033 (rn.GetCode() << 16));
26034 AdvanceIT();
26035 return;
26036 }
26037 }
26038 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26039 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026040 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026041 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026042 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26043 const DRegister& first = nreglist.GetFirstDRegister();
26044 EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26045 (encoded_align_2.GetEncodingValue() << 4) |
26046 first.Encode(22, 12) | (rn.GetCode() << 16));
26047 AdvanceIT();
26048 return;
26049 }
26050 }
26051 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26052 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026053 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026054 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026055 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26056 const DRegister& first = nreglist.GetFirstDRegister();
26057 EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26058 (encoded_align_2.GetEncodingValue() << 4) |
26059 first.Encode(22, 12) | (rn.GetCode() << 16));
26060 AdvanceIT();
26061 return;
26062 }
26063 }
26064 } else {
26065 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26066 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26067 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026068 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026069 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026070 if (cond.Is(al)) {
26071 const DRegister& first = nreglist.GetFirstDRegister();
26072 uint32_t len_encoding;
26073 switch (nreglist.GetLength()) {
26074 default:
26075 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26076 case 1:
26077 len_encoding = 0x7;
26078 break;
26079 case 2:
26080 len_encoding = 0xa;
26081 break;
26082 case 3:
26083 len_encoding = 0x6;
26084 break;
26085 case 4:
26086 len_encoding = 0x2;
26087 break;
26088 }
26089 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26090 (encoded_align_1.GetEncodingValue() << 4) |
26091 first.Encode(22, 12) | (len_encoding << 8) |
26092 (rn.GetCode() << 16));
26093 return;
26094 }
26095 }
26096 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26097 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26098 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026099 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026100 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026101 if (cond.Is(al)) {
26102 const DRegister& first = nreglist.GetFirstDRegister();
26103 uint32_t len_encoding;
26104 switch (nreglist.GetLength()) {
26105 default:
26106 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26107 case 1:
26108 len_encoding = 0x7;
26109 break;
26110 case 2:
26111 len_encoding = 0xa;
26112 break;
26113 case 3:
26114 len_encoding = 0x6;
26115 break;
26116 case 4:
26117 len_encoding = 0x2;
26118 break;
26119 }
26120 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26121 (encoded_align_1.GetEncodingValue() << 4) |
26122 first.Encode(22, 12) | (len_encoding << 8) |
26123 (rn.GetCode() << 16));
26124 return;
26125 }
26126 }
26127 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26128 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026129 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026130 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026131 if (cond.Is(al)) {
26132 const DRegister& first = nreglist.GetFirstDRegister();
26133 EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26134 (encoded_align_2.GetEncodingValue() << 4) |
26135 first.Encode(22, 12) | (rn.GetCode() << 16));
26136 return;
26137 }
26138 }
26139 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26140 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026141 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026142 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026143 if (cond.Is(al)) {
26144 const DRegister& first = nreglist.GetFirstDRegister();
26145 EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26146 (encoded_align_2.GetEncodingValue() << 4) |
26147 first.Encode(22, 12) | (rn.GetCode() << 16));
26148 return;
26149 }
26150 }
26151 }
26152 }
26153 if (operand.IsPlainRegister()) {
26154 Register rn = operand.GetBaseRegister();
26155 Alignment align = operand.GetAlignment();
26156 Register rm = operand.GetOffsetRegister();
26157 Dt_size_6 encoded_dt(dt);
26158 Dt_size_7 encoded_dt_2(dt);
26159 Align_align_5 encoded_align_1(align, nreglist);
26160 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026161 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026162 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26163 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26164 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026165 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026166 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26167 const DRegister& first = nreglist.GetFirstDRegister();
26168 uint32_t len_encoding;
26169 switch (nreglist.GetLength()) {
26170 default:
26171 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26172 case 1:
26173 len_encoding = 0x7;
26174 break;
26175 case 2:
26176 len_encoding = 0xa;
26177 break;
26178 case 3:
26179 len_encoding = 0x6;
26180 break;
26181 case 4:
26182 len_encoding = 0x2;
26183 break;
26184 }
26185 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26186 (encoded_align_1.GetEncodingValue() << 4) |
26187 first.Encode(22, 12) | (len_encoding << 8) |
26188 (rn.GetCode() << 16) | rm.GetCode());
26189 AdvanceIT();
26190 return;
26191 }
26192 }
26193 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26194 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026195 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26196 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026197 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26198 const DRegister& first = nreglist.GetFirstDRegister();
26199 EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26200 (encoded_align_2.GetEncodingValue() << 4) |
26201 first.Encode(22, 12) | (rn.GetCode() << 16) |
26202 rm.GetCode());
26203 AdvanceIT();
26204 return;
26205 }
26206 }
26207 } else {
26208 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26209 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26210 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026211 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026212 if (cond.Is(al)) {
26213 const DRegister& first = nreglist.GetFirstDRegister();
26214 uint32_t len_encoding;
26215 switch (nreglist.GetLength()) {
26216 default:
26217 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26218 case 1:
26219 len_encoding = 0x7;
26220 break;
26221 case 2:
26222 len_encoding = 0xa;
26223 break;
26224 case 3:
26225 len_encoding = 0x6;
26226 break;
26227 case 4:
26228 len_encoding = 0x2;
26229 break;
26230 }
26231 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26232 (encoded_align_1.GetEncodingValue() << 4) |
26233 first.Encode(22, 12) | (len_encoding << 8) |
26234 (rn.GetCode() << 16) | rm.GetCode());
26235 return;
26236 }
26237 }
26238 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26239 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026240 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26241 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026242 if (cond.Is(al)) {
26243 const DRegister& first = nreglist.GetFirstDRegister();
26244 EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26245 (encoded_align_2.GetEncodingValue() << 4) |
26246 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26247 return;
26248 }
26249 }
26250 }
26251 }
26252 Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
26253}
26254
26255void Assembler::vst2(Condition cond,
26256 DataType dt,
26257 const NeonRegisterList& nreglist,
26258 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026259 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026260 CheckIT(cond);
26261 if (operand.IsImmediateZero()) {
26262 Register rn = operand.GetBaseRegister();
26263 Alignment align = operand.GetAlignment();
26264 Dt_size_7 encoded_dt(dt);
26265 Align_align_2 encoded_align_1(align, nreglist);
26266 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026267 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026268 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26269 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26270 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26271 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26272 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026273 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026274 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026275 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26276 const DRegister& first = nreglist.GetFirstDRegister();
26277 uint32_t len_encoding;
26278 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26279 len_encoding = 0x8;
26280 }
26281 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26282 len_encoding = 0x9;
26283 }
26284 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26285 len_encoding = 0x3;
26286 }
26287 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26288 (encoded_align_1.GetEncodingValue() << 4) |
26289 first.Encode(22, 12) | (len_encoding << 8) |
26290 (rn.GetCode() << 16));
26291 AdvanceIT();
26292 return;
26293 }
26294 }
26295 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26296 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26297 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26298 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26299 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026300 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026301 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026302 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26303 const DRegister& first = nreglist.GetFirstDRegister();
26304 uint32_t len_encoding;
26305 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26306 len_encoding = 0x8;
26307 }
26308 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26309 len_encoding = 0x9;
26310 }
26311 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26312 len_encoding = 0x3;
26313 }
26314 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26315 (encoded_align_1.GetEncodingValue() << 4) |
26316 first.Encode(22, 12) | (len_encoding << 8) |
26317 (rn.GetCode() << 16));
26318 AdvanceIT();
26319 return;
26320 }
26321 }
26322 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26323 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26324 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26325 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026326 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026327 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026328 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26329 const DRegister& first = nreglist.GetFirstDRegister();
26330 EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
26331 (encoded_align_2.GetEncodingValue() << 4) |
26332 first.Encode(22, 12) | (rn.GetCode() << 16));
26333 AdvanceIT();
26334 return;
26335 }
26336 }
26337 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26338 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26339 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26340 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026341 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026342 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026343 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26344 const DRegister& first = nreglist.GetFirstDRegister();
26345 EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
26346 (encoded_align_2.GetEncodingValue() << 4) |
26347 first.Encode(22, 12) | (rn.GetCode() << 16));
26348 AdvanceIT();
26349 return;
26350 }
26351 }
26352 } else {
26353 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26354 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26355 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26356 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26357 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026358 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026359 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026360 if (cond.Is(al)) {
26361 const DRegister& first = nreglist.GetFirstDRegister();
26362 uint32_t len_encoding;
26363 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26364 len_encoding = 0x8;
26365 }
26366 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26367 len_encoding = 0x9;
26368 }
26369 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26370 len_encoding = 0x3;
26371 }
26372 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26373 (encoded_align_1.GetEncodingValue() << 4) |
26374 first.Encode(22, 12) | (len_encoding << 8) |
26375 (rn.GetCode() << 16));
26376 return;
26377 }
26378 }
26379 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26380 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26381 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26382 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26383 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026384 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026385 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026386 if (cond.Is(al)) {
26387 const DRegister& first = nreglist.GetFirstDRegister();
26388 uint32_t len_encoding;
26389 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26390 len_encoding = 0x8;
26391 }
26392 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26393 len_encoding = 0x9;
26394 }
26395 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26396 len_encoding = 0x3;
26397 }
26398 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26399 (encoded_align_1.GetEncodingValue() << 4) |
26400 first.Encode(22, 12) | (len_encoding << 8) |
26401 (rn.GetCode() << 16));
26402 return;
26403 }
26404 }
26405 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26406 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26407 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26408 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026409 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026410 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026411 if (cond.Is(al)) {
26412 const DRegister& first = nreglist.GetFirstDRegister();
26413 EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
26414 (encoded_align_2.GetEncodingValue() << 4) |
26415 first.Encode(22, 12) | (rn.GetCode() << 16));
26416 return;
26417 }
26418 }
26419 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26420 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26421 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26422 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026423 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026424 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026425 if (cond.Is(al)) {
26426 const DRegister& first = nreglist.GetFirstDRegister();
26427 EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
26428 (encoded_align_2.GetEncodingValue() << 4) |
26429 first.Encode(22, 12) | (rn.GetCode() << 16));
26430 return;
26431 }
26432 }
26433 }
26434 }
26435 if (operand.IsPlainRegister()) {
26436 Register rn = operand.GetBaseRegister();
26437 Alignment align = operand.GetAlignment();
26438 Register rm = operand.GetOffsetRegister();
26439 Dt_size_7 encoded_dt(dt);
26440 Align_align_2 encoded_align_1(align, nreglist);
26441 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026442 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026443 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26444 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26445 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26446 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26447 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026448 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026449 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26450 const DRegister& first = nreglist.GetFirstDRegister();
26451 uint32_t len_encoding;
26452 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26453 len_encoding = 0x8;
26454 }
26455 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26456 len_encoding = 0x9;
26457 }
26458 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26459 len_encoding = 0x3;
26460 }
26461 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26462 (encoded_align_1.GetEncodingValue() << 4) |
26463 first.Encode(22, 12) | (len_encoding << 8) |
26464 (rn.GetCode() << 16) | rm.GetCode());
26465 AdvanceIT();
26466 return;
26467 }
26468 }
26469 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26470 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26471 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26472 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026473 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026474 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26475 const DRegister& first = nreglist.GetFirstDRegister();
26476 EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
26477 (encoded_align_2.GetEncodingValue() << 4) |
26478 first.Encode(22, 12) | (rn.GetCode() << 16) |
26479 rm.GetCode());
26480 AdvanceIT();
26481 return;
26482 }
26483 }
26484 } else {
26485 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26486 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26487 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26488 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26489 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026490 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026491 if (cond.Is(al)) {
26492 const DRegister& first = nreglist.GetFirstDRegister();
26493 uint32_t len_encoding;
26494 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26495 len_encoding = 0x8;
26496 }
26497 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26498 len_encoding = 0x9;
26499 }
26500 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26501 len_encoding = 0x3;
26502 }
26503 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26504 (encoded_align_1.GetEncodingValue() << 4) |
26505 first.Encode(22, 12) | (len_encoding << 8) |
26506 (rn.GetCode() << 16) | rm.GetCode());
26507 return;
26508 }
26509 }
26510 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26511 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26512 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26513 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026514 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026515 if (cond.Is(al)) {
26516 const DRegister& first = nreglist.GetFirstDRegister();
26517 EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
26518 (encoded_align_2.GetEncodingValue() << 4) |
26519 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26520 return;
26521 }
26522 }
26523 }
26524 }
26525 Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
26526}
26527
26528void Assembler::vst3(Condition cond,
26529 DataType dt,
26530 const NeonRegisterList& nreglist,
26531 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026532 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026533 CheckIT(cond);
26534 if (operand.IsImmediateZero()) {
26535 Register rn = operand.GetBaseRegister();
26536 Alignment align = operand.GetAlignment();
26537 Dt_size_7 encoded_dt(dt);
26538 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026539 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026540 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26541 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26542 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26543 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026544 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026545 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026546 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26547 const DRegister& first = nreglist.GetFirstDRegister();
26548 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26549 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26550 (encoded_align_1.GetEncodingValue() << 4) |
26551 first.Encode(22, 12) | (len_encoding << 8) |
26552 (rn.GetCode() << 16));
26553 AdvanceIT();
26554 return;
26555 }
26556 }
26557 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26558 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26559 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26560 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026561 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026562 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026563 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26564 const DRegister& first = nreglist.GetFirstDRegister();
26565 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26566 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26567 (encoded_align_1.GetEncodingValue() << 4) |
26568 first.Encode(22, 12) | (len_encoding << 8) |
26569 (rn.GetCode() << 16));
26570 AdvanceIT();
26571 return;
26572 }
26573 }
26574 } else {
26575 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26576 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26577 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26578 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026579 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026580 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026581 if (cond.Is(al)) {
26582 const DRegister& first = nreglist.GetFirstDRegister();
26583 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26584 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26585 (encoded_align_1.GetEncodingValue() << 4) |
26586 first.Encode(22, 12) | (len_encoding << 8) |
26587 (rn.GetCode() << 16));
26588 return;
26589 }
26590 }
26591 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26592 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26593 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26594 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026595 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026596 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026597 if (cond.Is(al)) {
26598 const DRegister& first = nreglist.GetFirstDRegister();
26599 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26600 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26601 (encoded_align_1.GetEncodingValue() << 4) |
26602 first.Encode(22, 12) | (len_encoding << 8) |
26603 (rn.GetCode() << 16));
26604 return;
26605 }
26606 }
26607 }
26608 }
26609 if (operand.IsPlainRegister()) {
26610 Register rn = operand.GetBaseRegister();
26611 Alignment align = operand.GetAlignment();
26612 Register rm = operand.GetOffsetRegister();
26613 Dt_size_7 encoded_dt(dt);
26614 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026615 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026616 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26617 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26618 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26619 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026620 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026621 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26622 const DRegister& first = nreglist.GetFirstDRegister();
26623 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26624 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26625 (encoded_align_1.GetEncodingValue() << 4) |
26626 first.Encode(22, 12) | (len_encoding << 8) |
26627 (rn.GetCode() << 16) | rm.GetCode());
26628 AdvanceIT();
26629 return;
26630 }
26631 }
26632 } else {
26633 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26634 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26635 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26636 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026637 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026638 if (cond.Is(al)) {
26639 const DRegister& first = nreglist.GetFirstDRegister();
26640 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26641 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26642 (encoded_align_1.GetEncodingValue() << 4) |
26643 first.Encode(22, 12) | (len_encoding << 8) |
26644 (rn.GetCode() << 16) | rm.GetCode());
26645 return;
26646 }
26647 }
26648 }
26649 }
26650 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26651}
26652
26653void Assembler::vst3(Condition cond,
26654 DataType dt,
26655 const NeonRegisterList& nreglist,
26656 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026657 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026658 CheckIT(cond);
26659 if (operand.IsImmediateZero()) {
26660 Register rn = operand.GetBaseRegister();
26661 Dt_size_7 encoded_dt(dt);
26662 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026663 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026664 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
26665 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26666 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26667 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026668 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026669 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26670 const DRegister& first = nreglist.GetFirstDRegister();
26671 EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
26672 (encoded_align_1.GetEncodingValue() << 4) |
26673 first.Encode(22, 12) | (rn.GetCode() << 16));
26674 AdvanceIT();
26675 return;
26676 }
26677 }
26678 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
26679 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26680 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26681 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070026682 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026683 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26684 const DRegister& first = nreglist.GetFirstDRegister();
26685 EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
26686 (encoded_align_1.GetEncodingValue() << 4) |
26687 first.Encode(22, 12) | (rn.GetCode() << 16));
26688 AdvanceIT();
26689 return;
26690 }
26691 }
26692 } else {
26693 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
26694 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26695 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26696 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026697 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026698 if (cond.Is(al)) {
26699 const DRegister& first = nreglist.GetFirstDRegister();
26700 EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
26701 (encoded_align_1.GetEncodingValue() << 4) |
26702 first.Encode(22, 12) | (rn.GetCode() << 16));
26703 return;
26704 }
26705 }
26706 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
26707 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26708 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26709 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070026710 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026711 if (cond.Is(al)) {
26712 const DRegister& first = nreglist.GetFirstDRegister();
26713 EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
26714 (encoded_align_1.GetEncodingValue() << 4) |
26715 first.Encode(22, 12) | (rn.GetCode() << 16));
26716 return;
26717 }
26718 }
26719 }
26720 }
26721 if (operand.IsPlainRegister()) {
26722 Register rn = operand.GetBaseRegister();
26723 Sign sign = operand.GetSign();
26724 Register rm = operand.GetOffsetRegister();
26725 Dt_size_7 encoded_dt(dt);
26726 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026727 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026728 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
26729 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26730 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26731 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026732 sign.IsPlus() && operand.IsPostIndex() &&
26733 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026734 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26735 const DRegister& first = nreglist.GetFirstDRegister();
26736 EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
26737 (encoded_align_1.GetEncodingValue() << 4) |
26738 first.Encode(22, 12) | (rn.GetCode() << 16) |
26739 rm.GetCode());
26740 AdvanceIT();
26741 return;
26742 }
26743 }
26744 } else {
26745 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
26746 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26747 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26748 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026749 sign.IsPlus() && operand.IsPostIndex() &&
26750 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026751 if (cond.Is(al)) {
26752 const DRegister& first = nreglist.GetFirstDRegister();
26753 EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
26754 (encoded_align_1.GetEncodingValue() << 4) |
26755 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26756 return;
26757 }
26758 }
26759 }
26760 }
26761 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26762}
26763
26764void Assembler::vst4(Condition cond,
26765 DataType dt,
26766 const NeonRegisterList& nreglist,
26767 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026768 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026769 CheckIT(cond);
26770 if (operand.IsImmediateZero()) {
26771 Register rn = operand.GetBaseRegister();
26772 Alignment align = operand.GetAlignment();
26773 Dt_size_7 encoded_dt(dt);
26774 Align_align_4 encoded_align_1(align);
26775 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026776 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026777 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26778 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26779 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26780 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026781 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026782 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026783 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26784 const DRegister& first = nreglist.GetFirstDRegister();
26785 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26786 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26787 (encoded_align_1.GetEncodingValue() << 4) |
26788 first.Encode(22, 12) | (len_encoding << 8) |
26789 (rn.GetCode() << 16));
26790 AdvanceIT();
26791 return;
26792 }
26793 }
26794 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26795 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26796 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26797 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026798 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026799 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026800 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26801 const DRegister& first = nreglist.GetFirstDRegister();
26802 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26803 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26804 (encoded_align_1.GetEncodingValue() << 4) |
26805 first.Encode(22, 12) | (len_encoding << 8) |
26806 (rn.GetCode() << 16));
26807 AdvanceIT();
26808 return;
26809 }
26810 }
26811 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26812 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26813 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26814 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026815 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026816 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026817 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26818 const DRegister& first = nreglist.GetFirstDRegister();
26819 EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
26820 (encoded_align_2.GetEncodingValue() << 4) |
26821 first.Encode(22, 12) | (rn.GetCode() << 16));
26822 AdvanceIT();
26823 return;
26824 }
26825 }
26826 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26827 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26828 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26829 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026830 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026831 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026832 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26833 const DRegister& first = nreglist.GetFirstDRegister();
26834 EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
26835 (encoded_align_2.GetEncodingValue() << 4) |
26836 first.Encode(22, 12) | (rn.GetCode() << 16));
26837 AdvanceIT();
26838 return;
26839 }
26840 }
26841 } else {
26842 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26843 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26844 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26845 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026846 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026847 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026848 if (cond.Is(al)) {
26849 const DRegister& first = nreglist.GetFirstDRegister();
26850 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26851 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26852 (encoded_align_1.GetEncodingValue() << 4) |
26853 first.Encode(22, 12) | (len_encoding << 8) |
26854 (rn.GetCode() << 16));
26855 return;
26856 }
26857 }
26858 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26859 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26860 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26861 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026862 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026863 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026864 if (cond.Is(al)) {
26865 const DRegister& first = nreglist.GetFirstDRegister();
26866 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26867 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26868 (encoded_align_1.GetEncodingValue() << 4) |
26869 first.Encode(22, 12) | (len_encoding << 8) |
26870 (rn.GetCode() << 16));
26871 return;
26872 }
26873 }
26874 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26875 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26876 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26877 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026878 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026879 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026880 if (cond.Is(al)) {
26881 const DRegister& first = nreglist.GetFirstDRegister();
26882 EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
26883 (encoded_align_2.GetEncodingValue() << 4) |
26884 first.Encode(22, 12) | (rn.GetCode() << 16));
26885 return;
26886 }
26887 }
26888 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26889 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26890 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26891 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026892 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026893 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026894 if (cond.Is(al)) {
26895 const DRegister& first = nreglist.GetFirstDRegister();
26896 EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
26897 (encoded_align_2.GetEncodingValue() << 4) |
26898 first.Encode(22, 12) | (rn.GetCode() << 16));
26899 return;
26900 }
26901 }
26902 }
26903 }
26904 if (operand.IsPlainRegister()) {
26905 Register rn = operand.GetBaseRegister();
26906 Alignment align = operand.GetAlignment();
26907 Register rm = operand.GetOffsetRegister();
26908 Dt_size_7 encoded_dt(dt);
26909 Align_align_4 encoded_align_1(align);
26910 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026911 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026912 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26913 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26914 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26915 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026916 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026917 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26918 const DRegister& first = nreglist.GetFirstDRegister();
26919 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26920 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26921 (encoded_align_1.GetEncodingValue() << 4) |
26922 first.Encode(22, 12) | (len_encoding << 8) |
26923 (rn.GetCode() << 16) | rm.GetCode());
26924 AdvanceIT();
26925 return;
26926 }
26927 }
26928 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26929 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26930 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26931 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026932 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026933 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26934 const DRegister& first = nreglist.GetFirstDRegister();
26935 EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
26936 (encoded_align_2.GetEncodingValue() << 4) |
26937 first.Encode(22, 12) | (rn.GetCode() << 16) |
26938 rm.GetCode());
26939 AdvanceIT();
26940 return;
26941 }
26942 }
26943 } else {
26944 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26945 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26946 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26947 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026948 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026949 if (cond.Is(al)) {
26950 const DRegister& first = nreglist.GetFirstDRegister();
26951 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26952 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26953 (encoded_align_1.GetEncodingValue() << 4) |
26954 first.Encode(22, 12) | (len_encoding << 8) |
26955 (rn.GetCode() << 16) | rm.GetCode());
26956 return;
26957 }
26958 }
26959 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26960 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26961 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26962 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026963 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026964 if (cond.Is(al)) {
26965 const DRegister& first = nreglist.GetFirstDRegister();
26966 EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
26967 (encoded_align_2.GetEncodingValue() << 4) |
26968 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26969 return;
26970 }
26971 }
26972 }
26973 }
26974 Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
26975}
26976
26977void Assembler::vstm(Condition cond,
26978 DataType dt,
26979 Register rn,
26980 WriteBack write_back,
26981 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026982 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026983 CheckIT(cond);
26984 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026985 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026986 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070026987 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
26988 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026989 const DRegister& dreg = dreglist.GetFirstDRegister();
26990 unsigned len = dreglist.GetLength() * 2;
26991 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
26992 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
26993 (len & 0xff));
26994 AdvanceIT();
26995 return;
26996 }
26997 } else {
26998 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070026999 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27000 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27001 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027002 const DRegister& dreg = dreglist.GetFirstDRegister();
27003 unsigned len = dreglist.GetLength() * 2;
27004 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27005 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27006 (len & 0xff));
27007 return;
27008 }
27009 }
27010 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
27011}
27012
27013void Assembler::vstm(Condition cond,
27014 DataType dt,
27015 Register rn,
27016 WriteBack write_back,
27017 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027018 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027019 CheckIT(cond);
27020 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027021 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027022 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027023 if ((!rn.IsPC() || AllowUnpredictable())) {
27024 const SRegister& sreg = sreglist.GetFirstSRegister();
27025 unsigned len = sreglist.GetLength();
27026 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27027 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27028 (len & 0xff));
27029 AdvanceIT();
27030 return;
27031 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010027032 } else {
27033 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027034 if (cond.IsNotNever() &&
27035 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027036 const SRegister& sreg = sreglist.GetFirstSRegister();
27037 unsigned len = sreglist.GetLength();
27038 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27039 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27040 (len & 0xff));
27041 return;
27042 }
27043 }
27044 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
27045}
27046
27047void Assembler::vstmdb(Condition cond,
27048 DataType dt,
27049 Register rn,
27050 WriteBack write_back,
27051 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027052 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027053 CheckIT(cond);
27054 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027055 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027056 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
27057 if (write_back.DoesWriteBack() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027058 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27059 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027060 const DRegister& dreg = dreglist.GetFirstDRegister();
27061 unsigned len = dreglist.GetLength() * 2;
27062 EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
27063 (len & 0xff));
27064 AdvanceIT();
27065 return;
27066 }
27067 } else {
27068 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
27069 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027070 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27071 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027072 const DRegister& dreg = dreglist.GetFirstDRegister();
27073 unsigned len = dreglist.GetLength() * 2;
27074 EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27075 dreg.Encode(22, 12) | (len & 0xff));
27076 return;
27077 }
27078 }
27079 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
27080}
27081
27082void Assembler::vstmdb(Condition cond,
27083 DataType dt,
27084 Register rn,
27085 WriteBack write_back,
27086 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027087 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027088 CheckIT(cond);
27089 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027090 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027091 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027092 if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027093 const SRegister& sreg = sreglist.GetFirstSRegister();
27094 unsigned len = sreglist.GetLength();
27095 EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
27096 (len & 0xff));
27097 AdvanceIT();
27098 return;
27099 }
27100 } else {
27101 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027102 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
27103 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027104 const SRegister& sreg = sreglist.GetFirstSRegister();
27105 unsigned len = sreglist.GetLength();
27106 EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27107 sreg.Encode(22, 12) | (len & 0xff));
27108 return;
27109 }
27110 }
27111 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
27112}
27113
27114void Assembler::vstmia(Condition cond,
27115 DataType dt,
27116 Register rn,
27117 WriteBack write_back,
27118 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027119 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027120 CheckIT(cond);
27121 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027122 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027123 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027124 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27125 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027126 const DRegister& dreg = dreglist.GetFirstDRegister();
27127 unsigned len = dreglist.GetLength() * 2;
27128 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27129 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27130 (len & 0xff));
27131 AdvanceIT();
27132 return;
27133 }
27134 } else {
27135 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027136 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27137 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27138 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027139 const DRegister& dreg = dreglist.GetFirstDRegister();
27140 unsigned len = dreglist.GetLength() * 2;
27141 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27142 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27143 (len & 0xff));
27144 return;
27145 }
27146 }
27147 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
27148}
27149
27150void Assembler::vstmia(Condition cond,
27151 DataType dt,
27152 Register rn,
27153 WriteBack write_back,
27154 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027155 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027156 CheckIT(cond);
27157 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027158 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027159 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027160 if ((!rn.IsPC() || AllowUnpredictable())) {
27161 const SRegister& sreg = sreglist.GetFirstSRegister();
27162 unsigned len = sreglist.GetLength();
27163 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27164 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27165 (len & 0xff));
27166 AdvanceIT();
27167 return;
27168 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010027169 } else {
27170 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027171 if (cond.IsNotNever() &&
27172 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027173 const SRegister& sreg = sreglist.GetFirstSRegister();
27174 unsigned len = sreglist.GetLength();
27175 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27176 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27177 (len & 0xff));
27178 return;
27179 }
27180 }
27181 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
27182}
27183
27184void Assembler::vstr(Condition cond,
27185 DataType dt,
27186 DRegister rd,
27187 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027188 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027189 CheckIT(cond);
27190 if (operand.IsImmediate()) {
27191 Register rn = operand.GetBaseRegister();
27192 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027193 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027194 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
27195 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliard8ecc7892017-09-08 09:49:29 -070027196 ((offset % 4) == 0) && operand.IsOffset() &&
27197 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027198 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27199 uint32_t offset_ = abs(offset) >> 2;
27200 EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27201 offset_ | (sign << 23));
27202 AdvanceIT();
27203 return;
27204 }
27205 } else {
27206 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
27207 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027208 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027209 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27210 uint32_t offset_ = abs(offset) >> 2;
27211 EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27212 (rn.GetCode() << 16) | offset_ | (sign << 23));
27213 return;
27214 }
27215 }
27216 }
27217 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27218}
27219
27220void Assembler::vstr(Condition cond,
27221 DataType dt,
27222 SRegister rd,
27223 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027224 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027225 CheckIT(cond);
27226 if (operand.IsImmediate()) {
27227 Register rn = operand.GetBaseRegister();
27228 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027229 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027230 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
27231 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliard8ecc7892017-09-08 09:49:29 -070027232 ((offset % 4) == 0) && operand.IsOffset() &&
27233 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027234 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27235 uint32_t offset_ = abs(offset) >> 2;
27236 EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27237 offset_ | (sign << 23));
27238 AdvanceIT();
27239 return;
27240 }
27241 } else {
27242 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
27243 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027244 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027245 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27246 uint32_t offset_ = abs(offset) >> 2;
27247 EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27248 (rn.GetCode() << 16) | offset_ | (sign << 23));
27249 return;
27250 }
27251 }
27252 }
27253 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27254}
27255
27256void Assembler::vsub(
27257 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027258 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027259 CheckIT(cond);
27260 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027261 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027262 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
27263 if (dt.Is(F32)) {
27264 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27265 EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27266 rm.Encode(5, 0));
27267 AdvanceIT();
27268 return;
27269 }
27270 }
27271 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
27272 if (dt.Is(F64)) {
27273 EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27274 rm.Encode(5, 0));
27275 AdvanceIT();
27276 return;
27277 }
27278 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27279 if (encoded_dt.IsValid()) {
27280 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27281 EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
27282 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27283 AdvanceIT();
27284 return;
27285 }
27286 }
27287 } else {
27288 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
27289 if (dt.Is(F32)) {
27290 if (cond.Is(al)) {
27291 EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27292 rm.Encode(5, 0));
27293 return;
27294 }
27295 }
27296 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
27297 if (dt.Is(F64) && cond.IsNotNever()) {
27298 EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27299 rn.Encode(7, 16) | rm.Encode(5, 0));
27300 return;
27301 }
27302 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27303 if (encoded_dt.IsValid()) {
27304 if (cond.Is(al)) {
27305 EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
27306 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27307 return;
27308 }
27309 }
27310 }
27311 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27312}
27313
27314void Assembler::vsub(
27315 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027316 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027317 CheckIT(cond);
27318 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027320 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
27321 if (dt.Is(F32)) {
27322 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27323 EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27324 rm.Encode(5, 0));
27325 AdvanceIT();
27326 return;
27327 }
27328 }
27329 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27330 if (encoded_dt.IsValid()) {
27331 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27332 EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
27333 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27334 AdvanceIT();
27335 return;
27336 }
27337 }
27338 } else {
27339 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
27340 if (dt.Is(F32)) {
27341 if (cond.Is(al)) {
27342 EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27343 rm.Encode(5, 0));
27344 return;
27345 }
27346 }
27347 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27348 if (encoded_dt.IsValid()) {
27349 if (cond.Is(al)) {
27350 EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
27351 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27352 return;
27353 }
27354 }
27355 }
27356 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27357}
27358
27359void Assembler::vsub(
27360 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027361 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027362 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027363 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027364 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
27365 if (dt.Is(F32)) {
27366 EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27367 rm.Encode(5, 0));
27368 AdvanceIT();
27369 return;
27370 }
27371 } else {
27372 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
27373 if (dt.Is(F32) && cond.IsNotNever()) {
27374 EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27375 rn.Encode(7, 16) | rm.Encode(5, 0));
27376 return;
27377 }
27378 }
27379 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27380}
27381
27382void Assembler::vsubhn(
27383 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027384 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027385 CheckIT(cond);
27386 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027387 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027388 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
27389 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27390 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27391 EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
27392 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27393 AdvanceIT();
27394 return;
27395 }
27396 }
27397 } else {
27398 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
27399 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27400 if (cond.Is(al)) {
27401 EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
27402 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27403 return;
27404 }
27405 }
27406 }
27407 Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
27408}
27409
27410void Assembler::vsubl(
27411 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027412 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027413 CheckIT(cond);
27414 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027415 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027416 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
27417 if (encoded_dt.IsValid()) {
27418 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27419 EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27420 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27421 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27422 AdvanceIT();
27423 return;
27424 }
27425 }
27426 } else {
27427 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
27428 if (encoded_dt.IsValid()) {
27429 if (cond.Is(al)) {
27430 EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27431 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27432 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27433 return;
27434 }
27435 }
27436 }
27437 Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
27438}
27439
27440void Assembler::vsubw(
27441 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027442 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027443 CheckIT(cond);
27444 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027445 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027446 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
27447 if (encoded_dt.IsValid()) {
27448 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27449 EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27450 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27451 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27452 AdvanceIT();
27453 return;
27454 }
27455 }
27456 } else {
27457 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
27458 if (encoded_dt.IsValid()) {
27459 if (cond.Is(al)) {
27460 EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27461 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27462 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27463 return;
27464 }
27465 }
27466 }
27467 Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
27468}
27469
27470void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027471 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027472 CheckIT(cond);
27473 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027474 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027475 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
27476 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27477 EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27478 AdvanceIT();
27479 return;
27480 }
27481 } else {
27482 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
27483 if (cond.Is(al)) {
27484 EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27485 return;
27486 }
27487 }
27488 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27489}
27490
27491void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027493 CheckIT(cond);
27494 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027495 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027496 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
27497 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27498 EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27499 AdvanceIT();
27500 return;
27501 }
27502 } else {
27503 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
27504 if (cond.Is(al)) {
27505 EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27506 return;
27507 }
27508 }
27509 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27510}
27511
27512void Assembler::vtbl(Condition cond,
27513 DataType dt,
27514 DRegister rd,
27515 const NeonRegisterList& nreglist,
27516 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027517 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027518 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027519 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027520 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27521 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27522 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27523 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27524 const DRegister& first = nreglist.GetFirstDRegister();
27525 uint32_t len_encoding = nreglist.GetLength() - 1;
27526 EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27527 (len_encoding << 8) | rm.Encode(5, 0));
27528 AdvanceIT();
27529 return;
27530 }
27531 }
27532 } else {
27533 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27534 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27535 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27536 if (cond.Is(al)) {
27537 const DRegister& first = nreglist.GetFirstDRegister();
27538 uint32_t len_encoding = nreglist.GetLength() - 1;
27539 EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27540 (len_encoding << 8) | rm.Encode(5, 0));
27541 return;
27542 }
27543 }
27544 }
27545 Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
27546}
27547
27548void Assembler::vtbx(Condition cond,
27549 DataType dt,
27550 DRegister rd,
27551 const NeonRegisterList& nreglist,
27552 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027553 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027554 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027555 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027556 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27557 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27558 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27559 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27560 const DRegister& first = nreglist.GetFirstDRegister();
27561 uint32_t len_encoding = nreglist.GetLength() - 1;
27562 EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27563 (len_encoding << 8) | rm.Encode(5, 0));
27564 AdvanceIT();
27565 return;
27566 }
27567 }
27568 } else {
27569 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27570 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27571 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27572 if (cond.Is(al)) {
27573 const DRegister& first = nreglist.GetFirstDRegister();
27574 uint32_t len_encoding = nreglist.GetLength() - 1;
27575 EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27576 (len_encoding << 8) | rm.Encode(5, 0));
27577 return;
27578 }
27579 }
27580 }
27581 Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
27582}
27583
27584void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027585 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027586 CheckIT(cond);
27587 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027588 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027589 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27590 if (encoded_dt.IsValid()) {
27591 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27592 EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
27593 rd.Encode(22, 12) | rm.Encode(5, 0));
27594 AdvanceIT();
27595 return;
27596 }
27597 }
27598 } else {
27599 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27600 if (encoded_dt.IsValid()) {
27601 if (cond.Is(al)) {
27602 EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
27603 rd.Encode(22, 12) | rm.Encode(5, 0));
27604 return;
27605 }
27606 }
27607 }
27608 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27609}
27610
27611void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027612 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027613 CheckIT(cond);
27614 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027615 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027616 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27617 if (encoded_dt.IsValid()) {
27618 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27619 EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
27620 rd.Encode(22, 12) | rm.Encode(5, 0));
27621 AdvanceIT();
27622 return;
27623 }
27624 }
27625 } else {
27626 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27627 if (encoded_dt.IsValid()) {
27628 if (cond.Is(al)) {
27629 EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
27630 rd.Encode(22, 12) | rm.Encode(5, 0));
27631 return;
27632 }
27633 }
27634 }
27635 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27636}
27637
27638void Assembler::vtst(
27639 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027640 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027641 CheckIT(cond);
27642 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027643 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027644 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27645 if (encoded_dt.IsValid()) {
27646 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27647 EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
27648 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27649 AdvanceIT();
27650 return;
27651 }
27652 }
27653 } else {
27654 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27655 if (encoded_dt.IsValid()) {
27656 if (cond.Is(al)) {
27657 EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
27658 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27659 return;
27660 }
27661 }
27662 }
27663 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27664}
27665
27666void Assembler::vtst(
27667 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027668 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027669 CheckIT(cond);
27670 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027671 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027672 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27673 if (encoded_dt.IsValid()) {
27674 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27675 EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
27676 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27677 AdvanceIT();
27678 return;
27679 }
27680 }
27681 } else {
27682 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27683 if (encoded_dt.IsValid()) {
27684 if (cond.Is(al)) {
27685 EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
27686 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27687 return;
27688 }
27689 }
27690 }
27691 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27692}
27693
27694void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027695 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027696 CheckIT(cond);
27697 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027698 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027699 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27700 if (encoded_dt.IsValid()) {
27701 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27702 EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
27703 rd.Encode(22, 12) | rm.Encode(5, 0));
27704 AdvanceIT();
27705 return;
27706 }
27707 }
27708 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27709 if (dt.Is(Untyped32)) {
27710 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27711 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27712 AdvanceIT();
27713 return;
27714 }
27715 }
27716 } else {
27717 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27718 if (encoded_dt.IsValid()) {
27719 if (cond.Is(al)) {
27720 EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
27721 rd.Encode(22, 12) | rm.Encode(5, 0));
27722 return;
27723 }
27724 }
27725 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27726 if (dt.Is(Untyped32)) {
27727 if (cond.Is(al)) {
27728 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27729 return;
27730 }
27731 }
27732 }
27733 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27734}
27735
27736void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027737 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027738 CheckIT(cond);
27739 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027740 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027741 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27742 if (encoded_dt.IsValid()) {
27743 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27744 EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
27745 rd.Encode(22, 12) | rm.Encode(5, 0));
27746 AdvanceIT();
27747 return;
27748 }
27749 }
27750 } else {
27751 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27752 if (encoded_dt.IsValid()) {
27753 if (cond.Is(al)) {
27754 EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
27755 rd.Encode(22, 12) | rm.Encode(5, 0));
27756 return;
27757 }
27758 }
27759 }
27760 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27761}
27762
27763void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027764 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027765 CheckIT(cond);
27766 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027767 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027768 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27769 if (encoded_dt.IsValid()) {
27770 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27771 EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
27772 rd.Encode(22, 12) | rm.Encode(5, 0));
27773 AdvanceIT();
27774 return;
27775 }
27776 }
27777 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27778 if (dt.Is(Untyped32)) {
27779 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27780 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27781 AdvanceIT();
27782 return;
27783 }
27784 }
27785 } else {
27786 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27787 if (encoded_dt.IsValid()) {
27788 if (cond.Is(al)) {
27789 EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
27790 rd.Encode(22, 12) | rm.Encode(5, 0));
27791 return;
27792 }
27793 }
27794 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27795 if (dt.Is(Untyped32)) {
27796 if (cond.Is(al)) {
27797 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27798 return;
27799 }
27800 }
27801 }
27802 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27803}
27804
27805void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027806 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027807 CheckIT(cond);
27808 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027809 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027810 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27811 if (encoded_dt.IsValid()) {
27812 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27813 EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
27814 rd.Encode(22, 12) | rm.Encode(5, 0));
27815 AdvanceIT();
27816 return;
27817 }
27818 }
27819 } else {
27820 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27821 if (encoded_dt.IsValid()) {
27822 if (cond.Is(al)) {
27823 EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
27824 rd.Encode(22, 12) | rm.Encode(5, 0));
27825 return;
27826 }
27827 }
27828 }
27829 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27830}
27831
27832void Assembler::yield(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027833 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027834 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027835 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027836 // YIELD{<c>}{<q>} ; T1
27837 if (!size.IsWide()) {
27838 EmitT32_16(0xbf10);
27839 AdvanceIT();
27840 return;
27841 }
27842 // YIELD{<c>}.W ; T2
27843 if (!size.IsNarrow()) {
27844 EmitT32_32(0xf3af8001U);
27845 AdvanceIT();
27846 return;
27847 }
27848 } else {
27849 // YIELD{<c>}{<q>} ; A1
27850 if (cond.IsNotNever()) {
27851 EmitA32(0x0320f001U | (cond.GetCondition() << 28));
27852 return;
27853 }
27854 }
27855 Delegate(kYield, &Assembler::yield, cond, size);
27856}
27857// End of generated code.
27858
27859} // namespace aarch32
27860} // namespace vixl