blob: fb153cd505558c7253ce25977bfe5118171e9eda [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()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -08001313 case F32:
1314 SetEncodingValue(0x2);
1315 break;
1316 default:
1317 break;
1318 }
1319}
1320
1321class Dt_size_17 : public EncodingValue {
1322 public:
1323 explicit Dt_size_17(DataType dt);
1324};
1325
1326Dt_size_17::Dt_size_17(DataType dt) {
1327 switch (dt.GetValue()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001328 case I8:
1329 SetEncodingValue(0x0);
1330 break;
1331 case I16:
1332 SetEncodingValue(0x1);
1333 break;
1334 case I32:
1335 SetEncodingValue(0x2);
1336 break;
1337 default:
1338 break;
1339 }
1340}
1341
1342class Index_1 : public EncodingValue {
1343 public:
1344 Index_1(const NeonRegisterList& nreglist, DataType dt);
1345};
1346
1347Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1348 switch (dt.GetValue()) {
1349 case Untyped8: {
1350 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1351 return;
1352 }
1353 uint32_t value = nreglist.GetTransferLane() << 1;
1354 if (!nreglist.IsSingleSpaced()) return;
1355 SetEncodingValue(value);
1356 break;
1357 }
1358 case Untyped16: {
1359 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1360 return;
1361 }
1362 uint32_t value = nreglist.GetTransferLane() << 2;
1363 if (nreglist.IsDoubleSpaced()) value |= 2;
1364 SetEncodingValue(value);
1365 break;
1366 }
1367 case Untyped32: {
1368 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1369 return;
1370 }
1371 uint32_t value = nreglist.GetTransferLane() << 3;
1372 if (nreglist.IsDoubleSpaced()) value |= 4;
1373 SetEncodingValue(value);
1374 break;
1375 }
1376 default:
1377 break;
1378 }
1379}
1380
1381class Align_index_align_1 : public EncodingValue {
1382 public:
1383 Align_index_align_1(Alignment align,
1384 const NeonRegisterList& nreglist,
1385 DataType dt);
1386};
1387
1388Align_index_align_1::Align_index_align_1(Alignment align,
1389 const NeonRegisterList& nreglist,
1390 DataType dt) {
1391 switch (dt.GetValue()) {
1392 case Untyped8: {
1393 uint32_t value;
1394 if (align.GetType() == kNoAlignment) {
1395 value = 0;
1396 } else {
1397 return;
1398 }
1399 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1400 return;
1401 }
1402 value |= nreglist.GetTransferLane() << 1;
1403 SetEncodingValue(value);
1404 break;
1405 }
1406 case Untyped16: {
1407 uint32_t value;
1408 if (align.GetType() == k16BitAlign) {
1409 value = 1;
1410 } else if (align.GetType() == kNoAlignment) {
1411 value = 0;
1412 } else {
1413 return;
1414 }
1415 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1416 return;
1417 }
1418 value |= nreglist.GetTransferLane() << 2;
1419 SetEncodingValue(value);
1420 break;
1421 }
1422 case Untyped32: {
1423 uint32_t value;
1424 if (align.GetType() == k32BitAlign) {
1425 value = 3;
1426 } else if (align.GetType() == kNoAlignment) {
1427 value = 0;
1428 } else {
1429 return;
1430 }
1431 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1432 return;
1433 }
1434 value |= nreglist.GetTransferLane() << 3;
1435 SetEncodingValue(value);
1436 break;
1437 }
1438 default:
1439 break;
1440 }
1441}
1442
1443class Align_index_align_2 : public EncodingValue {
1444 public:
1445 Align_index_align_2(Alignment align,
1446 const NeonRegisterList& nreglist,
1447 DataType dt);
1448};
1449
1450Align_index_align_2::Align_index_align_2(Alignment align,
1451 const NeonRegisterList& nreglist,
1452 DataType dt) {
1453 switch (dt.GetValue()) {
1454 case Untyped8: {
1455 uint32_t value;
1456 if (align.GetType() == k16BitAlign) {
1457 value = 1;
1458 } else if (align.GetType() == kNoAlignment) {
1459 value = 0;
1460 } else {
1461 return;
1462 }
1463 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1464 return;
1465 }
1466 value |= nreglist.GetTransferLane() << 1;
1467 if (!nreglist.IsSingleSpaced()) return;
1468 SetEncodingValue(value);
1469 break;
1470 }
1471 case Untyped16: {
1472 uint32_t value;
1473 if (align.GetType() == k32BitAlign) {
1474 value = 1;
1475 } else if (align.GetType() == kNoAlignment) {
1476 value = 0;
1477 } else {
1478 return;
1479 }
1480 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1481 return;
1482 }
1483 value |= nreglist.GetTransferLane() << 2;
1484 if (nreglist.IsDoubleSpaced()) value |= 2;
1485 SetEncodingValue(value);
1486 break;
1487 }
1488 case Untyped32: {
1489 uint32_t value;
1490 if (align.GetType() == k64BitAlign) {
1491 value = 1;
1492 } else if (align.GetType() == kNoAlignment) {
1493 value = 0;
1494 } else {
1495 return;
1496 }
1497 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1498 return;
1499 }
1500 value |= nreglist.GetTransferLane() << 3;
1501 if (nreglist.IsDoubleSpaced()) value |= 4;
1502 SetEncodingValue(value);
1503 break;
1504 }
1505 default:
1506 break;
1507 }
1508}
1509
1510class Align_index_align_3 : public EncodingValue {
1511 public:
1512 Align_index_align_3(Alignment align,
1513 const NeonRegisterList& nreglist,
1514 DataType dt);
1515};
1516
1517Align_index_align_3::Align_index_align_3(Alignment align,
1518 const NeonRegisterList& nreglist,
1519 DataType dt) {
1520 switch (dt.GetValue()) {
1521 case Untyped8: {
1522 uint32_t value;
1523 if (align.GetType() == k32BitAlign) {
1524 value = 1;
1525 } else if (align.GetType() == kNoAlignment) {
1526 value = 0;
1527 } else {
1528 return;
1529 }
1530 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1531 return;
1532 }
1533 value |= nreglist.GetTransferLane() << 1;
1534 if (!nreglist.IsSingleSpaced()) return;
1535 SetEncodingValue(value);
1536 break;
1537 }
1538 case Untyped16: {
1539 uint32_t value;
1540 if (align.GetType() == k64BitAlign) {
1541 value = 1;
1542 } else if (align.GetType() == kNoAlignment) {
1543 value = 0;
1544 } else {
1545 return;
1546 }
1547 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1548 return;
1549 }
1550 value |= nreglist.GetTransferLane() << 2;
1551 if (nreglist.IsDoubleSpaced()) value |= 2;
1552 SetEncodingValue(value);
1553 break;
1554 }
1555 case Untyped32: {
1556 uint32_t value;
1557 if (align.GetType() == k64BitAlign) {
1558 value = 1;
1559 } else if (align.GetType() == k128BitAlign) {
1560 value = 2;
1561 } else if (align.GetType() == kNoAlignment) {
1562 value = 0;
1563 } else {
1564 return;
1565 }
1566 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1567 return;
1568 }
1569 value |= nreglist.GetTransferLane() << 3;
1570 if (nreglist.IsDoubleSpaced()) value |= 4;
1571 SetEncodingValue(value);
1572 break;
1573 }
1574 default:
1575 break;
1576 }
1577}
1578
1579class Align_a_1 : public EncodingValue {
1580 public:
1581 Align_a_1(Alignment align, DataType dt);
1582};
1583
1584Align_a_1::Align_a_1(Alignment align, DataType dt) {
1585 switch (align.GetType()) {
1586 case k16BitAlign:
1587 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1588 break;
1589 case k32BitAlign:
1590 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1591 break;
1592 case kNoAlignment:
1593 SetEncodingValue(0x0);
1594 break;
1595 default:
1596 break;
1597 }
1598}
1599
1600class Align_a_2 : public EncodingValue {
1601 public:
1602 Align_a_2(Alignment align, DataType dt);
1603};
1604
1605Align_a_2::Align_a_2(Alignment align, DataType dt) {
1606 switch (align.GetType()) {
1607 case k16BitAlign:
1608 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1609 break;
1610 case k32BitAlign:
1611 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1612 break;
1613 case k64BitAlign:
1614 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1615 break;
1616 case kNoAlignment:
1617 SetEncodingValue(0x0);
1618 break;
1619 default:
1620 break;
1621 }
1622}
1623
1624class Align_a_3 : public EncodingValue {
1625 public:
1626 Align_a_3(Alignment align, DataType dt);
1627};
1628
1629Align_a_3::Align_a_3(Alignment align, DataType dt) {
1630 switch (align.GetType()) {
1631 case k32BitAlign:
1632 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1633 break;
1634 case k64BitAlign:
1635 if (dt.Is(Untyped16))
1636 SetEncodingValue(0x1);
1637 else if (dt.Is(Untyped32))
1638 SetEncodingValue(0x1);
1639 break;
1640 case k128BitAlign:
1641 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1642 break;
1643 case kNoAlignment:
1644 SetEncodingValue(0x0);
1645 break;
1646 default:
1647 break;
1648 }
1649}
1650
1651class Align_align_1 : public EncodingValue {
1652 public:
1653 Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1654};
1655
1656Align_align_1::Align_align_1(Alignment align,
1657 const NeonRegisterList& nreglist) {
1658 switch (align.GetType()) {
1659 case k64BitAlign:
1660 SetEncodingValue(0x1);
1661 break;
1662 case k128BitAlign:
1663 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1664 SetEncodingValue(0x2);
1665 break;
1666 case k256BitAlign:
1667 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1668 SetEncodingValue(0x3);
1669 break;
1670 case kNoAlignment:
1671 SetEncodingValue(0x0);
1672 break;
1673 default:
1674 break;
1675 }
1676}
1677
1678class Align_align_2 : public EncodingValue {
1679 public:
1680 Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1681};
1682
1683Align_align_2::Align_align_2(Alignment align,
1684 const NeonRegisterList& nreglist) {
1685 switch (align.GetType()) {
1686 case k64BitAlign:
1687 SetEncodingValue(0x1);
1688 break;
1689 case k128BitAlign:
1690 SetEncodingValue(0x2);
1691 break;
1692 case k256BitAlign:
1693 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1694 break;
1695 case kNoAlignment:
1696 SetEncodingValue(0x0);
1697 break;
1698 default:
1699 break;
1700 }
1701}
1702
1703class Align_align_3 : public EncodingValue {
1704 public:
1705 explicit Align_align_3(Alignment align);
1706};
1707
1708Align_align_3::Align_align_3(Alignment align) {
1709 switch (align.GetType()) {
1710 case k64BitAlign:
1711 SetEncodingValue(0x1);
1712 break;
1713 case kNoAlignment:
1714 SetEncodingValue(0x0);
1715 break;
1716 default:
1717 break;
1718 }
1719}
1720
1721class Align_align_4 : public EncodingValue {
1722 public:
1723 explicit Align_align_4(Alignment align);
1724};
1725
1726Align_align_4::Align_align_4(Alignment align) {
1727 switch (align.GetType()) {
1728 case k64BitAlign:
1729 SetEncodingValue(0x1);
1730 break;
1731 case k128BitAlign:
1732 SetEncodingValue(0x2);
1733 break;
1734 case k256BitAlign:
1735 SetEncodingValue(0x3);
1736 break;
1737 case kNoAlignment:
1738 SetEncodingValue(0x0);
1739 break;
1740 default:
1741 break;
1742 }
1743}
1744
1745class Align_align_5 : public EncodingValue {
1746 public:
1747 Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1748};
1749
1750Align_align_5::Align_align_5(Alignment align,
1751 const NeonRegisterList& nreglist) {
1752 switch (align.GetType()) {
1753 case k64BitAlign:
1754 SetEncodingValue(0x1);
1755 break;
1756 case k128BitAlign:
1757 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1758 SetEncodingValue(0x2);
1759 break;
1760 case k256BitAlign:
1761 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1762 break;
1763 case kNoAlignment:
1764 SetEncodingValue(0x0);
1765 break;
1766 default:
1767 break;
1768 }
1769}
1770
Vincent Belliardac285442017-05-16 09:26:45 -07001771
1772// CBNZ{<q>} <Rn>, <label> ; T1
1773// CBZ{<q>} <Rn>, <label> ; T1
1774static const struct ReferenceInfo kT16CbzInfo =
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001775 {k16BitT32InstructionSizeInBytes,
1776 0, // Min offset.
1777 126, // Max offset.
1778 2, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001779 ReferenceInfo::kDontAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001780
1781
1782// B<c>{<q>} <label> ; T1
1783static const struct ReferenceInfo kT16ConditionalBranchInfo =
1784 {k16BitT32InstructionSizeInBytes,
1785 -256, // Min offset.
1786 254, // Max offset.
1787 2, // Alignment.
1788 ReferenceInfo::kDontAlignPc};
1789
1790
1791// ADR{<c>}{<q>} <Rd>, <label> ; T1
1792// LDR{<c>}{<q>} <Rt>, <label> ; T1
1793static const struct ReferenceInfo kT16DataInfo =
1794 {k16BitT32InstructionSizeInBytes,
1795 0, // Min offset.
1796 1020, // Max offset.
1797 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001798 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001799
1800
1801// B{<c>}{<q>} <label> ; T2
1802static const struct ReferenceInfo kT16BranchInfo =
1803 {k16BitT32InstructionSizeInBytes,
1804 -2048, // Min offset.
1805 2046, // Max offset.
1806 2, // Alignment.
1807 ReferenceInfo::kDontAlignPc};
1808
1809
1810// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
1811// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
1812// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
1813static const struct ReferenceInfo kT32DataInfo =
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001814 {k32BitT32InstructionSizeInBytes,
1815 -1020, // Min offset.
1816 1020, // Max offset.
1817 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001818 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001819
1820
1821// ADR{<c>}{<q>} <Rd>, <label> ; T3
1822// LDR{<c>}{<q>} <Rt>, <label> ; T2
1823// LDRB{<c>}{<q>} <Rt>, <label> ; T1
1824// LDRH{<c>}{<q>} <Rt>, <label> ; T1
1825// LDRSB{<c>}{<q>} <Rt>, <label> ; T1
1826// LDRSH{<c>}{<q>} <Rt>, <label> ; T1
1827// PLD{<c>}{<q>} <label> ; T1
1828// PLI{<c>}{<q>} <label> ; T3
1829static const struct ReferenceInfo kT32FarDataInfo =
1830 {k32BitT32InstructionSizeInBytes,
1831 -4095, // Min offset.
1832 4095, // Max offset.
1833 1, // Alignment.
1834 ReferenceInfo::kAlignPc};
1835
1836
1837// B<c>{<q>} <label> ; T3
1838static const struct ReferenceInfo kT32ConditionalBranchInfo =
1839 {k32BitT32InstructionSizeInBytes,
1840 -1048576, // Min offset.
1841 1048574, // Max offset.
1842 2, // Alignment.
1843 ReferenceInfo::kDontAlignPc};
1844
1845
1846// B{<c>}{<q>} <label> ; T4
1847// BL{<c>}{<q>} <label> ; T1
1848static const struct ReferenceInfo kT32BranchInfo =
1849 {k32BitT32InstructionSizeInBytes,
1850 -16777216, // Min offset.
1851 16777214, // Max offset.
1852 2, // Alignment.
1853 ReferenceInfo::kDontAlignPc};
1854
1855
1856// BLX{<c>}{<q>} <label> ; T2
1857static const struct ReferenceInfo kT32BlxInfo =
1858 {k32BitT32InstructionSizeInBytes,
1859 -16777216, // Min offset.
1860 16777212, // Max offset.
1861 4, // Alignment.
1862 ReferenceInfo::kAlignPc};
1863
1864
1865// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
1866// LDRH{<c>}{<q>} <Rt>, <label> ; A1
1867// LDRSB{<c>}{<q>} <Rt>, <label> ; A1
1868// LDRSH{<c>}{<q>} <Rt>, <label> ; A1
1869static const struct ReferenceInfo kA32VeryNearDataInfo =
1870 {kA32InstructionSizeInBytes,
1871 -255, // Min offset.
1872 255, // Max offset.
1873 1, // Alignment.
1874 ReferenceInfo::kAlignPc};
1875
1876
1877// ADR{<c>}{<q>} <Rd>, <label> ; A1
1878static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes,
1879 -256, // Min offset.
1880 256, // Max offset.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001881 1, // Alignment.
1882 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001883
1884
1885// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
1886// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
1887static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes,
1888 -1020, // Min offset.
1889 1020, // Max offset.
1890 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001891 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001892
1893
1894// LDR{<c>}{<q>} <Rt>, <label> ; A1
1895// LDRB{<c>}{<q>} <Rt>, <label> ; A1
1896// PLD{<c>}{<q>} <label> ; A1
1897// PLI{<c>}{<q>} <label> ; A1
1898static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes,
1899 -4095, // Min offset.
1900 4095, // Max offset.
1901 1, // Alignment.
1902 ReferenceInfo::kAlignPc};
1903
1904
1905// B{<c>}{<q>} <label> ; A1
1906// BL{<c>}{<q>} <label> ; A1
1907static const struct ReferenceInfo kA32BranchInfo =
1908 {kA32InstructionSizeInBytes,
1909 -33554432, // Min offset.
1910 33554428, // Max offset.
1911 4, // Alignment.
1912 ReferenceInfo::kDontAlignPc};
1913
1914
1915// BLX{<c>}{<q>} <label> ; A2
1916static const struct ReferenceInfo kA32BlxInfo = {kA32InstructionSizeInBytes,
1917 -33554432, // Min offset.
1918 33554430, // Max offset.
1919 2, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001920 ReferenceInfo::kAlignPc};
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001921
Alexandre Ramesd3832962016-07-04 15:03:43 +01001922
1923void Assembler::adc(Condition cond,
1924 EncodingSize size,
1925 Register rd,
1926 Register rn,
1927 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07001928 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01001929 CheckIT(cond);
1930 if (operand.IsImmediate()) {
1931 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001932 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001933 ImmediateT32 immediate_t32(imm);
1934 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08001935 if (!size.IsNarrow() && immediate_t32.IsValid() &&
1936 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001937 EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1938 (immediate_t32.GetEncodingValue() & 0xff) |
1939 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1940 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1941 AdvanceIT();
1942 return;
1943 }
1944 } else {
1945 ImmediateA32 immediate_a32(imm);
1946 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1947 if (immediate_a32.IsValid() && cond.IsNotNever()) {
1948 EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1949 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1950 immediate_a32.GetEncodingValue());
1951 return;
1952 }
1953 }
1954 }
1955 if (operand.IsImmediateShiftedRegister()) {
1956 Register rm = operand.GetBaseRegister();
1957 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001958 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001959 // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1960 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1961 rm.IsLow()) {
1962 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1963 AdvanceIT();
1964 return;
1965 }
1966 }
1967 }
1968 Shift shift = operand.GetShift();
1969 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001970 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001971 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08001972 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1973 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001974 uint32_t amount_ = amount % 32;
1975 EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1976 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1977 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1978 AdvanceIT();
1979 return;
1980 }
1981 } else {
1982 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1983 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1984 uint32_t amount_ = amount % 32;
1985 EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1986 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1987 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1988 return;
1989 }
1990 }
1991 }
1992 if (operand.IsRegisterShiftedRegister()) {
1993 Register rm = operand.GetBaseRegister();
1994 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00001995 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001996 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001997 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00001998 if (cond.IsNotNever() &&
1999 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2000 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002001 EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
2002 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002003 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002004 return;
2005 }
2006 }
2007 }
2008 Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
2009}
2010
2011void Assembler::adcs(Condition cond,
2012 EncodingSize size,
2013 Register rd,
2014 Register rn,
2015 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002016 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002017 CheckIT(cond);
2018 if (operand.IsImmediate()) {
2019 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002020 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002021 ImmediateT32 immediate_t32(imm);
2022 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08002023 if (!size.IsNarrow() && immediate_t32.IsValid() &&
2024 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002025 EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2026 (immediate_t32.GetEncodingValue() & 0xff) |
2027 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2028 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2029 AdvanceIT();
2030 return;
2031 }
2032 } else {
2033 ImmediateA32 immediate_a32(imm);
2034 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2035 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2036 EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
2037 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2038 immediate_a32.GetEncodingValue());
2039 return;
2040 }
2041 }
2042 }
2043 if (operand.IsImmediateShiftedRegister()) {
2044 Register rm = operand.GetBaseRegister();
2045 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002046 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002047 // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2048 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2049 rm.IsLow()) {
2050 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
2051 AdvanceIT();
2052 return;
2053 }
2054 }
2055 }
2056 Shift shift = operand.GetShift();
2057 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002058 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002059 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002060 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2061 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002062 uint32_t amount_ = amount % 32;
2063 EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2064 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2065 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2066 AdvanceIT();
2067 return;
2068 }
2069 } else {
2070 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2071 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2072 uint32_t amount_ = amount % 32;
2073 EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
2074 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2075 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2076 return;
2077 }
2078 }
2079 }
2080 if (operand.IsRegisterShiftedRegister()) {
2081 Register rm = operand.GetBaseRegister();
2082 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002083 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002084 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002085 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002086 if (cond.IsNotNever() &&
2087 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2088 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002089 EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
2090 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002091 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002092 return;
2093 }
2094 }
2095 }
2096 Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
2097}
2098
2099void Assembler::add(Condition cond,
2100 EncodingSize size,
2101 Register rd,
2102 Register rn,
2103 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002104 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002105 CheckIT(cond);
2106 if (operand.IsImmediate()) {
2107 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002108 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002109 ImmediateT32 immediate_t32(imm);
2110 // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
2111 if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
2112 ((imm % 4) == 0)) {
2113 uint32_t imm_ = imm >> 2;
2114 EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
2115 AdvanceIT();
2116 return;
2117 }
2118 // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
2119 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2120 (imm <= 7)) {
2121 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2122 AdvanceIT();
2123 return;
2124 }
2125 // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2126 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2127 (imm <= 255)) {
2128 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2129 AdvanceIT();
2130 return;
2131 }
2132 // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
2133 if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
2134 ((imm % 4) == 0)) {
2135 uint32_t imm_ = imm >> 2;
2136 EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2137 AdvanceIT();
2138 return;
2139 }
2140 // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2141 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2142 ((imm % 4) == 0)) {
2143 uint32_t imm_ = imm >> 2;
2144 EmitT32_16(0xb000 | imm_);
2145 AdvanceIT();
2146 return;
2147 }
2148 // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002149 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002150 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002151 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2152 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2153 AdvanceIT();
2154 return;
2155 }
2156 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002157 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2158 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002159 EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2160 (immediate_t32.GetEncodingValue() & 0xff) |
2161 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2162 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2163 AdvanceIT();
2164 return;
2165 }
2166 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002167 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002168 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002169 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2170 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2171 AdvanceIT();
2172 return;
2173 }
2174 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002175 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002176 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002177 EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2178 (immediate_t32.GetEncodingValue() & 0xff) |
2179 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2180 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2181 AdvanceIT();
2182 return;
2183 }
2184 // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002185 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002186 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002187 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2188 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2189 AdvanceIT();
2190 return;
2191 }
2192 } else {
2193 ImmediateA32 immediate_a32(imm);
2194 // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2195 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2196 EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2197 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2198 return;
2199 }
2200 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2201 if (immediate_a32.IsValid() && cond.IsNotNever() &&
2202 ((rn.GetCode() & 0xd) != 0xd)) {
2203 EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2204 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2205 immediate_a32.GetEncodingValue());
2206 return;
2207 }
2208 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2209 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2210 EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2211 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2212 return;
2213 }
2214 }
2215 }
2216 if (operand.IsImmediateShiftedRegister()) {
2217 Register rm = operand.GetBaseRegister();
2218 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002219 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002220 // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2221 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2222 rm.IsLow()) {
2223 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2224 (rm.GetCode() << 6));
2225 AdvanceIT();
2226 return;
2227 }
2228 // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002229 if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
2230 (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2231 (!rd.IsPC() || !rm.IsPC())) ||
2232 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002233 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2234 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2235 AdvanceIT();
2236 return;
2237 }
2238 // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08002239 if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002240 ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
Vincent Belliardd17e3482016-11-22 15:46:43 -08002241 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002242 EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2243 ((rd.GetCode() & 0x8) << 4));
2244 AdvanceIT();
2245 return;
2246 }
2247 // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2248 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2249 EmitT32_16(0x4485 | (rm.GetCode() << 3));
2250 AdvanceIT();
2251 return;
2252 }
2253 }
2254 }
2255 Shift shift = operand.GetShift();
2256 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002257 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002258 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002259 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2260 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002261 uint32_t amount_ = amount % 32;
2262 EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2263 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2264 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2265 AdvanceIT();
2266 return;
2267 }
2268 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002269 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2270 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002271 uint32_t amount_ = amount % 32;
2272 EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2273 (operand.GetTypeEncodingValue() << 4) |
2274 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2275 AdvanceIT();
2276 return;
2277 }
2278 } else {
2279 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2280 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2281 uint32_t amount_ = amount % 32;
2282 EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2283 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2284 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2285 return;
2286 }
2287 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2288 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2289 uint32_t amount_ = amount % 32;
2290 EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2291 (rd.GetCode() << 12) | rm.GetCode() |
2292 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2293 return;
2294 }
2295 }
2296 }
2297 if (operand.IsRegisterShiftedRegister()) {
2298 Register rm = operand.GetBaseRegister();
2299 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002300 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002301 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002302 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002303 if (cond.IsNotNever() &&
2304 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2305 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002306 EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2307 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002308 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002309 return;
2310 }
2311 }
2312 }
2313 Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2314}
2315
2316void Assembler::add(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002317 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002318 CheckIT(cond);
2319 if (operand.IsImmediate()) {
2320 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002321 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002322 // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2323 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2324 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2325 AdvanceIT();
2326 return;
2327 }
2328 }
2329 }
2330 if (operand.IsPlainRegister()) {
2331 Register rm = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002332 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002333 // ADD<c>{<q>} <Rdn>, <Rm> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002334 if (InITBlock() && !rm.Is(sp) &&
2335 (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2336 (!rd.IsPC() || !rm.IsPC())) ||
2337 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002338 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2339 (rm.GetCode() << 3));
2340 AdvanceIT();
2341 return;
2342 }
2343 }
2344 }
2345 Delegate(kAdd, &Assembler::add, cond, rd, operand);
2346}
2347
2348void Assembler::adds(Condition cond,
2349 EncodingSize size,
2350 Register rd,
2351 Register rn,
2352 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002353 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002354 CheckIT(cond);
2355 if (operand.IsImmediate()) {
2356 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002357 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002358 ImmediateT32 immediate_t32(imm);
2359 // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2360 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2361 (imm <= 7)) {
2362 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2363 AdvanceIT();
2364 return;
2365 }
2366 // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2367 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2368 (imm <= 255)) {
2369 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2370 AdvanceIT();
2371 return;
2372 }
2373 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2374 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002375 !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002376 EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2377 (immediate_t32.GetEncodingValue() & 0xff) |
2378 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2379 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2380 AdvanceIT();
2381 return;
2382 }
2383 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2384 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2385 !rd.Is(pc)) {
2386 EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2387 (immediate_t32.GetEncodingValue() & 0xff) |
2388 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2389 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2390 AdvanceIT();
2391 return;
2392 }
2393 } else {
2394 ImmediateA32 immediate_a32(imm);
2395 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2396 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2397 EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2398 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2399 immediate_a32.GetEncodingValue());
2400 return;
2401 }
2402 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2403 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2404 EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2405 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2406 return;
2407 }
2408 }
2409 }
2410 if (operand.IsImmediateShiftedRegister()) {
2411 Register rm = operand.GetBaseRegister();
2412 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002413 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002414 // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2415 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2416 rm.IsLow()) {
2417 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2418 (rm.GetCode() << 6));
2419 AdvanceIT();
2420 return;
2421 }
2422 }
2423 }
2424 Shift shift = operand.GetShift();
2425 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002426 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002427 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2428 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
Vincent Belliardd17e3482016-11-22 15:46:43 -08002429 !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002430 uint32_t amount_ = amount % 32;
2431 EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2432 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2433 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2434 AdvanceIT();
2435 return;
2436 }
2437 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2438 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002439 !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002440 uint32_t amount_ = amount % 32;
2441 EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2442 (operand.GetTypeEncodingValue() << 4) |
2443 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2444 AdvanceIT();
2445 return;
2446 }
2447 } else {
2448 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2449 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2450 uint32_t amount_ = amount % 32;
2451 EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2452 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2453 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2454 return;
2455 }
2456 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2457 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2458 uint32_t amount_ = amount % 32;
2459 EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2460 (rd.GetCode() << 12) | rm.GetCode() |
2461 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2462 return;
2463 }
2464 }
2465 }
2466 if (operand.IsRegisterShiftedRegister()) {
2467 Register rm = operand.GetBaseRegister();
2468 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002469 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002470 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002471 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002472 if (cond.IsNotNever() &&
2473 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2474 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002475 EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2476 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002477 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002478 return;
2479 }
2480 }
2481 }
2482 Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2483}
2484
2485void Assembler::adds(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002486 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002487 CheckIT(al);
2488 if (operand.IsImmediate()) {
2489 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002490 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002491 // ADDS{<q>} <Rdn>, #<imm8> ; T2
2492 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2493 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2494 AdvanceIT();
2495 return;
2496 }
2497 }
2498 }
2499 Delegate(kAdds, &Assembler::adds, rd, operand);
2500}
2501
2502void Assembler::addw(Condition cond,
2503 Register rd,
2504 Register rn,
2505 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002506 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002507 CheckIT(cond);
2508 if (operand.IsImmediate()) {
2509 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002510 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002511 // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08002512 if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002513 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2514 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2515 AdvanceIT();
2516 return;
2517 }
2518 // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002519 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002520 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002521 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2522 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2523 AdvanceIT();
2524 return;
2525 }
2526 // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
Vincent Belliard942e3b72016-11-29 15:50:14 -08002527 if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002528 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2529 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2530 AdvanceIT();
2531 return;
2532 }
2533 }
2534 }
2535 Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2536}
2537
2538void Assembler::adr(Condition cond,
2539 EncodingSize size,
2540 Register rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002541 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002542 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002543 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002544 Location::Offset offset =
2545 location->IsBound()
2546 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01002547 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2548 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002549 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002550 int32_t neg_offset = -offset;
2551 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2552 if (!size.IsWide() && rd.IsLow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002553 ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002554 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002555 (!location->IsBound() && size.IsNarrow()))) {
2556 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002557 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002558 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002559 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002560 Location::Offset pc,
2561 const Location* location) const VIXL_OVERRIDE {
2562 pc += kT32PcDelta;
2563 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002564 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2565 ((offset & 0x3) == 0));
2566 const int32_t target = offset >> 2;
2567 return instr | (target & 0xff);
2568 }
2569 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002570 EmitT32_16(
Vincent Belliardac285442017-05-16 09:26:45 -07002571 Link(0xa000 | (rd.GetCode() << 8), location, immop, &kT16DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002572 AdvanceIT();
2573 return;
2574 }
2575 // ADR{<c>}{<q>} <Rd>, <label> ; T2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002576 if (!size.IsNarrow() && location->IsBound() && (neg_offset > 0) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002577 (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002578 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2579 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2580 AdvanceIT();
2581 return;
2582 }
2583 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2584 if (!size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002585 (!location->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002586 (!rd.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002587 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002588 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002589 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002590 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002591 Location::Offset pc,
2592 const Location* location) const VIXL_OVERRIDE {
2593 pc += kT32PcDelta;
2594 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002595 int32_t target;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00002596 if ((offset >= 0) && (offset <= 4095)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002597 target = offset;
2598 } else {
2599 target = -offset;
2600 VIXL_ASSERT((target >= 0) && (target <= 4095));
2601 // Emit the T2 encoding.
2602 instr |= 0x00a00000;
2603 }
2604 return instr | (target & 0xff) | ((target & 0x700) << 4) |
2605 ((target & 0x800) << 15);
2606 }
2607 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002608 EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8),
2609 location,
2610 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07002611 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002612 AdvanceIT();
2613 return;
2614 }
2615 } else {
2616 ImmediateA32 positive_immediate_a32(offset);
2617 ImmediateA32 negative_immediate_a32(-offset);
2618 // ADR{<c>}{<q>} <Rd>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002619 if ((!location->IsBound() || positive_immediate_a32.IsValid()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002620 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002621 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002622 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002623 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002624 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002625 Location::Offset pc,
2626 const Location* location) const VIXL_OVERRIDE {
2627 pc += kA32PcDelta;
2628 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002629 int32_t target;
2630 ImmediateA32 positive_immediate_a32(offset);
2631 if (positive_immediate_a32.IsValid()) {
2632 target = positive_immediate_a32.GetEncodingValue();
2633 } else {
2634 ImmediateA32 negative_immediate_a32(-offset);
2635 VIXL_ASSERT(negative_immediate_a32.IsValid());
2636 // Emit the A2 encoding.
2637 target = negative_immediate_a32.GetEncodingValue();
2638 instr = (instr & ~0x00f00000) | 0x00400000;
2639 }
2640 return instr | (target & 0xfff);
2641 }
2642 } immop;
2643 EmitA32(
2644 Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002645 location,
2646 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07002647 &kA32AdrInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002648 return;
2649 }
2650 // ADR{<c>}{<q>} <Rd>, <label> ; A2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002651 if (location->IsBound() && negative_immediate_a32.IsValid() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002652 cond.IsNotNever()) {
2653 EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2654 negative_immediate_a32.GetEncodingValue());
2655 return;
2656 }
2657 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002658 Delegate(kAdr, &Assembler::adr, cond, size, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002659}
2660
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002661bool Assembler::adr_info(Condition cond,
2662 EncodingSize size,
2663 Register rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002664 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002665 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002666 VIXL_ASSERT(!location->IsBound());
2667 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002668 if (IsUsingT32()) {
2669 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2670 if (!size.IsWide() && rd.IsLow() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002671 *info = &kT16DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002672 return true;
2673 }
2674 // Skipped T2, as it is a negative offset variant.
2675 // The minimum offset is included in the corresponding
2676 // positive variant.
2677 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2678 if (!size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002679 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002680 return true;
2681 }
2682 } else {
2683 // ADR{<c>}{<q>} <Rd>, <label> ; A1
2684 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002685 *info = &kA32AdrInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002686 return true;
2687 }
2688 // Skipped A2, as it is a negative offset variant.
2689 // The minimum offset is included in the corresponding
2690 // positive variant.
2691 }
2692 return false;
2693}
2694
Alexandre Ramesd3832962016-07-04 15:03:43 +01002695void Assembler::and_(Condition cond,
2696 EncodingSize size,
2697 Register rd,
2698 Register rn,
2699 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002700 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002701 CheckIT(cond);
2702 if (operand.IsImmediate()) {
2703 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002704 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002705 ImmediateT32 immediate_t32(imm);
2706 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00002707 if (!size.IsNarrow() && immediate_t32.IsValid() &&
2708 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002709 EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2710 (immediate_t32.GetEncodingValue() & 0xff) |
2711 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2712 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2713 AdvanceIT();
2714 return;
2715 }
2716 } else {
2717 ImmediateA32 immediate_a32(imm);
2718 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2719 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2720 EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2721 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2722 immediate_a32.GetEncodingValue());
2723 return;
2724 }
2725 }
2726 }
2727 if (operand.IsImmediateShiftedRegister()) {
2728 Register rm = operand.GetBaseRegister();
2729 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002730 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002731 // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2732 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2733 rm.IsLow()) {
2734 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2735 AdvanceIT();
2736 return;
2737 }
2738 }
2739 }
2740 Shift shift = operand.GetShift();
2741 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002743 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00002744 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2745 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002746 uint32_t amount_ = amount % 32;
2747 EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2748 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2749 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2750 AdvanceIT();
2751 return;
2752 }
2753 } else {
2754 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2755 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2756 uint32_t amount_ = amount % 32;
2757 EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2758 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2759 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2760 return;
2761 }
2762 }
2763 }
2764 if (operand.IsRegisterShiftedRegister()) {
2765 Register rm = operand.GetBaseRegister();
2766 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002767 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002768 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002769 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002770 if (cond.IsNotNever() &&
2771 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2772 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002773 EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2774 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002775 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002776 return;
2777 }
2778 }
2779 }
2780 Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2781}
2782
2783void Assembler::ands(Condition cond,
2784 EncodingSize size,
2785 Register rd,
2786 Register rn,
2787 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002788 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002789 CheckIT(cond);
2790 if (operand.IsImmediate()) {
2791 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002792 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002793 ImmediateT32 immediate_t32(imm);
2794 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00002795 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
2796 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002797 EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2798 (immediate_t32.GetEncodingValue() & 0xff) |
2799 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2800 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2801 AdvanceIT();
2802 return;
2803 }
2804 } else {
2805 ImmediateA32 immediate_a32(imm);
2806 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2807 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2808 EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2809 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2810 immediate_a32.GetEncodingValue());
2811 return;
2812 }
2813 }
2814 }
2815 if (operand.IsImmediateShiftedRegister()) {
2816 Register rm = operand.GetBaseRegister();
2817 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002818 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002819 // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2820 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2821 rm.IsLow()) {
2822 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2823 AdvanceIT();
2824 return;
2825 }
2826 }
2827 }
2828 Shift shift = operand.GetShift();
2829 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002831 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00002832 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
2833 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002834 uint32_t amount_ = amount % 32;
2835 EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2836 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2837 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2838 AdvanceIT();
2839 return;
2840 }
2841 } else {
2842 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2843 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2844 uint32_t amount_ = amount % 32;
2845 EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2846 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2847 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2848 return;
2849 }
2850 }
2851 }
2852 if (operand.IsRegisterShiftedRegister()) {
2853 Register rm = operand.GetBaseRegister();
2854 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002855 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002856 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002857 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002858 if (cond.IsNotNever() &&
2859 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2860 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002861 EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2862 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002863 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002864 return;
2865 }
2866 }
2867 }
2868 Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2869}
2870
2871void Assembler::asr(Condition cond,
2872 EncodingSize size,
2873 Register rd,
2874 Register rm,
2875 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002876 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002877 CheckIT(cond);
2878 if (operand.IsImmediate()) {
2879 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002880 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002881 // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2882 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2883 (imm >= 1) && (imm <= 32)) {
2884 uint32_t amount_ = imm % 32;
2885 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2886 (amount_ << 6));
2887 AdvanceIT();
2888 return;
2889 }
2890 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002891 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2892 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002893 uint32_t amount_ = imm % 32;
2894 EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2895 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2896 AdvanceIT();
2897 return;
2898 }
2899 } else {
2900 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2901 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2902 uint32_t amount_ = imm % 32;
2903 EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2904 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2905 return;
2906 }
2907 }
2908 }
2909 if (operand.IsPlainRegister()) {
2910 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002911 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002912 // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2913 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2914 rs.IsLow()) {
2915 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2916 AdvanceIT();
2917 return;
2918 }
2919 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002920 if (!size.IsNarrow() &&
2921 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002922 EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2923 rs.GetCode());
2924 AdvanceIT();
2925 return;
2926 }
2927 } else {
2928 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002929 if (cond.IsNotNever() &&
2930 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002931 EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2932 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2933 return;
2934 }
2935 }
2936 }
2937 Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2938}
2939
2940void Assembler::asrs(Condition cond,
2941 EncodingSize size,
2942 Register rd,
2943 Register rm,
2944 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002946 CheckIT(cond);
2947 if (operand.IsImmediate()) {
2948 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002949 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002950 // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2951 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2952 (imm >= 1) && (imm <= 32)) {
2953 uint32_t amount_ = imm % 32;
2954 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2955 (amount_ << 6));
2956 AdvanceIT();
2957 return;
2958 }
2959 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002960 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2961 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002962 uint32_t amount_ = imm % 32;
2963 EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2964 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2965 AdvanceIT();
2966 return;
2967 }
2968 } else {
2969 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2970 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2971 uint32_t amount_ = imm % 32;
2972 EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2973 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2974 return;
2975 }
2976 }
2977 }
2978 if (operand.IsPlainRegister()) {
2979 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002980 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002981 // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2982 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2983 rs.IsLow()) {
2984 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2985 AdvanceIT();
2986 return;
2987 }
2988 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002989 if (!size.IsNarrow() &&
2990 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002991 EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2992 rs.GetCode());
2993 AdvanceIT();
2994 return;
2995 }
2996 } else {
2997 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002998 if (cond.IsNotNever() &&
2999 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003000 EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
3001 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
3002 return;
3003 }
3004 }
3005 }
3006 Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
3007}
3008
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003009void Assembler::b(Condition cond, EncodingSize size, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003010 VIXL_ASSERT(AllowAssembler());
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003011 Location::Offset offset =
3012 location->IsBound()
3013 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003014 (GetCursorOffset() + GetArchitectureStatePCOffset())
3015 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003016 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003017 // B<c>{<q>} <label> ; T1
3018 if (OutsideITBlock() && !size.IsWide() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003019 ((location->IsBound() && (offset >= -256) && (offset <= 254) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003020 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003021 (!location->IsBound() && size.IsNarrow())) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003022 !cond.Is(al) && cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003023 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003024 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003025 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003026 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003027 Location::Offset pc,
3028 const Location* location) const VIXL_OVERRIDE {
3029 pc += kT32PcDelta;
3030 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003031 VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
3032 ((offset & 0x1) == 0));
3033 const int32_t target = offset >> 1;
3034 return instr | (target & 0xff);
3035 }
3036 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003037 EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8),
3038 location,
3039 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003040 &kT16ConditionalBranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003041 AdvanceIT();
3042 return;
3043 }
3044 // B{<c>}{<q>} <label> ; T2
3045 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003046 ((location->IsBound() && (offset >= -2048) && (offset <= 2046) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003047 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003048 (!location->IsBound() && size.IsNarrow()))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003049 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003050 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003051 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003052 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003053 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003054 Location::Offset pc,
3055 const Location* location) const VIXL_OVERRIDE {
3056 pc += kT32PcDelta;
3057 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003058 VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
3059 ((offset & 0x1) == 0));
3060 const int32_t target = offset >> 1;
3061 return instr | (target & 0x7ff);
3062 }
3063 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003064 EmitT32_16(Link(0xe000, location, immop, &kT16BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003065 AdvanceIT();
3066 return;
3067 }
3068 // B<c>{<q>} <label> ; T3
3069 if (OutsideITBlock() && !size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003070 ((location->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003071 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003072 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003073 !cond.Is(al) && cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003074 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003075 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003076 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003077 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003078 Location::Offset pc,
3079 const Location* location) const VIXL_OVERRIDE {
3080 pc += kT32PcDelta;
3081 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003082 VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
3083 ((offset & 0x1) == 0));
3084 const int32_t target = offset >> 1;
3085 return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
3086 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
3087 ((target & 0x80000) << 7);
3088 }
3089 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003090 EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22),
3091 location,
3092 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003093 &kT32ConditionalBranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003094 AdvanceIT();
3095 return;
3096 }
3097 // B{<c>}{<q>} <label> ; T4
3098 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003099 ((location->IsBound() && (offset >= -16777216) &&
3100 (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3101 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003102 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003103 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003104 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003105 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003106 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003107 Location::Offset pc,
3108 const Location* location) const VIXL_OVERRIDE {
3109 pc += kT32PcDelta;
3110 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003111 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3112 ((offset & 0x1) == 0));
3113 int32_t target = offset >> 1;
3114 uint32_t S = target & (1 << 23);
3115 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3116 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3117 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3118 ((target & 0x800000) << 3);
3119 }
3120 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003121 EmitT32_32(Link(0xf0009000U, location, immop, &kT32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003122 AdvanceIT();
3123 return;
3124 }
3125 } else {
3126 // B{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003127 if (((location->IsBound() && (offset >= -33554432) &&
3128 (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3129 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003130 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003131 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003132 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003133 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003134 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003135 Location::Offset pc,
3136 const Location* location) const VIXL_OVERRIDE {
3137 pc += kA32PcDelta;
3138 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003139 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3140 ((offset & 0x3) == 0));
3141 const int32_t target = offset >> 2;
3142 return instr | (target & 0xffffff);
3143 }
3144 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003145 EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28),
3146 location,
3147 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003148 &kA32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003149 return;
3150 }
3151 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003152 Delegate(kB, &Assembler::b, cond, size, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003153}
3154
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003155bool Assembler::b_info(Condition cond,
3156 EncodingSize size,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003157 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003158 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003159 VIXL_ASSERT(!location->IsBound());
3160 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003161 if (IsUsingT32()) {
3162 // B<c>{<q>} <label> ; T1
3163 if (OutsideITBlock() && !size.IsWide() && size.IsNarrow() && !cond.Is(al) &&
3164 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003165 *info = &kT16ConditionalBranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003166 return true;
3167 }
3168 // B{<c>}{<q>} <label> ; T2
3169 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003170 *info = &kT16BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003171 return true;
3172 }
3173 // B<c>{<q>} <label> ; T3
3174 if (OutsideITBlock() && !size.IsNarrow() && !cond.Is(al) &&
3175 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003176 *info = &kT32ConditionalBranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003177 return true;
3178 }
3179 // B{<c>}{<q>} <label> ; T4
3180 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003181 *info = &kT32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003182 return true;
3183 }
3184 } else {
3185 // B{<c>}{<q>} <label> ; A1
3186 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003187 *info = &kA32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003188 return true;
3189 }
3190 }
3191 return false;
3192}
3193
Vincent Belliard609821f2017-02-08 14:17:25 -08003194void Assembler::bfc(Condition cond, Register rd, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003195 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003196 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08003197 if (IsUsingT32()) {
3198 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003199 if ((lsb <= 31) && (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3200 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003201 uint32_t msb = lsb + width - 1;
3202 EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
3203 ((lsb & 0x1c) << 10) | msb);
3204 AdvanceIT();
3205 return;
3206 }
3207 } else {
3208 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
3209 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003210 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3211 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003212 uint32_t msb = lsb + width - 1;
3213 EmitA32(0x07c0001fU | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3214 (lsb << 7) | (msb << 16));
3215 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003216 }
3217 }
Vincent Belliard609821f2017-02-08 14:17:25 -08003218 Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003219}
3220
Vincent Belliard609821f2017-02-08 14:17:25 -08003221void Assembler::bfi(
3222 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003223 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003224 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08003225 if (IsUsingT32()) {
3226 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
3227 if ((lsb <= 31) && !rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003228 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3229 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003230 uint32_t msb = lsb + width - 1;
3231 EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3232 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
3233 AdvanceIT();
3234 return;
3235 }
3236 } else {
3237 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
3238 if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003239 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3240 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003241 uint32_t msb = lsb + width - 1;
3242 EmitA32(0x07c00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3243 rn.GetCode() | (lsb << 7) | (msb << 16));
3244 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003245 }
3246 }
Vincent Belliard609821f2017-02-08 14:17:25 -08003247 Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003248}
3249
3250void Assembler::bic(Condition cond,
3251 EncodingSize size,
3252 Register rd,
3253 Register rn,
3254 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003255 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003256 CheckIT(cond);
3257 if (operand.IsImmediate()) {
3258 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003259 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003260 ImmediateT32 immediate_t32(imm);
3261 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003262 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3263 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003264 EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3265 (immediate_t32.GetEncodingValue() & 0xff) |
3266 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3267 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3268 AdvanceIT();
3269 return;
3270 }
3271 } else {
3272 ImmediateA32 immediate_a32(imm);
3273 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3274 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3275 EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3276 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3277 immediate_a32.GetEncodingValue());
3278 return;
3279 }
3280 }
3281 }
3282 if (operand.IsImmediateShiftedRegister()) {
3283 Register rm = operand.GetBaseRegister();
3284 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003285 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003286 // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3287 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3288 rm.IsLow()) {
3289 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3290 AdvanceIT();
3291 return;
3292 }
3293 }
3294 }
3295 Shift shift = operand.GetShift();
3296 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003297 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003298 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003299 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3300 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003301 uint32_t amount_ = amount % 32;
3302 EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3303 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3304 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3305 AdvanceIT();
3306 return;
3307 }
3308 } else {
3309 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3310 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3311 uint32_t amount_ = amount % 32;
3312 EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3313 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3314 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3315 return;
3316 }
3317 }
3318 }
3319 if (operand.IsRegisterShiftedRegister()) {
3320 Register rm = operand.GetBaseRegister();
3321 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003322 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003323 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003324 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00003325 if (cond.IsNotNever() &&
3326 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3327 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003328 EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3329 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003330 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003331 return;
3332 }
3333 }
3334 }
3335 Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3336}
3337
3338void Assembler::bics(Condition cond,
3339 EncodingSize size,
3340 Register rd,
3341 Register rn,
3342 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003343 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003344 CheckIT(cond);
3345 if (operand.IsImmediate()) {
3346 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003347 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003348 ImmediateT32 immediate_t32(imm);
3349 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003350 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3351 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003352 EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3353 (immediate_t32.GetEncodingValue() & 0xff) |
3354 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3355 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3356 AdvanceIT();
3357 return;
3358 }
3359 } else {
3360 ImmediateA32 immediate_a32(imm);
3361 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3362 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3363 EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3364 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3365 immediate_a32.GetEncodingValue());
3366 return;
3367 }
3368 }
3369 }
3370 if (operand.IsImmediateShiftedRegister()) {
3371 Register rm = operand.GetBaseRegister();
3372 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003373 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003374 // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3375 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3376 rm.IsLow()) {
3377 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3378 AdvanceIT();
3379 return;
3380 }
3381 }
3382 }
3383 Shift shift = operand.GetShift();
3384 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003385 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003386 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003387 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3388 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003389 uint32_t amount_ = amount % 32;
3390 EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3391 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3392 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3393 AdvanceIT();
3394 return;
3395 }
3396 } else {
3397 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3398 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3399 uint32_t amount_ = amount % 32;
3400 EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3401 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3402 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3403 return;
3404 }
3405 }
3406 }
3407 if (operand.IsRegisterShiftedRegister()) {
3408 Register rm = operand.GetBaseRegister();
3409 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003410 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003411 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003412 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00003413 if (cond.IsNotNever() &&
3414 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3415 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003416 EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3417 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003418 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003419 return;
3420 }
3421 }
3422 }
3423 Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3424}
3425
3426void Assembler::bkpt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003427 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003428 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003429 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003430 // BKPT{<q>} {#}<imm> ; T1
3431 if ((imm <= 255)) {
3432 EmitT32_16(0xbe00 | imm);
3433 AdvanceIT();
3434 return;
3435 }
3436 } else {
3437 // BKPT{<q>} {#}<imm> ; A1
3438 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3439 EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3440 ((imm & 0xfff0) << 4));
3441 return;
3442 }
3443 }
3444 Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3445}
3446
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003447void Assembler::bl(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003448 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003449 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003450 Location::Offset offset =
3451 location->IsBound()
3452 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003453 (GetCursorOffset() + GetArchitectureStatePCOffset())
3454 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003455 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003456 // BL{<c>}{<q>} <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003457 if (((location->IsBound() && (offset >= -16777216) &&
3458 (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3459 !location->IsBound()) &&
Pierre Langloisdc626f32017-02-15 13:31:28 +00003460 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003461 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003462 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003463 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003464 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003465 Location::Offset pc,
3466 const Location* location) const VIXL_OVERRIDE {
3467 pc += kT32PcDelta;
3468 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003469 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3470 ((offset & 0x1) == 0));
3471 int32_t target = offset >> 1;
3472 uint32_t S = target & (1 << 23);
3473 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3474 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3475 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3476 ((target & 0x800000) << 3);
3477 }
3478 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003479 EmitT32_32(Link(0xf000d000U, location, immop, &kT32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003480 AdvanceIT();
3481 return;
3482 }
3483 } else {
3484 // BL{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003485 if (((location->IsBound() && (offset >= -33554432) &&
3486 (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3487 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003488 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003489 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003490 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003491 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003492 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003493 Location::Offset pc,
3494 const Location* location) const VIXL_OVERRIDE {
3495 pc += kA32PcDelta;
3496 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003497 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3498 ((offset & 0x3) == 0));
3499 const int32_t target = offset >> 2;
3500 return instr | (target & 0xffffff);
3501 }
3502 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003503 EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28),
3504 location,
3505 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003506 &kA32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003507 return;
3508 }
3509 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003510 Delegate(kBl, &Assembler::bl, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003511}
3512
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003513bool Assembler::bl_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003514 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003515 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003516 VIXL_ASSERT(!location->IsBound());
3517 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003518 if (IsUsingT32()) {
3519 // BL{<c>}{<q>} <label> ; T1
3520 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003521 *info = &kT32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003522 return true;
3523 }
3524 } else {
3525 // BL{<c>}{<q>} <label> ; A1
3526 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003527 *info = &kA32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003528 return true;
3529 }
3530 }
3531 return false;
3532}
3533
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003534void Assembler::blx(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003535 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003536 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003537 Location::Offset offset =
3538 location->IsBound()
3539 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003540 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3541 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003542 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003543 // BLX{<c>}{<q>} <label> ; T2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003544 if (((location->IsBound() && (offset >= -16777216) &&
3545 (offset <= 16777212) && ((offset & 0x3) == 0)) ||
3546 !location->IsBound()) &&
Pierre Langloisdc626f32017-02-15 13:31:28 +00003547 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003548 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003549 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003550 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003551 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003552 Location::Offset pc,
3553 const Location* location) const VIXL_OVERRIDE {
3554 pc += kT32PcDelta;
3555 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003556 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3557 ((offset & 0x3) == 0));
3558 int32_t target = offset >> 2;
3559 uint32_t S = target & (1 << 22);
3560 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3561 return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3562 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3563 ((target & 0x400000) << 4);
3564 }
3565 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003566 EmitT32_32(Link(0xf000c000U, location, immop, &kT32BlxInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003567 AdvanceIT();
3568 return;
3569 }
3570 } else {
3571 // BLX{<c>}{<q>} <label> ; A2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003572 if (((location->IsBound() && (offset >= -33554432) &&
3573 (offset <= 33554430) && ((offset & 0x1) == 0)) ||
3574 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003575 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003576 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003577 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003578 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003579 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003580 Location::Offset pc,
3581 const Location* location) const
3582 VIXL_OVERRIDE {
3583 pc += kA32PcDelta;
3584 Location::Offset offset =
3585 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003586 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3587 ((offset & 0x1) == 0));
3588 const int32_t target = offset >> 1;
3589 return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3590 }
3591 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003592 EmitA32(Link(0xfa000000U, location, immop, &kA32BlxInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003593 return;
3594 }
3595 }
3596 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003597 Delegate(kBlx, &Assembler::blx, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003598}
3599
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003600bool Assembler::blx_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003601 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003602 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003603 VIXL_ASSERT(!location->IsBound());
3604 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003605 USE(cond);
3606 if (IsUsingT32()) {
3607 // BLX{<c>}{<q>} <label> ; T2
3608 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003609 *info = &kT32BlxInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003610 return true;
3611 }
3612 } else {
3613 // BLX{<c>}{<q>} <label> ; A2
3614 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003615 *info = &kA32BlxInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003616 return true;
3617 }
3618 }
3619 return false;
3620}
3621
Alexandre Ramesd3832962016-07-04 15:03:43 +01003622void Assembler::blx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003623 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003624 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003625 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003626 // BLX{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003627 if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3628 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003629 EmitT32_16(0x4780 | (rm.GetCode() << 3));
3630 AdvanceIT();
3631 return;
3632 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003633 } else {
3634 // BLX{<c>}{<q>} <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003635 if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003636 EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3637 return;
3638 }
3639 }
3640 Delegate(kBlx, &Assembler::blx, cond, rm);
3641}
3642
3643void Assembler::bx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003644 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003645 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003646 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003647 // BX{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003648 if ((OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3649 EmitT32_16(0x4700 | (rm.GetCode() << 3));
3650 AdvanceIT();
3651 return;
3652 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003653 } else {
3654 // BX{<c>}{<q>} <Rm> ; A1
3655 if (cond.IsNotNever()) {
3656 EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3657 return;
3658 }
3659 }
3660 Delegate(kBx, &Assembler::bx, cond, rm);
3661}
3662
3663void Assembler::bxj(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003664 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003665 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003666 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003667 // BXJ{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003668 if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3669 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003670 EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3671 AdvanceIT();
3672 return;
3673 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003674 } else {
3675 // BXJ{<c>}{<q>} <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003676 if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003677 EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3678 return;
3679 }
3680 }
3681 Delegate(kBxj, &Assembler::bxj, cond, rm);
3682}
3683
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003684void Assembler::cbnz(Register rn, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003685 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003686 CheckIT(al);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003687 Location::Offset offset =
3688 location->IsBound()
3689 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003690 (GetCursorOffset() + GetArchitectureStatePCOffset())
3691 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003692 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003693 // CBNZ{<q>} <Rn>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003694 if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3695 (offset <= 126) && ((offset & 0x1) == 0)) ||
3696 !location->IsBound())) {
3697 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003698 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003699 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003700 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003701 Location::Offset pc,
3702 const Location* location) const VIXL_OVERRIDE {
3703 pc += kT32PcDelta;
3704 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003705 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3706 ((offset & 0x1) == 0));
3707 const int32_t target = offset >> 1;
3708 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3709 }
3710 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003711 EmitT32_16(Link(0xb900 | rn.GetCode(), location, immop, &kT16CbzInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003712 AdvanceIT();
3713 return;
3714 }
3715 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003716 Delegate(kCbnz, &Assembler::cbnz, rn, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003717}
3718
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003719bool Assembler::cbnz_info(Register rn,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003720 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003721 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003722 VIXL_ASSERT(!location->IsBound());
3723 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003724 if (IsUsingT32()) {
3725 // CBNZ{<q>} <Rn>, <label> ; T1
3726 if (rn.IsLow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003727 *info = &kT16CbzInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003728 return true;
3729 }
3730 }
3731 return false;
3732}
3733
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003734void Assembler::cbz(Register rn, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003735 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003736 CheckIT(al);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003737 Location::Offset offset =
3738 location->IsBound()
3739 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003740 (GetCursorOffset() + GetArchitectureStatePCOffset())
3741 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003743 // CBZ{<q>} <Rn>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003744 if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3745 (offset <= 126) && ((offset & 0x1) == 0)) ||
3746 !location->IsBound())) {
3747 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003748 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003749 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003750 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003751 Location::Offset pc,
3752 const Location* location) const VIXL_OVERRIDE {
3753 pc += kT32PcDelta;
3754 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003755 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3756 ((offset & 0x1) == 0));
3757 const int32_t target = offset >> 1;
3758 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3759 }
3760 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003761 EmitT32_16(Link(0xb100 | rn.GetCode(), location, immop, &kT16CbzInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003762 AdvanceIT();
3763 return;
3764 }
3765 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003766 Delegate(kCbz, &Assembler::cbz, rn, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003767}
3768
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003769bool Assembler::cbz_info(Register rn,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003770 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003771 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003772 VIXL_ASSERT(!location->IsBound());
3773 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003774 if (IsUsingT32()) {
3775 // CBZ{<q>} <Rn>, <label> ; T1
3776 if (rn.IsLow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003777 *info = &kT16CbzInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003778 return true;
3779 }
3780 }
3781 return false;
3782}
3783
Alexandre Ramesd3832962016-07-04 15:03:43 +01003784void Assembler::clrex(Condition cond) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003785 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003786 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003787 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003788 // CLREX{<c>}{<q>} ; T1
3789 EmitT32_32(0xf3bf8f2fU);
3790 AdvanceIT();
3791 return;
3792 } else {
3793 // CLREX{<c>}{<q>} ; A1
3794 if (cond.Is(al)) {
3795 EmitA32(0xf57ff01fU);
3796 return;
3797 }
3798 }
3799 Delegate(kClrex, &Assembler::clrex, cond);
3800}
3801
3802void Assembler::clz(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003803 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003804 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003806 // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
Georgia Kouvelie99f34d2016-12-21 17:00:29 +00003807 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3808 EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3809 (rm.GetCode() << 16));
3810 AdvanceIT();
3811 return;
3812 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003813 } else {
3814 // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
Georgia Kouvelie99f34d2016-12-21 17:00:29 +00003815 if (cond.IsNotNever() &&
3816 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003817 EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3818 rm.GetCode());
3819 return;
3820 }
3821 }
3822 Delegate(kClz, &Assembler::clz, cond, rd, rm);
3823}
3824
3825void Assembler::cmn(Condition cond,
3826 EncodingSize size,
3827 Register rn,
3828 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003829 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003830 CheckIT(cond);
3831 if (operand.IsImmediate()) {
3832 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003833 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003834 ImmediateT32 immediate_t32(imm);
3835 // CMN{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003836 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3837 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003838 EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3839 (immediate_t32.GetEncodingValue() & 0xff) |
3840 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3841 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3842 AdvanceIT();
3843 return;
3844 }
3845 } else {
3846 ImmediateA32 immediate_a32(imm);
3847 // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3848 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3849 EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3850 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3851 return;
3852 }
3853 }
3854 }
3855 if (operand.IsImmediateShiftedRegister()) {
3856 Register rm = operand.GetBaseRegister();
3857 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003858 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003859 // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3860 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3861 EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3862 AdvanceIT();
3863 return;
3864 }
3865 }
3866 }
3867 Shift shift = operand.GetShift();
3868 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003869 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003870 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003871 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3872 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003873 uint32_t amount_ = amount % 32;
3874 EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3875 (operand.GetTypeEncodingValue() << 4) |
3876 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3877 AdvanceIT();
3878 return;
3879 }
3880 } else {
3881 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3882 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3883 uint32_t amount_ = amount % 32;
3884 EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3885 (rn.GetCode() << 16) | rm.GetCode() |
3886 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3887 return;
3888 }
3889 }
3890 }
3891 if (operand.IsRegisterShiftedRegister()) {
3892 Register rm = operand.GetBaseRegister();
3893 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003894 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003895 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003896 // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003897 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00003898 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003899 EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3900 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003901 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003902 return;
3903 }
3904 }
3905 }
3906 Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3907}
3908
3909void Assembler::cmp(Condition cond,
3910 EncodingSize size,
3911 Register rn,
3912 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003913 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003914 CheckIT(cond);
3915 if (operand.IsImmediate()) {
3916 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003917 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003918 ImmediateT32 immediate_t32(imm);
3919 // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3920 if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3921 EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3922 AdvanceIT();
3923 return;
3924 }
3925 // CMP{<c>}{<q>} <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003926 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3927 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003928 EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3929 (immediate_t32.GetEncodingValue() & 0xff) |
3930 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3931 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3932 AdvanceIT();
3933 return;
3934 }
3935 } else {
3936 ImmediateA32 immediate_a32(imm);
3937 // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3938 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3939 EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3940 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3941 return;
3942 }
3943 }
3944 }
3945 if (operand.IsImmediateShiftedRegister()) {
3946 Register rm = operand.GetBaseRegister();
3947 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003948 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003949 // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3950 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3951 EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3952 AdvanceIT();
3953 return;
3954 }
3955 // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003956 if (!size.IsWide() &&
3957 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003958 EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3959 ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3960 AdvanceIT();
3961 return;
3962 }
3963 }
3964 }
3965 Shift shift = operand.GetShift();
3966 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003968 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +00003969 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3970 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003971 uint32_t amount_ = amount % 32;
3972 EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3973 (operand.GetTypeEncodingValue() << 4) |
3974 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3975 AdvanceIT();
3976 return;
3977 }
3978 } else {
3979 // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3980 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3981 uint32_t amount_ = amount % 32;
3982 EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3983 (rn.GetCode() << 16) | rm.GetCode() |
3984 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3985 return;
3986 }
3987 }
3988 }
3989 if (operand.IsRegisterShiftedRegister()) {
3990 Register rm = operand.GetBaseRegister();
3991 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003992 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003993 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003994 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003995 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00003996 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003997 EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3998 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003999 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004000 return;
4001 }
4002 }
4003 }
4004 Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
4005}
4006
4007void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004008 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004009 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004010 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004011 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004012 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4013 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004014 EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4015 rm.GetCode());
4016 AdvanceIT();
4017 return;
4018 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004019 } else {
4020 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004021 if ((cond.Is(al) || AllowUnpredictable()) &&
4022 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004023 EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4024 (rn.GetCode() << 16) | rm.GetCode());
4025 return;
4026 }
4027 }
4028 Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
4029}
4030
4031void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004032 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004033 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004034 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004035 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004036 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4037 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004038 EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4039 rm.GetCode());
4040 AdvanceIT();
4041 return;
4042 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004043 } else {
4044 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004045 if ((cond.Is(al) || AllowUnpredictable()) &&
4046 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004047 EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4048 (rn.GetCode() << 16) | rm.GetCode());
4049 return;
4050 }
4051 }
4052 Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
4053}
4054
4055void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004056 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004057 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004058 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004059 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004060 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4061 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004062 EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4063 rm.GetCode());
4064 AdvanceIT();
4065 return;
4066 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004067 } else {
4068 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004069 if ((cond.Is(al) || AllowUnpredictable()) &&
4070 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004071 EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4072 (rn.GetCode() << 16) | rm.GetCode());
4073 return;
4074 }
4075 }
4076 Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
4077}
4078
4079void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004080 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004081 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004082 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004083 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004084 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4085 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004086 EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4087 rm.GetCode());
4088 AdvanceIT();
4089 return;
4090 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004091 } else {
4092 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004093 if ((cond.Is(al) || AllowUnpredictable()) &&
4094 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004095 EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4096 (rn.GetCode() << 16) | rm.GetCode());
4097 return;
4098 }
4099 }
4100 Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
4101}
4102
4103void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004104 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004105 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004106 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004107 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004108 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4109 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004110 EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4111 rm.GetCode());
4112 AdvanceIT();
4113 return;
4114 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004115 } else {
4116 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004117 if ((cond.Is(al) || AllowUnpredictable()) &&
4118 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004119 EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4120 (rn.GetCode() << 16) | rm.GetCode());
4121 return;
4122 }
4123 }
4124 Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
4125}
4126
4127void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004128 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004129 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004130 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004131 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004132 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
4133 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00004134 EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4135 rm.GetCode());
4136 AdvanceIT();
4137 return;
4138 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004139 } else {
4140 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004141 if ((cond.Is(al) || AllowUnpredictable()) &&
4142 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004143 EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4144 (rn.GetCode() << 16) | rm.GetCode());
4145 return;
4146 }
4147 }
4148 Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
4149}
4150
4151void Assembler::dmb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004152 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004153 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004154 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004155 // DMB{<c>}{<q>} {<option>} ; T1
4156 EmitT32_32(0xf3bf8f50U | option.GetType());
4157 AdvanceIT();
4158 return;
4159 } else {
4160 // DMB{<c>}{<q>} {<option>} ; A1
4161 if (cond.Is(al)) {
4162 EmitA32(0xf57ff050U | option.GetType());
4163 return;
4164 }
4165 }
4166 Delegate(kDmb, &Assembler::dmb, cond, option);
4167}
4168
4169void Assembler::dsb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004170 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004171 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004172 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004173 // DSB{<c>}{<q>} {<option>} ; T1
4174 EmitT32_32(0xf3bf8f40U | option.GetType());
4175 AdvanceIT();
4176 return;
4177 } else {
4178 // DSB{<c>}{<q>} {<option>} ; A1
4179 if (cond.Is(al)) {
4180 EmitA32(0xf57ff040U | option.GetType());
4181 return;
4182 }
4183 }
4184 Delegate(kDsb, &Assembler::dsb, cond, option);
4185}
4186
4187void Assembler::eor(Condition cond,
4188 EncodingSize size,
4189 Register rd,
4190 Register rn,
4191 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004192 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004193 CheckIT(cond);
4194 if (operand.IsImmediate()) {
4195 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004196 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004197 ImmediateT32 immediate_t32(imm);
4198 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004199 if (!size.IsNarrow() && immediate_t32.IsValid() &&
4200 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004201 EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4202 (immediate_t32.GetEncodingValue() & 0xff) |
4203 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4204 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4205 AdvanceIT();
4206 return;
4207 }
4208 } else {
4209 ImmediateA32 immediate_a32(imm);
4210 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4211 if (immediate_a32.IsValid() && cond.IsNotNever()) {
4212 EmitA32(0x02200000U | (cond.GetCondition() << 28) |
4213 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4214 immediate_a32.GetEncodingValue());
4215 return;
4216 }
4217 }
4218 }
4219 if (operand.IsImmediateShiftedRegister()) {
4220 Register rm = operand.GetBaseRegister();
4221 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004222 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004223 // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4224 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4225 rm.IsLow()) {
4226 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4227 AdvanceIT();
4228 return;
4229 }
4230 }
4231 }
4232 Shift shift = operand.GetShift();
4233 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004234 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004235 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004236 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
4237 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004238 uint32_t amount_ = amount % 32;
4239 EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4240 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4241 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4242 AdvanceIT();
4243 return;
4244 }
4245 } else {
4246 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4247 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4248 uint32_t amount_ = amount % 32;
4249 EmitA32(0x00200000U | (cond.GetCondition() << 28) |
4250 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4251 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4252 return;
4253 }
4254 }
4255 }
4256 if (operand.IsRegisterShiftedRegister()) {
4257 Register rm = operand.GetBaseRegister();
4258 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00004259 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004260 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004261 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00004262 if (cond.IsNotNever() &&
4263 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4264 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004265 EmitA32(0x00200010U | (cond.GetCondition() << 28) |
4266 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00004267 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004268 return;
4269 }
4270 }
4271 }
4272 Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
4273}
4274
4275void Assembler::eors(Condition cond,
4276 EncodingSize size,
4277 Register rd,
4278 Register rn,
4279 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004280 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004281 CheckIT(cond);
4282 if (operand.IsImmediate()) {
4283 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004285 ImmediateT32 immediate_t32(imm);
4286 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004287 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
4288 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004289 EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4290 (immediate_t32.GetEncodingValue() & 0xff) |
4291 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4292 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4293 AdvanceIT();
4294 return;
4295 }
4296 } else {
4297 ImmediateA32 immediate_a32(imm);
4298 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4299 if (immediate_a32.IsValid() && cond.IsNotNever()) {
4300 EmitA32(0x02300000U | (cond.GetCondition() << 28) |
4301 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4302 immediate_a32.GetEncodingValue());
4303 return;
4304 }
4305 }
4306 }
4307 if (operand.IsImmediateShiftedRegister()) {
4308 Register rm = operand.GetBaseRegister();
4309 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004310 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004311 // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4312 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4313 rm.IsLow()) {
4314 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4315 AdvanceIT();
4316 return;
4317 }
4318 }
4319 }
4320 Shift shift = operand.GetShift();
4321 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004322 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004323 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004324 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
4325 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004326 uint32_t amount_ = amount % 32;
4327 EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4328 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4329 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4330 AdvanceIT();
4331 return;
4332 }
4333 } else {
4334 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4335 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4336 uint32_t amount_ = amount % 32;
4337 EmitA32(0x00300000U | (cond.GetCondition() << 28) |
4338 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4339 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4340 return;
4341 }
4342 }
4343 }
4344 if (operand.IsRegisterShiftedRegister()) {
4345 Register rm = operand.GetBaseRegister();
4346 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00004347 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004348 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004349 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00004350 if (cond.IsNotNever() &&
4351 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4352 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004353 EmitA32(0x00300010U | (cond.GetCondition() << 28) |
4354 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00004355 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004356 return;
4357 }
4358 }
4359 }
4360 Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
4361}
4362
4363void Assembler::fldmdbx(Condition cond,
4364 Register rn,
4365 WriteBack write_back,
4366 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004367 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004368 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004369 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004370 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4371 if (write_back.DoesWriteBack() &&
4372 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004373 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004374 AllowUnpredictable())) {
4375 const DRegister& dreg = dreglist.GetFirstDRegister();
4376 unsigned len = dreglist.GetLength() * 2;
4377 EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4378 (len & 0xff));
4379 AdvanceIT();
4380 return;
4381 }
4382 } else {
4383 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4384 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4385 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004386 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004387 AllowUnpredictable())) {
4388 const DRegister& dreg = dreglist.GetFirstDRegister();
4389 unsigned len = dreglist.GetLength() * 2;
4390 EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4391 dreg.Encode(22, 12) | (len & 0xff));
4392 return;
4393 }
4394 }
4395 Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
4396}
4397
4398void Assembler::fldmiax(Condition cond,
4399 Register rn,
4400 WriteBack write_back,
4401 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004402 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004403 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004404 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004405 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4406 if ((((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004407 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004408 AllowUnpredictable())) {
4409 const DRegister& dreg = dreglist.GetFirstDRegister();
4410 unsigned len = dreglist.GetLength() * 2;
4411 EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4412 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4413 (len & 0xff));
4414 AdvanceIT();
4415 return;
4416 }
4417 } else {
4418 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4419 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004420 (dreglist.GetLastDRegister().GetCode() < 16) &&
4421 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004422 AllowUnpredictable())) {
4423 const DRegister& dreg = dreglist.GetFirstDRegister();
4424 unsigned len = dreglist.GetLength() * 2;
4425 EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4426 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4427 (len & 0xff));
4428 return;
4429 }
4430 }
4431 Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4432}
4433
4434void Assembler::fstmdbx(Condition cond,
4435 Register rn,
4436 WriteBack write_back,
4437 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004438 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004439 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004440 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004441 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4442 if (write_back.DoesWriteBack() &&
4443 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004444 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004445 AllowUnpredictable())) {
4446 const DRegister& dreg = dreglist.GetFirstDRegister();
4447 unsigned len = dreglist.GetLength() * 2;
4448 EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4449 (len & 0xff));
4450 AdvanceIT();
4451 return;
4452 }
4453 } else {
4454 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4455 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4456 (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004457 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004458 AllowUnpredictable())) {
4459 const DRegister& dreg = dreglist.GetFirstDRegister();
4460 unsigned len = dreglist.GetLength() * 2;
4461 EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4462 dreg.Encode(22, 12) | (len & 0xff));
4463 return;
4464 }
4465 }
4466 Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4467}
4468
4469void Assembler::fstmiax(Condition cond,
4470 Register rn,
4471 WriteBack write_back,
4472 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004473 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004474 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004475 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004476 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4477 if ((((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004478 (dreglist.GetLastDRegister().GetCode() < 16) && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004479 AllowUnpredictable())) {
4480 const DRegister& dreg = dreglist.GetFirstDRegister();
4481 unsigned len = dreglist.GetLength() * 2;
4482 EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4483 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4484 (len & 0xff));
4485 AdvanceIT();
4486 return;
4487 }
4488 } else {
4489 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4490 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -07004491 (dreglist.GetLastDRegister().GetCode() < 16) &&
4492 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004493 AllowUnpredictable())) {
4494 const DRegister& dreg = dreglist.GetFirstDRegister();
4495 unsigned len = dreglist.GetLength() * 2;
4496 EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4497 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4498 (len & 0xff));
4499 return;
4500 }
4501 }
4502 Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4503}
4504
4505void Assembler::hlt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004506 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004507 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004508 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004509 // HLT{<q>} {#}<imm> ; T1
4510 if ((imm <= 63)) {
4511 EmitT32_16(0xba80 | imm);
4512 AdvanceIT();
4513 return;
4514 }
4515 } else {
4516 // HLT{<q>} {#}<imm> ; A1
4517 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4518 EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4519 ((imm & 0xfff0) << 4));
4520 return;
4521 }
4522 }
4523 Delegate(kHlt, &Assembler::hlt, cond, imm);
4524}
4525
4526void Assembler::hvc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004527 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004528 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004529 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004530 // HVC{<q>} {#}<imm16> ; T1
Vincent Belliardf9d8c6e2017-09-12 10:11:12 -07004531 if ((imm <= 65535) && (OutsideITBlock() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004532 EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4533 AdvanceIT();
4534 return;
4535 }
4536 } else {
4537 // HVC{<q>} {#}<imm16> ; A1
4538 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4539 EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4540 ((imm & 0xfff0) << 4));
4541 return;
4542 }
4543 }
4544 Delegate(kHvc, &Assembler::hvc, cond, imm);
4545}
4546
4547void Assembler::isb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004548 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004549 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004550 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004551 // ISB{<c>}{<q>} {<option>} ; T1
4552 EmitT32_32(0xf3bf8f60U | option.GetType());
4553 AdvanceIT();
4554 return;
4555 } else {
4556 // ISB{<c>}{<q>} {<option>} ; A1
4557 if (cond.Is(al)) {
4558 EmitA32(0xf57ff060U | option.GetType());
4559 return;
4560 }
4561 }
4562 Delegate(kIsb, &Assembler::isb, cond, option);
4563}
4564
4565void Assembler::it(Condition cond, uint16_t mask) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004566 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004567 CheckNotIT();
4568 if (mask != 0) {
4569 if ((cond.GetCondition() & 0x1) != 0) {
4570 if ((mask & 0x1) != 0) {
4571 mask ^= 0xE;
4572 } else if ((mask & 0x2) != 0) {
4573 mask ^= 0xC;
4574 } else if ((mask & 0x4) != 0) {
4575 mask ^= 0x8;
4576 }
4577 }
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004578 if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004579 SetIT(cond, mask);
4580 return;
4581 }
4582 DelegateIt(cond, mask);
4583}
4584
4585void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004586 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004587 CheckIT(cond);
4588 if (operand.IsImmediateZero()) {
4589 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004590 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004591 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004592 if (operand.IsOffset() &&
4593 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004594 EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4595 AdvanceIT();
4596 return;
4597 }
4598 } else {
4599 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004600 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004601 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004602 EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4603 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4604 return;
4605 }
4606 }
4607 }
4608 Delegate(kLda, &Assembler::lda, cond, rt, operand);
4609}
4610
4611void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004612 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004613 CheckIT(cond);
4614 if (operand.IsImmediateZero()) {
4615 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004616 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004617 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004618 if (operand.IsOffset() &&
4619 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004620 EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4621 AdvanceIT();
4622 return;
4623 }
4624 } else {
4625 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004626 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004627 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004628 EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4629 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4630 return;
4631 }
4632 }
4633 }
4634 Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4635}
4636
4637void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004638 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004639 CheckIT(cond);
4640 if (operand.IsImmediateZero()) {
4641 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004642 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004643 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004644 if (operand.IsOffset() &&
4645 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004646 EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4647 AdvanceIT();
4648 return;
4649 }
4650 } else {
4651 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004652 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004653 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004654 EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4655 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4656 return;
4657 }
4658 }
4659 }
4660 Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4661}
4662
4663void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004664 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004665 CheckIT(cond);
4666 if (operand.IsImmediateZero()) {
4667 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004668 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004669 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004670 if (operand.IsOffset() &&
4671 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004672 EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4673 AdvanceIT();
4674 return;
4675 }
4676 } else {
4677 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004678 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004679 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004680 EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4681 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4682 return;
4683 }
4684 }
4685 }
4686 Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4687}
4688
4689void Assembler::ldaexd(Condition cond,
4690 Register rt,
4691 Register rt2,
4692 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004693 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004694 CheckIT(cond);
4695 if (operand.IsImmediateZero()) {
4696 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004697 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004698 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004699 if (operand.IsOffset() &&
4700 ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004701 EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4702 (rn.GetCode() << 16));
4703 AdvanceIT();
4704 return;
4705 }
4706 } else {
4707 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4708 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004709 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00004710 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004711 AllowUnpredictable())) {
4712 EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4713 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4714 return;
4715 }
4716 }
4717 }
4718 Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4719}
4720
4721void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004722 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004723 CheckIT(cond);
4724 if (operand.IsImmediateZero()) {
4725 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004726 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004727 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004728 if (operand.IsOffset() &&
4729 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004730 EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4731 AdvanceIT();
4732 return;
4733 }
4734 } else {
4735 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004736 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004737 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004738 EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4739 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4740 return;
4741 }
4742 }
4743 }
4744 Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4745}
4746
4747void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004748 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004749 CheckIT(cond);
4750 if (operand.IsImmediateZero()) {
4751 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004752 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004753 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004754 if (operand.IsOffset() &&
4755 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004756 EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4757 AdvanceIT();
4758 return;
4759 }
4760 } else {
4761 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004762 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004763 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004764 EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4765 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4766 return;
4767 }
4768 }
4769 }
4770 Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4771}
4772
4773void Assembler::ldm(Condition cond,
4774 EncodingSize size,
4775 Register rn,
4776 WriteBack write_back,
4777 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004778 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004779 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004780 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004781 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4782 if (!size.IsWide() && rn.IsLow() &&
4783 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4784 write_back.DoesWriteBack()) &&
4785 ((registers.GetList() & ~0xff) == 0)) {
4786 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4787 GetRegisterListEncoding(registers, 0, 8));
4788 AdvanceIT();
4789 return;
4790 }
4791 // LDM{<c>}{<q>} SP!, <registers> ; T1
4792 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
Peter Collingbourne920189b2021-01-22 17:42:36 -08004793 registers.IsR0toR7orPC()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004794 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4795 GetRegisterListEncoding(registers, 0, 8));
4796 AdvanceIT();
4797 return;
4798 }
4799 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004800 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4801 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004802 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4803 (write_back.GetWriteBackUint32() << 21) |
4804 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4805 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4806 GetRegisterListEncoding(registers, 0, 13));
4807 AdvanceIT();
4808 return;
4809 }
4810 } else {
4811 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004812 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004813 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4814 (write_back.GetWriteBackUint32() << 21) |
4815 GetRegisterListEncoding(registers, 0, 16));
4816 return;
4817 }
4818 }
4819 Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4820}
4821
4822void Assembler::ldmda(Condition cond,
4823 Register rn,
4824 WriteBack write_back,
4825 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004826 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004827 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004828 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004829 // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004830 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004831 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4832 (write_back.GetWriteBackUint32() << 21) |
4833 GetRegisterListEncoding(registers, 0, 16));
4834 return;
4835 }
4836 }
4837 Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4838}
4839
4840void Assembler::ldmdb(Condition cond,
4841 Register rn,
4842 WriteBack write_back,
4843 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004844 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004845 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004846 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004847 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004848 if (((registers.GetList() & ~0xdfff) == 0) &&
4849 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004850 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4851 (write_back.GetWriteBackUint32() << 21) |
4852 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4853 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4854 GetRegisterListEncoding(registers, 0, 13));
4855 AdvanceIT();
4856 return;
4857 }
4858 } else {
4859 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004860 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004861 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4862 (write_back.GetWriteBackUint32() << 21) |
4863 GetRegisterListEncoding(registers, 0, 16));
4864 return;
4865 }
4866 }
4867 Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4868}
4869
4870void Assembler::ldmea(Condition cond,
4871 Register rn,
4872 WriteBack write_back,
4873 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004874 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004875 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004876 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004877 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004878 if (((registers.GetList() & ~0xdfff) == 0) &&
4879 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004880 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4881 (write_back.GetWriteBackUint32() << 21) |
4882 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4883 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4884 GetRegisterListEncoding(registers, 0, 13));
4885 AdvanceIT();
4886 return;
4887 }
4888 } else {
4889 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004890 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004891 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4892 (write_back.GetWriteBackUint32() << 21) |
4893 GetRegisterListEncoding(registers, 0, 16));
4894 return;
4895 }
4896 }
4897 Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4898}
4899
4900void Assembler::ldmed(Condition cond,
4901 Register rn,
4902 WriteBack write_back,
4903 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004904 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004905 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004906 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004907 // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004908 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004909 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4910 (write_back.GetWriteBackUint32() << 21) |
4911 GetRegisterListEncoding(registers, 0, 16));
4912 return;
4913 }
4914 }
4915 Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4916}
4917
4918void Assembler::ldmfa(Condition cond,
4919 Register rn,
4920 WriteBack write_back,
4921 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004922 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004923 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004924 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004925 // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004926 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004927 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4928 (write_back.GetWriteBackUint32() << 21) |
4929 GetRegisterListEncoding(registers, 0, 16));
4930 return;
4931 }
4932 }
4933 Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4934}
4935
4936void Assembler::ldmfd(Condition cond,
4937 EncodingSize size,
4938 Register rn,
4939 WriteBack write_back,
4940 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004941 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004942 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004944 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4945 if (!size.IsWide() && rn.IsLow() &&
4946 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4947 write_back.DoesWriteBack()) &&
4948 ((registers.GetList() & ~0xff) == 0)) {
4949 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4950 GetRegisterListEncoding(registers, 0, 8));
4951 AdvanceIT();
4952 return;
4953 }
4954 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004955 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4956 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004957 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4958 (write_back.GetWriteBackUint32() << 21) |
4959 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4960 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4961 GetRegisterListEncoding(registers, 0, 13));
4962 AdvanceIT();
4963 return;
4964 }
4965 } else {
4966 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004967 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004968 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4969 (write_back.GetWriteBackUint32() << 21) |
4970 GetRegisterListEncoding(registers, 0, 16));
4971 return;
4972 }
4973 }
4974 Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4975}
4976
4977void Assembler::ldmib(Condition cond,
4978 Register rn,
4979 WriteBack write_back,
4980 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004981 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004982 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004983 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004984 // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004985 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004986 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4987 (write_back.GetWriteBackUint32() << 21) |
4988 GetRegisterListEncoding(registers, 0, 16));
4989 return;
4990 }
4991 }
4992 Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4993}
4994
4995void Assembler::ldr(Condition cond,
4996 EncodingSize size,
4997 Register rt,
4998 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004999 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005000 CheckIT(cond);
5001 if (operand.IsImmediate()) {
5002 Register rn = operand.GetBaseRegister();
5003 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005004 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005005 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5006 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005007 (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005008 int32_t offset_ = offset >> 2;
5009 EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
5010 ((offset_ & 0x1f) << 6));
5011 AdvanceIT();
5012 return;
5013 }
5014 // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
5015 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005016 ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005017 int32_t offset_ = offset >> 2;
5018 EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
5019 AdvanceIT();
5020 return;
5021 }
5022 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
5023 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005024 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5025 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5026 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005027 EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5028 (offset & 0xfff));
5029 AdvanceIT();
5030 return;
5031 }
5032 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
5033 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005034 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5035 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5036 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005037 EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5038 (-offset & 0xff));
5039 AdvanceIT();
5040 return;
5041 }
5042 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
5043 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005044 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5045 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5046 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005047 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5048 uint32_t offset_ = abs(offset);
5049 EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5050 offset_ | (sign << 9));
5051 AdvanceIT();
5052 return;
5053 }
5054 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
5055 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005056 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5057 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5058 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005059 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5060 uint32_t offset_ = abs(offset);
5061 EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5062 offset_ | (sign << 9));
5063 AdvanceIT();
5064 return;
5065 }
5066 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
5067 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005068 rn.Is(pc) && operand.IsOffset() &&
5069 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5070 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005071 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5072 uint32_t offset_ = abs(offset);
5073 EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5074 AdvanceIT();
5075 return;
5076 }
5077 } else {
5078 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005079 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5080 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005081 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5082 uint32_t offset_ = abs(offset);
5083 EmitA32(0x05100000U | (cond.GetCondition() << 28) |
5084 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5085 (sign << 23));
5086 return;
5087 }
5088 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005089 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5090 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005091 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5092 uint32_t offset_ = abs(offset);
5093 EmitA32(0x04100000U | (cond.GetCondition() << 28) |
5094 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5095 (sign << 23));
5096 return;
5097 }
5098 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005099 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5100 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005101 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5102 uint32_t offset_ = abs(offset);
5103 EmitA32(0x05300000U | (cond.GetCondition() << 28) |
5104 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5105 (sign << 23));
5106 return;
5107 }
5108 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5109 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005110 operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005111 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5112 uint32_t offset_ = abs(offset);
5113 EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
5114 (rt.GetCode() << 12) | offset_ | (sign << 23));
5115 return;
5116 }
5117 }
5118 }
5119 if (operand.IsPlainRegister()) {
5120 Register rn = operand.GetBaseRegister();
5121 Sign sign = operand.GetSign();
5122 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005123 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005124 // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5125 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005126 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005127 EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
5128 (rm.GetCode() << 6));
5129 AdvanceIT();
5130 return;
5131 }
5132 }
5133 }
5134 if (operand.IsShiftedRegister()) {
5135 Register rn = operand.GetBaseRegister();
5136 Sign sign = operand.GetSign();
5137 Register rm = operand.GetOffsetRegister();
5138 Shift shift = operand.GetShift();
5139 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005140 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005141 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5142 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005143 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5144 ((!rm.IsPC() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
5145 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005146 EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5147 rm.GetCode() | (amount << 4));
5148 AdvanceIT();
5149 return;
5150 }
5151 } else {
5152 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005153 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5154 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005155 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5156 uint32_t shift_ = TypeEncodingValue(shift);
5157 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5158 EmitA32(0x07100000U | (cond.GetCondition() << 28) |
5159 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5160 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5161 return;
5162 }
5163 // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005164 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005165 cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005166 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5167 uint32_t shift_ = TypeEncodingValue(shift);
5168 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5169 EmitA32(0x06100000U | (cond.GetCondition() << 28) |
5170 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5171 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5172 return;
5173 }
5174 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005175 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5176 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005177 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5178 uint32_t shift_ = TypeEncodingValue(shift);
5179 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5180 EmitA32(0x07300000U | (cond.GetCondition() << 28) |
5181 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5182 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5183 return;
5184 }
5185 }
5186 }
5187 Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
5188}
5189
5190void Assembler::ldr(Condition cond,
5191 EncodingSize size,
5192 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005193 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005194 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005195 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005196 Location::Offset offset =
5197 location->IsBound()
5198 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005199 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5200 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005201 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005202 // LDR{<c>}{<q>} <Rt>, <label> ; T1
5203 if (!size.IsWide() && rt.IsLow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005204 ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005205 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005206 (!location->IsBound() && size.IsNarrow()))) {
5207 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005208 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005209 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005210 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005211 Location::Offset pc,
5212 const Location* location) const VIXL_OVERRIDE {
5213 pc += kT32PcDelta;
5214 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005215 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
5216 ((offset & 0x3) == 0));
5217 const int32_t target = offset >> 2;
5218 return instr | (target & 0xff);
5219 }
5220 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005221 EmitT32_16(
Vincent Belliardac285442017-05-16 09:26:45 -07005222 Link(0x4800 | (rt.GetCode() << 8), location, immop, &kT16DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005223 AdvanceIT();
5224 return;
5225 }
5226 // LDR{<c>}{<q>} <Rt>, <label> ; T2
5227 if (!size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005228 ((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5229 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005230 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5231 AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005232 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005233 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005234 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005235 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005236 Location::Offset pc,
5237 const Location* location) const VIXL_OVERRIDE {
5238 pc += kT32PcDelta;
5239 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005240 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005241 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005242 int32_t target = abs(offset) | (U << 12);
5243 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5244 }
5245 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005246 EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12),
5247 location,
5248 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005249 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005250 AdvanceIT();
5251 return;
5252 }
5253 } else {
5254 // LDR{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005255 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5256 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005257 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005258 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005259 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005260 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005261 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005262 Location::Offset pc,
5263 const Location* location) const VIXL_OVERRIDE {
5264 pc += kA32PcDelta;
5265 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005266 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005267 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005268 int32_t target = abs(offset) | (U << 12);
5269 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5270 }
5271 } immop;
5272 EmitA32(
5273 Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005274 location,
5275 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005276 &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005277 return;
5278 }
5279 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005280 Delegate(kLdr, &Assembler::ldr, cond, size, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005281}
5282
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005283bool Assembler::ldr_info(Condition cond,
5284 EncodingSize size,
5285 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005286 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005287 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005288 VIXL_ASSERT(!location->IsBound());
5289 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005290 if (IsUsingT32()) {
5291 // LDR{<c>}{<q>} <Rt>, <label> ; T1
5292 if (!size.IsWide() && rt.IsLow() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005293 *info = &kT16DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005294 return true;
5295 }
5296 // LDR{<c>}{<q>} <Rt>, <label> ; T2
5297 if (!size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005298 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005299 return true;
5300 }
5301 } else {
5302 // LDR{<c>}{<q>} <Rt>, <label> ; A1
5303 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005304 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005305 return true;
5306 }
5307 }
5308 return false;
5309}
5310
Alexandre Ramesd3832962016-07-04 15:03:43 +01005311void Assembler::ldrb(Condition cond,
5312 EncodingSize size,
5313 Register rt,
5314 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005315 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005316 CheckIT(cond);
5317 if (operand.IsImmediate()) {
5318 Register rn = operand.GetBaseRegister();
5319 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005320 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005321 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5322 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005323 (offset <= 31) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005324 EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
5325 ((offset & 0x1f) << 6));
5326 AdvanceIT();
5327 return;
5328 }
5329 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5330 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005331 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005332 EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5333 (offset & 0xfff));
5334 AdvanceIT();
5335 return;
5336 }
5337 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5338 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005339 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005340 EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5341 (-offset & 0xff));
5342 AdvanceIT();
5343 return;
5344 }
5345 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5346 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005347 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005348 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5349 uint32_t offset_ = abs(offset);
5350 EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5351 offset_ | (sign << 9));
5352 AdvanceIT();
5353 return;
5354 }
5355 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5356 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005357 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005358 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5359 uint32_t offset_ = abs(offset);
5360 EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5361 offset_ | (sign << 9));
5362 AdvanceIT();
5363 return;
5364 }
5365 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5366 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005367 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005368 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5369 uint32_t offset_ = abs(offset);
5370 EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5371 AdvanceIT();
5372 return;
5373 }
5374 } else {
5375 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005376 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005377 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5378 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005379 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5380 uint32_t offset_ = abs(offset);
5381 EmitA32(0x05500000U | (cond.GetCondition() << 28) |
5382 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5383 (sign << 23));
5384 return;
5385 }
5386 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005387 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005388 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5389 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005390 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5391 uint32_t offset_ = abs(offset);
5392 EmitA32(0x04500000U | (cond.GetCondition() << 28) |
5393 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5394 (sign << 23));
5395 return;
5396 }
5397 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005398 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005399 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5400 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005401 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5402 uint32_t offset_ = abs(offset);
5403 EmitA32(0x05700000U | (cond.GetCondition() << 28) |
5404 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5405 (sign << 23));
5406 return;
5407 }
5408 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5409 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005410 operand.IsOffset() && cond.IsNotNever() &&
5411 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005412 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5413 uint32_t offset_ = abs(offset);
5414 EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
5415 (rt.GetCode() << 12) | offset_ | (sign << 23));
5416 return;
5417 }
5418 }
5419 }
5420 if (operand.IsPlainRegister()) {
5421 Register rn = operand.GetBaseRegister();
5422 Sign sign = operand.GetSign();
5423 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005424 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005425 // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5426 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005427 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005428 EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
5429 (rm.GetCode() << 6));
5430 AdvanceIT();
5431 return;
5432 }
5433 }
5434 }
5435 if (operand.IsShiftedRegister()) {
5436 Register rn = operand.GetBaseRegister();
5437 Sign sign = operand.GetSign();
5438 Register rm = operand.GetOffsetRegister();
5439 Shift shift = operand.GetShift();
5440 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005441 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005442 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5443 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005444 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
5445 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005446 EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5447 rm.GetCode() | (amount << 4));
5448 AdvanceIT();
5449 return;
5450 }
5451 } else {
5452 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005453 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5454 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005455 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5456 uint32_t shift_ = TypeEncodingValue(shift);
5457 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5458 EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5459 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5460 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5461 return;
5462 }
5463 // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005464 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005465 cond.IsNotNever() &&
5466 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005467 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5468 uint32_t shift_ = TypeEncodingValue(shift);
5469 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5470 EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5471 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5472 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5473 return;
5474 }
5475 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005476 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5477 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005478 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5479 uint32_t shift_ = TypeEncodingValue(shift);
5480 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5481 EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5482 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5483 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5484 return;
5485 }
5486 }
5487 }
5488 Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5489}
5490
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005491void Assembler::ldrb(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005493 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005494 Location::Offset offset =
5495 location->IsBound()
5496 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005497 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5498 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005499 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005500 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005501 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5502 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005503 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005504 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005505 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005506 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005507 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005508 Location::Offset pc,
5509 const Location* location) const VIXL_OVERRIDE {
5510 pc += kT32PcDelta;
5511 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005512 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005513 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005514 int32_t target = abs(offset) | (U << 12);
5515 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5516 }
5517 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005518 EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12),
5519 location,
5520 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005521 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005522 AdvanceIT();
5523 return;
5524 }
5525 } else {
5526 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005527 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5528 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005529 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005530 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005531 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005532 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005533 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005534 Location::Offset pc,
5535 const Location* location) const VIXL_OVERRIDE {
5536 pc += kA32PcDelta;
5537 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005538 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005539 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005540 int32_t target = abs(offset) | (U << 12);
5541 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5542 }
5543 } immop;
5544 EmitA32(
5545 Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005546 location,
5547 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005548 &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005549 return;
5550 }
5551 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005552 Delegate(kLdrb, &Assembler::ldrb, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005553}
5554
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005555bool Assembler::ldrb_info(Condition cond,
5556 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005557 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005558 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005559 VIXL_ASSERT(!location->IsBound());
5560 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005561 if (IsUsingT32()) {
5562 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5563 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07005564 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005565 return true;
5566 }
5567 } else {
5568 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5569 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005570 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005571 return true;
5572 }
5573 }
5574 return false;
5575}
5576
Alexandre Ramesd3832962016-07-04 15:03:43 +01005577void Assembler::ldrd(Condition cond,
5578 Register rt,
5579 Register rt2,
5580 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005581 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005582 CheckIT(cond);
5583 if (operand.IsImmediate()) {
5584 Register rn = operand.GetBaseRegister();
5585 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005586 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005587 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5588 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005589 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5590 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005591 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5592 uint32_t offset_ = abs(offset) >> 2;
5593 EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5594 (rn.GetCode() << 16) | offset_ | (sign << 23));
5595 AdvanceIT();
5596 return;
5597 }
5598 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5599 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005600 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5601 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005602 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5603 uint32_t offset_ = abs(offset) >> 2;
5604 EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5605 (rn.GetCode() << 16) | offset_ | (sign << 23));
5606 AdvanceIT();
5607 return;
5608 }
5609 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5610 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005611 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5612 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005613 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5614 uint32_t offset_ = abs(offset) >> 2;
5615 EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5616 (rn.GetCode() << 16) | offset_ | (sign << 23));
5617 AdvanceIT();
5618 return;
5619 }
5620 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5621 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005622 operand.IsOffset() &&
5623 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005624 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5625 uint32_t offset_ = abs(offset);
5626 EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5627 offset_ | (sign << 23));
5628 AdvanceIT();
5629 return;
5630 }
5631 } else {
5632 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5633 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005634 (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5635 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005636 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005637 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005638 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5639 uint32_t offset_ = abs(offset);
5640 EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5641 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5642 ((offset_ & 0xf0) << 4) | (sign << 23));
5643 return;
5644 }
5645 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5646 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005647 (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5648 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005649 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005650 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005651 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5652 uint32_t offset_ = abs(offset);
5653 EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5654 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5655 ((offset_ & 0xf0) << 4) | (sign << 23));
5656 return;
5657 }
5658 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5659 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005660 (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5661 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005662 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005663 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005664 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5665 uint32_t offset_ = abs(offset);
5666 EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5667 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5668 ((offset_ & 0xf0) << 4) | (sign << 23));
5669 return;
5670 }
5671 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5672 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5673 (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005674 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005675 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005676 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005677 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5678 uint32_t offset_ = abs(offset);
5679 EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5680 (rt.GetCode() << 12) | (offset_ & 0xf) |
5681 ((offset_ & 0xf0) << 4) | (sign << 23));
5682 return;
5683 }
5684 }
5685 }
5686 if (operand.IsPlainRegister()) {
5687 Register rn = operand.GetBaseRegister();
5688 Sign sign = operand.GetSign();
5689 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005690 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005691 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5692 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005693 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005694 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005695 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005696 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5697 EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5698 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5699 (sign_ << 23));
5700 return;
5701 }
5702 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5703 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005704 operand.IsPostIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005705 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005706 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005707 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5708 EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5709 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5710 (sign_ << 23));
5711 return;
5712 }
5713 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5714 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005715 operand.IsPreIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005716 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005717 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005718 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5719 EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5720 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5721 (sign_ << 23));
5722 return;
5723 }
5724 }
5725 }
5726 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5727}
5728
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005729void Assembler::ldrd(Condition cond,
5730 Register rt,
5731 Register rt2,
5732 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005733 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005734 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005735 Location::Offset offset =
5736 location->IsBound()
5737 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005738 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5739 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005740 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005741 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005742 if (((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005743 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005744 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005745 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005746 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005747 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005748 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005749 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005750 Location::Offset pc,
5751 const Location* location) const VIXL_OVERRIDE {
5752 pc += kT32PcDelta;
5753 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005754 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5755 ((offset & 0x3) == 0));
5756 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005757 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005758 target = abs(target) | (U << 8);
5759 return instr | (target & 0xff) | ((target & 0x100) << 15);
5760 }
5761 } immop;
5762 EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005763 location,
5764 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005765 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005766 AdvanceIT();
5767 return;
5768 }
5769 } else {
5770 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5771 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005772 ((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
5773 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005774 cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005775 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005776 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005777 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005778 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005779 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005780 Location::Offset pc,
5781 const Location* location) const VIXL_OVERRIDE {
5782 pc += kA32PcDelta;
5783 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005784 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005785 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005786 int32_t target = abs(offset) | (U << 8);
5787 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5788 ((target & 0x100) << 15);
5789 }
5790 } immop;
5791 EmitA32(
5792 Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005793 location,
5794 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005795 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005796 return;
5797 }
5798 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005799 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005800}
5801
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005802bool Assembler::ldrd_info(Condition cond,
5803 Register rt,
5804 Register rt2,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005805 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005806 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005807 VIXL_ASSERT(!location->IsBound());
5808 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005809 if (IsUsingT32()) {
5810 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5811 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07005812 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005813 return true;
5814 }
5815 } else {
5816 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5817 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5818 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005819 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005820 return true;
5821 }
5822 }
5823 return false;
5824}
5825
Alexandre Ramesd3832962016-07-04 15:03:43 +01005826void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005827 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005828 CheckIT(cond);
5829 if (operand.IsImmediate()) {
5830 Register rn = operand.GetBaseRegister();
5831 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005833 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5834 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005835 operand.IsOffset() &&
5836 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005837 int32_t offset_ = offset >> 2;
5838 EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5839 (offset_ & 0xff));
5840 AdvanceIT();
5841 return;
5842 }
5843 } else {
5844 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005845 if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
5846 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005847 EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5848 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5849 return;
5850 }
5851 }
5852 }
5853 Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5854}
5855
5856void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005857 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005858 CheckIT(cond);
5859 if (operand.IsImmediateZero()) {
5860 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005861 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005862 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005863 if (operand.IsOffset() &&
5864 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005865 EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5866 AdvanceIT();
5867 return;
5868 }
5869 } else {
5870 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005871 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005872 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005873 EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5874 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5875 return;
5876 }
5877 }
5878 }
5879 Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5880}
5881
5882void Assembler::ldrexd(Condition cond,
5883 Register rt,
5884 Register rt2,
5885 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005886 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005887 CheckIT(cond);
5888 if (operand.IsImmediateZero()) {
5889 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005890 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005891 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005892 if (operand.IsOffset() &&
5893 ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005894 EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5895 (rn.GetCode() << 16));
5896 AdvanceIT();
5897 return;
5898 }
5899 } else {
5900 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5901 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005902 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005903 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01005904 AllowUnpredictable())) {
5905 EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5906 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5907 return;
5908 }
5909 }
5910 }
5911 Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5912}
5913
5914void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005915 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005916 CheckIT(cond);
5917 if (operand.IsImmediateZero()) {
5918 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005919 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005920 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005921 if (operand.IsOffset() &&
5922 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005923 EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5924 AdvanceIT();
5925 return;
5926 }
5927 } else {
5928 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005929 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005930 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005931 EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5932 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5933 return;
5934 }
5935 }
5936 }
5937 Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5938}
5939
5940void Assembler::ldrh(Condition cond,
5941 EncodingSize size,
5942 Register rt,
5943 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005944 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005945 CheckIT(cond);
5946 if (operand.IsImmediate()) {
5947 Register rn = operand.GetBaseRegister();
5948 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005949 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005950 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5951 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005952 (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005953 int32_t offset_ = offset >> 1;
5954 EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5955 ((offset_ & 0x1f) << 6));
5956 AdvanceIT();
5957 return;
5958 }
5959 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5960 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005961 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005962 EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5963 (offset & 0xfff));
5964 AdvanceIT();
5965 return;
5966 }
5967 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5968 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005969 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005970 EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5971 (-offset & 0xff));
5972 AdvanceIT();
5973 return;
5974 }
5975 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5976 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005977 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005978 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5979 uint32_t offset_ = abs(offset);
5980 EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5981 offset_ | (sign << 9));
5982 AdvanceIT();
5983 return;
5984 }
5985 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5986 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005987 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005988 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5989 uint32_t offset_ = abs(offset);
5990 EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5991 offset_ | (sign << 9));
5992 AdvanceIT();
5993 return;
5994 }
5995 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5996 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005997 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005998 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5999 uint32_t offset_ = abs(offset);
6000 EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6001 AdvanceIT();
6002 return;
6003 }
6004 } else {
6005 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006006 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006007 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6008 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006009 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6010 uint32_t offset_ = abs(offset);
6011 EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
6012 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6013 ((offset_ & 0xf0) << 4) | (sign << 23));
6014 return;
6015 }
6016 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006017 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006018 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6019 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006020 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6021 uint32_t offset_ = abs(offset);
6022 EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
6023 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6024 ((offset_ & 0xf0) << 4) | (sign << 23));
6025 return;
6026 }
6027 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006028 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006029 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6030 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006031 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6032 uint32_t offset_ = abs(offset);
6033 EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
6034 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6035 ((offset_ & 0xf0) << 4) | (sign << 23));
6036 return;
6037 }
6038 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6039 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006040 operand.IsOffset() && cond.IsNotNever() &&
6041 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006042 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6043 uint32_t offset_ = abs(offset);
6044 EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
6045 (rt.GetCode() << 12) | (offset_ & 0xf) |
6046 ((offset_ & 0xf0) << 4) | (sign << 23));
6047 return;
6048 }
6049 }
6050 }
6051 if (operand.IsPlainRegister()) {
6052 Register rn = operand.GetBaseRegister();
6053 Sign sign = operand.GetSign();
6054 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006055 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006056 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6057 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006058 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006059 EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
6060 (rm.GetCode() << 6));
6061 AdvanceIT();
6062 return;
6063 }
6064 } else {
6065 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006066 if (operand.IsOffset() && cond.IsNotNever() &&
6067 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006068 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6069 EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
6070 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6071 (sign_ << 23));
6072 return;
6073 }
6074 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006075 if (operand.IsPostIndex() && cond.IsNotNever() &&
6076 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006077 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6078 EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
6079 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6080 (sign_ << 23));
6081 return;
6082 }
6083 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006084 if (operand.IsPreIndex() && cond.IsNotNever() &&
6085 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006086 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6087 EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
6088 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6089 (sign_ << 23));
6090 return;
6091 }
6092 }
6093 }
6094 if (operand.IsShiftedRegister()) {
6095 Register rn = operand.GetBaseRegister();
6096 Sign sign = operand.GetSign();
6097 Register rm = operand.GetOffsetRegister();
6098 Shift shift = operand.GetShift();
6099 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006100 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006101 // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6102 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006103 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6104 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006105 EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6106 rm.GetCode() | (amount << 4));
6107 AdvanceIT();
6108 return;
6109 }
6110 }
6111 }
6112 Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
6113}
6114
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006115void Assembler::ldrh(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006116 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006117 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006118 Location::Offset offset =
6119 location->IsBound()
6120 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006121 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6122 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006123 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006124 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006125 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6126 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006127 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006128 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006129 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006130 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006131 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006132 Location::Offset pc,
6133 const Location* location) const VIXL_OVERRIDE {
6134 pc += kT32PcDelta;
6135 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006136 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006137 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006138 int32_t target = abs(offset) | (U << 12);
6139 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6140 }
6141 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006142 EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12),
6143 location,
6144 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006145 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006146 AdvanceIT();
6147 return;
6148 }
6149 } else {
6150 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006151 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6152 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006153 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006154 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006155 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006156 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006157 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006158 Location::Offset pc,
6159 const Location* location) const VIXL_OVERRIDE {
6160 pc += kA32PcDelta;
6161 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006162 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006163 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006164 int32_t target = abs(offset) | (U << 8);
6165 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6166 ((target & 0x100) << 15);
6167 }
6168 } immop;
6169 EmitA32(
6170 Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006171 location,
6172 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006173 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006174 return;
6175 }
6176 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006177 Delegate(kLdrh, &Assembler::ldrh, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006178}
6179
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006180bool Assembler::ldrh_info(Condition cond,
6181 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006182 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006183 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006184 VIXL_ASSERT(!location->IsBound());
6185 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006186 if (IsUsingT32()) {
6187 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6188 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006189 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006190 return true;
6191 }
6192 } else {
6193 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6194 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006195 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006196 return true;
6197 }
6198 }
6199 return false;
6200}
6201
Alexandre Ramesd3832962016-07-04 15:03:43 +01006202void Assembler::ldrsb(Condition cond,
6203 EncodingSize size,
6204 Register rt,
6205 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006206 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006207 CheckIT(cond);
6208 if (operand.IsImmediate()) {
6209 Register rn = operand.GetBaseRegister();
6210 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006211 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006212 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6213 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006214 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006215 EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6216 (offset & 0xfff));
6217 AdvanceIT();
6218 return;
6219 }
6220 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6221 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006222 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006223 EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6224 (-offset & 0xff));
6225 AdvanceIT();
6226 return;
6227 }
6228 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6229 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006230 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006231 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6232 uint32_t offset_ = abs(offset);
6233 EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6234 offset_ | (sign << 9));
6235 AdvanceIT();
6236 return;
6237 }
6238 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6239 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006240 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006241 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6242 uint32_t offset_ = abs(offset);
6243 EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6244 offset_ | (sign << 9));
6245 AdvanceIT();
6246 return;
6247 }
6248 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6249 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006250 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006251 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6252 uint32_t offset_ = abs(offset);
6253 EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6254 AdvanceIT();
6255 return;
6256 }
6257 } else {
6258 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006259 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006260 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6261 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006262 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6263 uint32_t offset_ = abs(offset);
6264 EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
6265 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6266 ((offset_ & 0xf0) << 4) | (sign << 23));
6267 return;
6268 }
6269 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006270 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006271 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6272 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006273 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6274 uint32_t offset_ = abs(offset);
6275 EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
6276 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6277 ((offset_ & 0xf0) << 4) | (sign << 23));
6278 return;
6279 }
6280 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006281 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006282 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6283 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006284 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6285 uint32_t offset_ = abs(offset);
6286 EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
6287 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6288 ((offset_ & 0xf0) << 4) | (sign << 23));
6289 return;
6290 }
6291 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6292 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006293 operand.IsOffset() && cond.IsNotNever() &&
6294 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006295 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6296 uint32_t offset_ = abs(offset);
6297 EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
6298 (rt.GetCode() << 12) | (offset_ & 0xf) |
6299 ((offset_ & 0xf0) << 4) | (sign << 23));
6300 return;
6301 }
6302 }
6303 }
6304 if (operand.IsPlainRegister()) {
6305 Register rn = operand.GetBaseRegister();
6306 Sign sign = operand.GetSign();
6307 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006308 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006309 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6310 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006311 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006312 EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
6313 (rm.GetCode() << 6));
6314 AdvanceIT();
6315 return;
6316 }
6317 } else {
6318 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006319 if (operand.IsOffset() && cond.IsNotNever() &&
6320 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006321 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6322 EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
6323 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6324 (sign_ << 23));
6325 return;
6326 }
6327 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006328 if (operand.IsPostIndex() && cond.IsNotNever() &&
6329 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006330 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6331 EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
6332 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6333 (sign_ << 23));
6334 return;
6335 }
6336 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006337 if (operand.IsPreIndex() && cond.IsNotNever() &&
6338 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006339 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6340 EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
6341 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6342 (sign_ << 23));
6343 return;
6344 }
6345 }
6346 }
6347 if (operand.IsShiftedRegister()) {
6348 Register rn = operand.GetBaseRegister();
6349 Sign sign = operand.GetSign();
6350 Register rm = operand.GetOffsetRegister();
6351 Shift shift = operand.GetShift();
6352 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006353 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006354 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6355 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006356 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6357 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006358 EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6359 rm.GetCode() | (amount << 4));
6360 AdvanceIT();
6361 return;
6362 }
6363 }
6364 }
6365 Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
6366}
6367
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006368void Assembler::ldrsb(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006369 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006370 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006371 Location::Offset offset =
6372 location->IsBound()
6373 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006374 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6375 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006376 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006377 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006378 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6379 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006380 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006381 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006382 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006383 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006384 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006385 Location::Offset pc,
6386 const Location* location) const VIXL_OVERRIDE {
6387 pc += kT32PcDelta;
6388 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006389 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006390 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006391 int32_t target = abs(offset) | (U << 12);
6392 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6393 }
6394 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006395 EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12),
6396 location,
6397 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006398 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006399 AdvanceIT();
6400 return;
6401 }
6402 } else {
6403 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006404 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6405 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006406 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006407 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006408 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006409 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006410 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006411 Location::Offset pc,
6412 const Location* location) const VIXL_OVERRIDE {
6413 pc += kA32PcDelta;
6414 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006415 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006416 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006417 int32_t target = abs(offset) | (U << 8);
6418 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6419 ((target & 0x100) << 15);
6420 }
6421 } immop;
6422 EmitA32(
6423 Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006424 location,
6425 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006426 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006427 return;
6428 }
6429 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006430 Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006431}
6432
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006433bool Assembler::ldrsb_info(Condition cond,
6434 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006435 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006436 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006437 VIXL_ASSERT(!location->IsBound());
6438 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006439 if (IsUsingT32()) {
6440 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6441 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006442 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006443 return true;
6444 }
6445 } else {
6446 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6447 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006448 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006449 return true;
6450 }
6451 }
6452 return false;
6453}
6454
Alexandre Ramesd3832962016-07-04 15:03:43 +01006455void Assembler::ldrsh(Condition cond,
6456 EncodingSize size,
6457 Register rt,
6458 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006459 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006460 CheckIT(cond);
6461 if (operand.IsImmediate()) {
6462 Register rn = operand.GetBaseRegister();
6463 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006465 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6466 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006467 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006468 EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6469 (offset & 0xfff));
6470 AdvanceIT();
6471 return;
6472 }
6473 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6474 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006475 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006476 EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6477 (-offset & 0xff));
6478 AdvanceIT();
6479 return;
6480 }
6481 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6482 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006483 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006484 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6485 uint32_t offset_ = abs(offset);
6486 EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6487 offset_ | (sign << 9));
6488 AdvanceIT();
6489 return;
6490 }
6491 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6492 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006493 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006494 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6495 uint32_t offset_ = abs(offset);
6496 EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6497 offset_ | (sign << 9));
6498 AdvanceIT();
6499 return;
6500 }
6501 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6502 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006503 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006504 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6505 uint32_t offset_ = abs(offset);
6506 EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6507 AdvanceIT();
6508 return;
6509 }
6510 } else {
6511 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006512 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006513 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6514 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006515 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6516 uint32_t offset_ = abs(offset);
6517 EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
6518 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6519 ((offset_ & 0xf0) << 4) | (sign << 23));
6520 return;
6521 }
6522 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006523 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006524 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6525 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006526 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6527 uint32_t offset_ = abs(offset);
6528 EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
6529 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6530 ((offset_ & 0xf0) << 4) | (sign << 23));
6531 return;
6532 }
6533 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006534 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006535 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6536 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006537 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6538 uint32_t offset_ = abs(offset);
6539 EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
6540 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6541 ((offset_ & 0xf0) << 4) | (sign << 23));
6542 return;
6543 }
6544 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6545 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006546 operand.IsOffset() && cond.IsNotNever() &&
6547 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006548 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6549 uint32_t offset_ = abs(offset);
6550 EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
6551 (rt.GetCode() << 12) | (offset_ & 0xf) |
6552 ((offset_ & 0xf0) << 4) | (sign << 23));
6553 return;
6554 }
6555 }
6556 }
6557 if (operand.IsPlainRegister()) {
6558 Register rn = operand.GetBaseRegister();
6559 Sign sign = operand.GetSign();
6560 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006561 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006562 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6563 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006564 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006565 EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
6566 (rm.GetCode() << 6));
6567 AdvanceIT();
6568 return;
6569 }
6570 } else {
6571 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006572 if (operand.IsOffset() && cond.IsNotNever() &&
6573 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006574 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6575 EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6576 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6577 (sign_ << 23));
6578 return;
6579 }
6580 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006581 if (operand.IsPostIndex() && cond.IsNotNever() &&
6582 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006583 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6584 EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6585 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6586 (sign_ << 23));
6587 return;
6588 }
6589 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006590 if (operand.IsPreIndex() && cond.IsNotNever() &&
6591 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006592 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6593 EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6594 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6595 (sign_ << 23));
6596 return;
6597 }
6598 }
6599 }
6600 if (operand.IsShiftedRegister()) {
6601 Register rn = operand.GetBaseRegister();
6602 Sign sign = operand.GetSign();
6603 Register rm = operand.GetOffsetRegister();
6604 Shift shift = operand.GetShift();
6605 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006606 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006607 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6608 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006609 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6610 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006611 EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6612 rm.GetCode() | (amount << 4));
6613 AdvanceIT();
6614 return;
6615 }
6616 }
6617 }
6618 Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6619}
6620
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006621void Assembler::ldrsh(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006622 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006623 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006624 Location::Offset offset =
6625 location->IsBound()
6626 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006627 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6628 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006629 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006630 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006631 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6632 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006633 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006634 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006635 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006636 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006637 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006638 Location::Offset pc,
6639 const Location* location) const VIXL_OVERRIDE {
6640 pc += kT32PcDelta;
6641 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006642 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006643 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006644 int32_t target = abs(offset) | (U << 12);
6645 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6646 }
6647 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006648 EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12),
6649 location,
6650 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006651 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006652 AdvanceIT();
6653 return;
6654 }
6655 } else {
6656 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006657 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6658 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006659 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006660 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006661 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006662 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006663 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006664 Location::Offset pc,
6665 const Location* location) const VIXL_OVERRIDE {
6666 pc += kA32PcDelta;
6667 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006668 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006669 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006670 int32_t target = abs(offset) | (U << 8);
6671 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6672 ((target & 0x100) << 15);
6673 }
6674 } immop;
6675 EmitA32(
6676 Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006677 location,
6678 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006679 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006680 return;
6681 }
6682 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006683 Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006684}
6685
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006686bool Assembler::ldrsh_info(Condition cond,
6687 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006688 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006689 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006690 VIXL_ASSERT(!location->IsBound());
6691 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006692 if (IsUsingT32()) {
6693 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6694 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006695 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006696 return true;
6697 }
6698 } else {
6699 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6700 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006701 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006702 return true;
6703 }
6704 }
6705 return false;
6706}
6707
Alexandre Ramesd3832962016-07-04 15:03:43 +01006708void Assembler::lsl(Condition cond,
6709 EncodingSize size,
6710 Register rd,
6711 Register rm,
6712 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006713 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006714 CheckIT(cond);
6715 if (operand.IsImmediate()) {
6716 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006717 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006718 // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6719 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6720 (imm >= 1) && (imm <= 31)) {
6721 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6722 AdvanceIT();
6723 return;
6724 }
6725 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006726 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6727 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006728 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6729 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6730 AdvanceIT();
6731 return;
6732 }
6733 } else {
6734 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6735 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6736 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6737 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6738 return;
6739 }
6740 }
6741 }
6742 if (operand.IsPlainRegister()) {
6743 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006744 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006745 // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6746 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6747 rs.IsLow()) {
6748 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6749 AdvanceIT();
6750 return;
6751 }
6752 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006753 if (!size.IsNarrow() &&
6754 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006755 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6756 rs.GetCode());
6757 AdvanceIT();
6758 return;
6759 }
6760 } else {
6761 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006762 if (cond.IsNotNever() &&
6763 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006764 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6765 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6766 return;
6767 }
6768 }
6769 }
6770 Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6771}
6772
6773void Assembler::lsls(Condition cond,
6774 EncodingSize size,
6775 Register rd,
6776 Register rm,
6777 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006778 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006779 CheckIT(cond);
6780 if (operand.IsImmediate()) {
6781 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006783 // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6784 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6785 (imm >= 1) && (imm <= 31)) {
6786 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6787 AdvanceIT();
6788 return;
6789 }
6790 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006791 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6792 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006793 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6794 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6795 AdvanceIT();
6796 return;
6797 }
6798 } else {
6799 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6800 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6801 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6802 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6803 return;
6804 }
6805 }
6806 }
6807 if (operand.IsPlainRegister()) {
6808 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006809 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006810 // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6811 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6812 rs.IsLow()) {
6813 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6814 AdvanceIT();
6815 return;
6816 }
6817 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006818 if (!size.IsNarrow() &&
6819 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006820 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6821 rs.GetCode());
6822 AdvanceIT();
6823 return;
6824 }
6825 } else {
6826 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006827 if (cond.IsNotNever() &&
6828 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006829 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6830 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6831 return;
6832 }
6833 }
6834 }
6835 Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6836}
6837
6838void Assembler::lsr(Condition cond,
6839 EncodingSize size,
6840 Register rd,
6841 Register rm,
6842 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006843 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006844 CheckIT(cond);
6845 if (operand.IsImmediate()) {
6846 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006847 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006848 // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6849 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6850 (imm >= 1) && (imm <= 32)) {
6851 uint32_t amount_ = imm % 32;
6852 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6853 (amount_ << 6));
6854 AdvanceIT();
6855 return;
6856 }
6857 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006858 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6859 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006860 uint32_t amount_ = imm % 32;
6861 EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6862 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6863 AdvanceIT();
6864 return;
6865 }
6866 } else {
6867 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6868 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6869 uint32_t amount_ = imm % 32;
6870 EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6871 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6872 return;
6873 }
6874 }
6875 }
6876 if (operand.IsPlainRegister()) {
6877 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006878 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006879 // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6880 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6881 rs.IsLow()) {
6882 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6883 AdvanceIT();
6884 return;
6885 }
6886 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006887 if (!size.IsNarrow() &&
6888 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006889 EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6890 rs.GetCode());
6891 AdvanceIT();
6892 return;
6893 }
6894 } else {
6895 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006896 if (cond.IsNotNever() &&
6897 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006898 EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6899 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6900 return;
6901 }
6902 }
6903 }
6904 Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6905}
6906
6907void Assembler::lsrs(Condition cond,
6908 EncodingSize size,
6909 Register rd,
6910 Register rm,
6911 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006912 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006913 CheckIT(cond);
6914 if (operand.IsImmediate()) {
6915 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006916 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006917 // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6918 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6919 (imm >= 1) && (imm <= 32)) {
6920 uint32_t amount_ = imm % 32;
6921 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6922 (amount_ << 6));
6923 AdvanceIT();
6924 return;
6925 }
6926 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006927 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6928 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006929 uint32_t amount_ = imm % 32;
6930 EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6931 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6932 AdvanceIT();
6933 return;
6934 }
6935 } else {
6936 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6937 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6938 uint32_t amount_ = imm % 32;
6939 EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6940 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6941 return;
6942 }
6943 }
6944 }
6945 if (operand.IsPlainRegister()) {
6946 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006947 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006948 // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6949 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6950 rs.IsLow()) {
6951 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6952 AdvanceIT();
6953 return;
6954 }
6955 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006956 if (!size.IsNarrow() &&
6957 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006958 EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6959 rs.GetCode());
6960 AdvanceIT();
6961 return;
6962 }
6963 } else {
6964 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006965 if (cond.IsNotNever() &&
6966 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006967 EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6968 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6969 return;
6970 }
6971 }
6972 }
6973 Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6974}
6975
6976void Assembler::mla(
6977 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006978 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006979 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006980 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006981 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006982 if (!ra.Is(pc) &&
6983 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006984 EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6985 rm.GetCode() | (ra.GetCode() << 12));
6986 AdvanceIT();
6987 return;
6988 }
6989 } else {
6990 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006991 if (cond.IsNotNever() &&
6992 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6993 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006994 EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6995 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6996 return;
6997 }
6998 }
6999 Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
7000}
7001
7002void Assembler::mlas(
7003 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007004 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007005 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007006 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007007 // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007008 if (cond.IsNotNever() &&
7009 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7010 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007011 EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7012 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7013 return;
7014 }
7015 }
7016 Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
7017}
7018
7019void Assembler::mls(
7020 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007021 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007022 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007023 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007024 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007025 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7026 AllowUnpredictable())) {
7027 EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7028 rm.GetCode() | (ra.GetCode() << 12));
7029 AdvanceIT();
7030 return;
7031 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007032 } else {
7033 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007034 if (cond.IsNotNever() &&
7035 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7036 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007037 EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7038 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7039 return;
7040 }
7041 }
7042 Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
7043}
7044
7045void Assembler::mov(Condition cond,
7046 EncodingSize size,
7047 Register rd,
7048 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007049 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007050 CheckIT(cond);
7051 if (operand.IsImmediateShiftedRegister()) {
7052 Register rm = operand.GetBaseRegister();
7053 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007054 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007055 // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007056 if (!size.IsWide() &&
7057 ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
7058 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007059 EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
7060 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
7061 AdvanceIT();
7062 return;
7063 }
7064 }
7065 }
7066 Shift shift = operand.GetShift();
7067 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007068 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007069 // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7070 if (InITBlock() && !size.IsWide() && rd.IsLow() &&
7071 shift.IsValidAmount(amount) && rm.IsLow() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007072 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
7073 ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007074 uint32_t amount_ = amount % 32;
7075 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7076 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7077 AdvanceIT();
7078 return;
7079 }
7080 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007081 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7082 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007083 uint32_t amount_ = amount % 32;
7084 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7085 (operand.GetTypeEncodingValue() << 4) |
7086 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7087 AdvanceIT();
7088 return;
7089 }
7090 } else {
7091 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7092 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7093 uint32_t amount_ = amount % 32;
7094 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
7095 (rd.GetCode() << 12) | rm.GetCode() |
7096 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7097 return;
7098 }
7099 }
7100 }
7101 if (operand.IsRegisterShiftedRegister()) {
7102 Register rm = operand.GetBaseRegister();
7103 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007104 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007105 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007106 // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7107 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007108 shift.IsASR() && rs.IsLow()) {
7109 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007110 AdvanceIT();
7111 return;
7112 }
7113 // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7114 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007115 shift.IsLSL() && rs.IsLow()) {
7116 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007117 AdvanceIT();
7118 return;
7119 }
7120 // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7121 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007122 shift.IsLSR() && rs.IsLow()) {
7123 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007124 AdvanceIT();
7125 return;
7126 }
7127 // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7128 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007129 shift.IsROR() && rs.IsLow()) {
7130 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007131 AdvanceIT();
7132 return;
7133 }
7134 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
Vincent Belliard942e3b72016-11-29 15:50:14 -08007135 if (!size.IsNarrow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007136 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007137 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007138 (shift.GetType() << 21) | rs.GetCode());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007139 AdvanceIT();
7140 return;
7141 }
7142 } else {
7143 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007144 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007145 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007146 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
7147 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007148 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007149 return;
7150 }
7151 }
7152 }
7153 if (operand.IsImmediate()) {
7154 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007155 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007156 ImmediateT32 immediate_t32(imm);
7157 // MOV<c>{<q>} <Rd>, #<imm8> ; T1
7158 if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7159 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7160 AdvanceIT();
7161 return;
7162 }
7163 // MOV{<c>}{<q>} <Rd>, #<const> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007164 if (!size.IsNarrow() && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007165 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007166 EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
7167 (immediate_t32.GetEncodingValue() & 0xff) |
7168 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7169 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7170 AdvanceIT();
7171 return;
7172 }
7173 // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08007174 if (!size.IsNarrow() && (imm <= 65535) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007175 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007176 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7177 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7178 ((imm & 0xf000) << 4));
7179 AdvanceIT();
7180 return;
7181 }
7182 } else {
7183 ImmediateA32 immediate_a32(imm);
7184 // MOV{<c>}{<q>} <Rd>, #<const> ; A1
7185 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7186 EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
7187 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7188 return;
7189 }
7190 // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007191 if ((imm <= 65535) && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007192 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007193 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7194 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7195 return;
7196 }
7197 }
7198 }
7199 Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
7200}
7201
7202void Assembler::movs(Condition cond,
7203 EncodingSize size,
7204 Register rd,
7205 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007206 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007207 CheckIT(cond);
7208 if (operand.IsImmediateShiftedRegister()) {
7209 Register rm = operand.GetBaseRegister();
7210 Shift shift = operand.GetShift();
7211 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007212 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007213 // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7214 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
7215 shift.IsValidAmount(amount) && rm.IsLow() &&
7216 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
7217 uint32_t amount_ = amount % 32;
7218 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7219 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7220 AdvanceIT();
7221 return;
7222 }
7223 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007224 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7225 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007226 uint32_t amount_ = amount % 32;
7227 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7228 (operand.GetTypeEncodingValue() << 4) |
7229 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7230 AdvanceIT();
7231 return;
7232 }
7233 } else {
7234 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007235 if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
7236 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007237 uint32_t amount_ = amount % 32;
7238 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
7239 (rd.GetCode() << 12) | rm.GetCode() |
7240 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7241 return;
7242 }
7243 }
7244 }
7245 if (operand.IsRegisterShiftedRegister()) {
7246 Register rm = operand.GetBaseRegister();
7247 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007248 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007249 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007250 // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7251 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007252 shift.IsASR() && rs.IsLow()) {
7253 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007254 AdvanceIT();
7255 return;
7256 }
7257 // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7258 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007259 shift.IsLSL() && rs.IsLow()) {
7260 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007261 AdvanceIT();
7262 return;
7263 }
7264 // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7265 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007266 shift.IsLSR() && rs.IsLow()) {
7267 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007268 AdvanceIT();
7269 return;
7270 }
7271 // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7272 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007273 shift.IsROR() && rs.IsLow()) {
7274 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007275 AdvanceIT();
7276 return;
7277 }
7278 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
Vincent Belliard942e3b72016-11-29 15:50:14 -08007279 if (!size.IsNarrow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007280 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007281 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007282 (shift.GetType() << 21) | rs.GetCode());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007283 AdvanceIT();
7284 return;
7285 }
7286 } else {
7287 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007288 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007289 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007290 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
7291 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007292 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007293 return;
7294 }
7295 }
7296 }
7297 if (operand.IsImmediate()) {
7298 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007299 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007300 ImmediateT32 immediate_t32(imm);
7301 // MOVS{<q>} <Rd>, #<imm8> ; T1
7302 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7303 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7304 AdvanceIT();
7305 return;
7306 }
7307 // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007308 if (!size.IsNarrow() && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007309 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007310 EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
7311 (immediate_t32.GetEncodingValue() & 0xff) |
7312 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7313 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7314 AdvanceIT();
7315 return;
7316 }
7317 } else {
7318 ImmediateA32 immediate_a32(imm);
7319 // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
7320 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7321 EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
7322 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7323 return;
7324 }
7325 }
7326 }
7327 Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
7328}
7329
7330void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007331 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007332 CheckIT(cond);
7333 if (operand.IsImmediate()) {
7334 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007335 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007336 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007337 if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007338 EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
7339 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7340 ((imm & 0xf000) << 4));
7341 AdvanceIT();
7342 return;
7343 }
7344 } else {
7345 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007346 if ((imm <= 65535) && cond.IsNotNever() &&
7347 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007348 EmitA32(0x03400000U | (cond.GetCondition() << 28) |
7349 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7350 return;
7351 }
7352 }
7353 }
7354 Delegate(kMovt, &Assembler::movt, cond, rd, operand);
7355}
7356
7357void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007358 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007359 CheckIT(cond);
7360 if (operand.IsImmediate()) {
7361 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007362 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007363 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007364 if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007365 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7366 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7367 ((imm & 0xf000) << 4));
7368 AdvanceIT();
7369 return;
7370 }
7371 } else {
7372 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007373 if ((imm <= 65535) && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007374 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007375 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7376 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7377 return;
7378 }
7379 }
7380 }
7381 Delegate(kMovw, &Assembler::movw, cond, rd, operand);
7382}
7383
7384void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007385 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007386 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007387 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007388 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007389 if ((!rd.IsPC() || AllowUnpredictable())) {
7390 EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
7391 AdvanceIT();
7392 return;
7393 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007394 } else {
7395 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007396 if (cond.IsNotNever() && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007397 EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7398 (spec_reg.GetReg() << 22));
7399 return;
7400 }
7401 }
7402 Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
7403}
7404
7405void Assembler::msr(Condition cond,
7406 MaskedSpecialRegister spec_reg,
7407 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007408 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007409 CheckIT(cond);
7410 if (operand.IsImmediate()) {
7411 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007412 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007413 ImmediateA32 immediate_a32(imm);
7414 // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
7415 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7416 EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
7417 ((spec_reg.GetReg() & 0xf) << 16) |
7418 ((spec_reg.GetReg() & 0x10) << 18) |
7419 immediate_a32.GetEncodingValue());
7420 return;
7421 }
7422 }
7423 }
7424 if (operand.IsPlainRegister()) {
7425 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007426 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007427 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007428 if ((!rn.IsPC() || AllowUnpredictable())) {
7429 EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
7430 ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
7431 AdvanceIT();
7432 return;
7433 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007434 } else {
7435 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007436 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007437 EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
7438 ((spec_reg.GetReg() & 0xf) << 16) |
7439 ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
7440 return;
7441 }
7442 }
7443 }
7444 Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
7445}
7446
7447void Assembler::mul(
7448 Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007449 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007450 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007451 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007452 // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7453 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
7454 rm.IsLow()) {
7455 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7456 AdvanceIT();
7457 return;
7458 }
7459 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007460 if (!size.IsNarrow() &&
7461 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007462 EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7463 rm.GetCode());
7464 AdvanceIT();
7465 return;
7466 }
7467 } else {
7468 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007469 if (cond.IsNotNever() &&
7470 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007471 EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7472 rn.GetCode() | (rm.GetCode() << 8));
7473 return;
7474 }
7475 }
7476 Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
7477}
7478
7479void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007480 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007481 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007482 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007483 // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7484 if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
7485 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7486 AdvanceIT();
7487 return;
7488 }
7489 } else {
7490 // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007491 if (cond.IsNotNever() &&
7492 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007493 EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7494 rn.GetCode() | (rm.GetCode() << 8));
7495 return;
7496 }
7497 }
7498 Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
7499}
7500
7501void Assembler::mvn(Condition cond,
7502 EncodingSize size,
7503 Register rd,
7504 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007505 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007506 CheckIT(cond);
7507 if (operand.IsImmediate()) {
7508 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007509 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007510 ImmediateT32 immediate_t32(imm);
7511 // MVN{<c>}{<q>} <Rd>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007512 if (!size.IsNarrow() && immediate_t32.IsValid() &&
7513 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007514 EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
7515 (immediate_t32.GetEncodingValue() & 0xff) |
7516 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7517 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7518 AdvanceIT();
7519 return;
7520 }
7521 } else {
7522 ImmediateA32 immediate_a32(imm);
7523 // MVN{<c>}{<q>} <Rd>, #<const> ; A1
7524 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7525 EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
7526 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7527 return;
7528 }
7529 }
7530 }
7531 if (operand.IsImmediateShiftedRegister()) {
7532 Register rm = operand.GetBaseRegister();
7533 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007534 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007535 // MVN<c>{<q>} <Rd>, <Rm> ; T1
7536 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7537 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7538 AdvanceIT();
7539 return;
7540 }
7541 }
7542 }
7543 Shift shift = operand.GetShift();
7544 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007545 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007546 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007547 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7548 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007549 uint32_t amount_ = amount % 32;
7550 EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7551 (operand.GetTypeEncodingValue() << 4) |
7552 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7553 AdvanceIT();
7554 return;
7555 }
7556 } else {
7557 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7558 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7559 uint32_t amount_ = amount % 32;
7560 EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
7561 (rd.GetCode() << 12) | rm.GetCode() |
7562 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7563 return;
7564 }
7565 }
7566 }
7567 if (operand.IsRegisterShiftedRegister()) {
7568 Register rm = operand.GetBaseRegister();
7569 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007570 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007571 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007572 // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007573 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007574 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007575 EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
7576 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007577 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007578 return;
7579 }
7580 }
7581 }
7582 Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
7583}
7584
7585void Assembler::mvns(Condition cond,
7586 EncodingSize size,
7587 Register rd,
7588 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007589 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007590 CheckIT(cond);
7591 if (operand.IsImmediate()) {
7592 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007593 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007594 ImmediateT32 immediate_t32(imm);
7595 // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007596 if (!size.IsNarrow() && immediate_t32.IsValid() &&
7597 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007598 EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
7599 (immediate_t32.GetEncodingValue() & 0xff) |
7600 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7601 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7602 AdvanceIT();
7603 return;
7604 }
7605 } else {
7606 ImmediateA32 immediate_a32(imm);
7607 // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
7608 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7609 EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
7610 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7611 return;
7612 }
7613 }
7614 }
7615 if (operand.IsImmediateShiftedRegister()) {
7616 Register rm = operand.GetBaseRegister();
7617 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007618 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007619 // MVNS{<q>} <Rd>, <Rm> ; T1
7620 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7621 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7622 AdvanceIT();
7623 return;
7624 }
7625 }
7626 }
7627 Shift shift = operand.GetShift();
7628 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007629 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007630 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007631 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7632 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007633 uint32_t amount_ = amount % 32;
7634 EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7635 (operand.GetTypeEncodingValue() << 4) |
7636 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7637 AdvanceIT();
7638 return;
7639 }
7640 } else {
7641 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7642 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7643 uint32_t amount_ = amount % 32;
7644 EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7645 (rd.GetCode() << 12) | rm.GetCode() |
7646 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7647 return;
7648 }
7649 }
7650 }
7651 if (operand.IsRegisterShiftedRegister()) {
7652 Register rm = operand.GetBaseRegister();
7653 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007654 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007655 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007656 // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007657 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007658 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007659 EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7660 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007661 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007662 return;
7663 }
7664 }
7665 }
7666 Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7667}
7668
7669void Assembler::nop(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007670 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007671 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007673 // NOP{<c>}{<q>} ; T1
7674 if (!size.IsWide()) {
7675 EmitT32_16(0xbf00);
7676 AdvanceIT();
7677 return;
7678 }
7679 // NOP{<c>}.W ; T2
7680 if (!size.IsNarrow()) {
7681 EmitT32_32(0xf3af8000U);
7682 AdvanceIT();
7683 return;
7684 }
7685 } else {
7686 // NOP{<c>}{<q>} ; A1
7687 if (cond.IsNotNever()) {
7688 EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7689 return;
7690 }
7691 }
7692 Delegate(kNop, &Assembler::nop, cond, size);
7693}
7694
7695void Assembler::orn(Condition cond,
7696 Register rd,
7697 Register rn,
7698 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007699 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007700 CheckIT(cond);
7701 if (operand.IsImmediate()) {
7702 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007703 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007704 ImmediateT32 immediate_t32(imm);
7705 // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007706 if (immediate_t32.IsValid() && !rn.Is(pc) &&
7707 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007708 EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7709 (immediate_t32.GetEncodingValue() & 0xff) |
7710 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7711 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7712 AdvanceIT();
7713 return;
7714 }
7715 }
7716 }
7717 if (operand.IsImmediateShiftedRegister()) {
7718 Register rm = operand.GetBaseRegister();
7719 Shift shift = operand.GetShift();
7720 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007721 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007722 // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007723 if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7724 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007725 uint32_t amount_ = amount % 32;
7726 EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7727 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7728 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7729 AdvanceIT();
7730 return;
7731 }
7732 }
7733 }
7734 Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7735}
7736
7737void Assembler::orns(Condition cond,
7738 Register rd,
7739 Register rn,
7740 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007741 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007742 CheckIT(cond);
7743 if (operand.IsImmediate()) {
7744 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007745 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007746 ImmediateT32 immediate_t32(imm);
7747 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007748 if (immediate_t32.IsValid() && !rn.Is(pc) &&
7749 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007750 EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7751 (immediate_t32.GetEncodingValue() & 0xff) |
7752 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7753 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7754 AdvanceIT();
7755 return;
7756 }
7757 }
7758 }
7759 if (operand.IsImmediateShiftedRegister()) {
7760 Register rm = operand.GetBaseRegister();
7761 Shift shift = operand.GetShift();
7762 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007763 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007764 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007765 if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7766 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007767 uint32_t amount_ = amount % 32;
7768 EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7769 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7770 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7771 AdvanceIT();
7772 return;
7773 }
7774 }
7775 }
7776 Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7777}
7778
7779void Assembler::orr(Condition cond,
7780 EncodingSize size,
7781 Register rd,
7782 Register rn,
7783 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007784 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007785 CheckIT(cond);
7786 if (operand.IsImmediate()) {
7787 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007788 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007789 ImmediateT32 immediate_t32(imm);
7790 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007791 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7792 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007793 EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7794 (immediate_t32.GetEncodingValue() & 0xff) |
7795 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7796 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7797 AdvanceIT();
7798 return;
7799 }
7800 } else {
7801 ImmediateA32 immediate_a32(imm);
7802 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7803 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7804 EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7805 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7806 immediate_a32.GetEncodingValue());
7807 return;
7808 }
7809 }
7810 }
7811 if (operand.IsImmediateShiftedRegister()) {
7812 Register rm = operand.GetBaseRegister();
7813 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007814 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007815 // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7816 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7817 rm.IsLow()) {
7818 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7819 AdvanceIT();
7820 return;
7821 }
7822 }
7823 }
7824 Shift shift = operand.GetShift();
7825 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007826 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007827 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007828 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7829 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007830 uint32_t amount_ = amount % 32;
7831 EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7832 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7833 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7834 AdvanceIT();
7835 return;
7836 }
7837 } else {
7838 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7839 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7840 uint32_t amount_ = amount % 32;
7841 EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7842 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7843 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7844 return;
7845 }
7846 }
7847 }
7848 if (operand.IsRegisterShiftedRegister()) {
7849 Register rm = operand.GetBaseRegister();
7850 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007851 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007852 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007853 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00007854 if (cond.IsNotNever() &&
7855 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7856 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007857 EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7858 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007859 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007860 return;
7861 }
7862 }
7863 }
7864 Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7865}
7866
7867void Assembler::orrs(Condition cond,
7868 EncodingSize size,
7869 Register rd,
7870 Register rn,
7871 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007872 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007873 CheckIT(cond);
7874 if (operand.IsImmediate()) {
7875 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007876 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007877 ImmediateT32 immediate_t32(imm);
7878 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007879 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7880 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007881 EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7882 (immediate_t32.GetEncodingValue() & 0xff) |
7883 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7884 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7885 AdvanceIT();
7886 return;
7887 }
7888 } else {
7889 ImmediateA32 immediate_a32(imm);
7890 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7891 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7892 EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7893 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7894 immediate_a32.GetEncodingValue());
7895 return;
7896 }
7897 }
7898 }
7899 if (operand.IsImmediateShiftedRegister()) {
7900 Register rm = operand.GetBaseRegister();
7901 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007902 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007903 // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7904 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7905 rm.IsLow()) {
7906 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7907 AdvanceIT();
7908 return;
7909 }
7910 }
7911 }
7912 Shift shift = operand.GetShift();
7913 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007914 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007915 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007916 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7917 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007918 uint32_t amount_ = amount % 32;
7919 EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7920 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7921 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7922 AdvanceIT();
7923 return;
7924 }
7925 } else {
7926 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7927 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7928 uint32_t amount_ = amount % 32;
7929 EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7930 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7931 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7932 return;
7933 }
7934 }
7935 }
7936 if (operand.IsRegisterShiftedRegister()) {
7937 Register rm = operand.GetBaseRegister();
7938 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007939 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007940 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007941 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00007942 if (cond.IsNotNever() &&
7943 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7944 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007945 EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7946 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007947 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007948 return;
7949 }
7950 }
7951 }
7952 Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7953}
7954
7955void Assembler::pkhbt(Condition cond,
7956 Register rd,
7957 Register rn,
7958 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007959 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007960 CheckIT(cond);
7961 if (operand.IsImmediateShiftedRegister()) {
7962 Register rm = operand.GetBaseRegister();
7963 Shift shift = operand.GetShift();
7964 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007965 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007966 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007967 if (shift.IsLSL() && shift.IsValidAmount(amount) &&
7968 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007969 EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7970 rm.GetCode() | ((amount & 0x3) << 6) |
7971 ((amount & 0x1c) << 10));
7972 AdvanceIT();
7973 return;
7974 }
7975 } else {
7976 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007977 if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever() &&
7978 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007979 EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7980 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7981 (amount << 7));
7982 return;
7983 }
7984 }
7985 }
7986 Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7987}
7988
7989void Assembler::pkhtb(Condition cond,
7990 Register rd,
7991 Register rn,
7992 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007993 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007994 CheckIT(cond);
7995 if (operand.IsImmediateShiftedRegister()) {
7996 Register rm = operand.GetBaseRegister();
7997 Shift shift = operand.GetShift();
7998 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007999 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008000 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008001 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
8002 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008003 uint32_t amount_ = amount % 32;
8004 EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8005 rm.GetCode() | ((amount_ & 0x3) << 6) |
8006 ((amount_ & 0x1c) << 10));
8007 AdvanceIT();
8008 return;
8009 }
8010 } else {
8011 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
8012 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008013 cond.IsNotNever() &&
8014 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008015 uint32_t amount_ = amount % 32;
8016 EmitA32(0x06800050U | (cond.GetCondition() << 28) |
8017 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
8018 (amount_ << 7));
8019 return;
8020 }
8021 }
8022 }
8023 Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
8024}
8025
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008026void Assembler::pld(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008027 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008028 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008029 Location::Offset offset =
8030 location->IsBound()
8031 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01008032 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8033 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008034 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008035 // PLD{<c>}{<q>} <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008036 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8037 !location->IsBound())) {
8038 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008039 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008040 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008041 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008042 Location::Offset pc,
8043 const Location* location) const VIXL_OVERRIDE {
8044 pc += kT32PcDelta;
8045 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008046 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008047 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008048 int32_t target = abs(offset) | (U << 12);
8049 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8050 }
8051 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008052 EmitT32_32(Link(0xf81ff000U, location, immop, &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008053 AdvanceIT();
8054 return;
8055 }
8056 } else {
8057 // PLD{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008058 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8059 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008060 if (cond.Is(al)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008061 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008062 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008063 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008064 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008065 Location::Offset pc,
8066 const Location* location) const
8067 VIXL_OVERRIDE {
8068 pc += kA32PcDelta;
8069 Location::Offset offset =
8070 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008071 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008072 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008073 int32_t target = abs(offset) | (U << 12);
8074 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8075 }
8076 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008077 EmitA32(Link(0xf55ff000U, location, immop, &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008078 return;
8079 }
8080 }
8081 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008082 Delegate(kPld, &Assembler::pld, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008083}
8084
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008085bool Assembler::pld_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008086 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008087 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008088 VIXL_ASSERT(!location->IsBound());
8089 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008090 USE(cond);
8091 if (IsUsingT32()) {
8092 // PLD{<c>}{<q>} <label> ; T1
8093 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008094 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008095 return true;
8096 }
8097 } else {
8098 // PLD{<c>}{<q>} <label> ; A1
8099 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008100 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008101 return true;
8102 }
8103 }
8104 return false;
8105}
8106
Alexandre Ramesd3832962016-07-04 15:03:43 +01008107void Assembler::pld(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008108 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008109 CheckIT(cond);
8110 if (operand.IsImmediate()) {
8111 Register rn = operand.GetBaseRegister();
8112 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008113 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008114 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008115 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8116 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008117 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8118 uint32_t offset_ = abs(offset);
8119 EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
8120 AdvanceIT();
8121 return;
8122 }
8123 } else {
8124 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008125 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8126 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008127 if (cond.Is(al)) {
8128 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8129 uint32_t offset_ = abs(offset);
8130 EmitA32(0xf55ff000U | offset_ | (sign << 23));
8131 return;
8132 }
8133 }
8134 }
8135 }
8136 if (operand.IsImmediate()) {
8137 Register rn = operand.GetBaseRegister();
8138 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008139 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008140 // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008141 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8142 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008143 EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8144 AdvanceIT();
8145 return;
8146 }
8147 // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008148 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8149 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008150 EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8151 AdvanceIT();
8152 return;
8153 }
8154 } else {
8155 // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008156 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008157 ((rn.GetCode() & 0xf) != 0xf)) {
8158 if (cond.Is(al)) {
8159 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8160 uint32_t offset_ = abs(offset);
8161 EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8162 return;
8163 }
8164 }
8165 }
8166 }
8167 if (operand.IsShiftedRegister()) {
8168 Register rn = operand.GetBaseRegister();
8169 Sign sign = operand.GetSign();
8170 Register rm = operand.GetOffsetRegister();
8171 Shift shift = operand.GetShift();
8172 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008173 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008174 // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008175 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008176 ((rn.GetCode() & 0xf) != 0xf) &&
8177 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008178 EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
8179 (amount << 4));
8180 AdvanceIT();
8181 return;
8182 }
8183 } else {
8184 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008185 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8186 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008187 if (cond.Is(al)) {
8188 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8189 uint32_t amount_ = amount % 32;
8190 EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
8191 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8192 return;
8193 }
8194 }
8195 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008196 if (shift.IsRRX() && operand.IsOffset() &&
8197 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008198 if (cond.Is(al)) {
8199 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8200 EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
8201 (sign_ << 23));
8202 return;
8203 }
8204 }
8205 }
8206 }
8207 Delegate(kPld, &Assembler::pld, cond, operand);
8208}
8209
8210void Assembler::pldw(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008211 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008212 CheckIT(cond);
8213 if (operand.IsImmediate()) {
8214 Register rn = operand.GetBaseRegister();
8215 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008216 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008217 // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008218 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8219 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008220 EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8221 AdvanceIT();
8222 return;
8223 }
8224 // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008225 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8226 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008227 EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8228 AdvanceIT();
8229 return;
8230 }
8231 } else {
8232 // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008233 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008234 ((rn.GetCode() & 0xf) != 0xf)) {
8235 if (cond.Is(al)) {
8236 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8237 uint32_t offset_ = abs(offset);
8238 EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8239 return;
8240 }
8241 }
8242 }
8243 }
8244 if (operand.IsShiftedRegister()) {
8245 Register rn = operand.GetBaseRegister();
8246 Sign sign = operand.GetSign();
8247 Register rm = operand.GetOffsetRegister();
8248 Shift shift = operand.GetShift();
8249 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008250 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008251 // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008252 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008253 ((rn.GetCode() & 0xf) != 0xf) &&
8254 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008255 EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
8256 (amount << 4));
8257 AdvanceIT();
8258 return;
8259 }
8260 } else {
8261 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008262 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8263 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008264 if (cond.Is(al)) {
8265 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8266 uint32_t amount_ = amount % 32;
8267 EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
8268 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8269 return;
8270 }
8271 }
8272 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008273 if (shift.IsRRX() && operand.IsOffset() &&
8274 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008275 if (cond.Is(al)) {
8276 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8277 EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
8278 (sign_ << 23));
8279 return;
8280 }
8281 }
8282 }
8283 }
8284 Delegate(kPldw, &Assembler::pldw, cond, operand);
8285}
8286
8287void Assembler::pli(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008288 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008289 CheckIT(cond);
8290 if (operand.IsImmediate()) {
8291 Register rn = operand.GetBaseRegister();
8292 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008293 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008294 // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008295 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8296 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008297 EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8298 AdvanceIT();
8299 return;
8300 }
8301 // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008302 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8303 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008304 EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8305 AdvanceIT();
8306 return;
8307 }
8308 } else {
8309 // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008310 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008311 ((rn.GetCode() & 0xf) != 0xf)) {
8312 if (cond.Is(al)) {
8313 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8314 uint32_t offset_ = abs(offset);
8315 EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8316 return;
8317 }
8318 }
8319 }
8320 }
8321 if (operand.IsImmediate()) {
8322 Register rn = operand.GetBaseRegister();
8323 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008324 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008325 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008326 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8327 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008328 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8329 uint32_t offset_ = abs(offset);
8330 EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
8331 AdvanceIT();
8332 return;
8333 }
8334 } else {
8335 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008336 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8337 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008338 if (cond.Is(al)) {
8339 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8340 uint32_t offset_ = abs(offset);
8341 EmitA32(0xf45ff000U | offset_ | (sign << 23));
8342 return;
8343 }
8344 }
8345 }
8346 }
8347 if (operand.IsShiftedRegister()) {
8348 Register rn = operand.GetBaseRegister();
8349 Sign sign = operand.GetSign();
8350 Register rm = operand.GetOffsetRegister();
8351 Shift shift = operand.GetShift();
8352 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008353 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008354 // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008355 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008356 ((rn.GetCode() & 0xf) != 0xf) &&
8357 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008358 EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
8359 (amount << 4));
8360 AdvanceIT();
8361 return;
8362 }
8363 } else {
8364 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008365 if (shift.IsRRX() && operand.IsOffset() &&
8366 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008367 if (cond.Is(al)) {
8368 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8369 EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
8370 (sign_ << 23));
8371 return;
8372 }
8373 }
8374 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008375 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8376 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008377 if (cond.Is(al)) {
8378 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8379 uint32_t amount_ = amount % 32;
8380 EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
8381 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8382 return;
8383 }
8384 }
8385 }
8386 }
8387 Delegate(kPli, &Assembler::pli, cond, operand);
8388}
8389
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008390void Assembler::pli(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008391 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008392 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008393 Location::Offset offset =
8394 location->IsBound()
8395 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01008396 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8397 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008398 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008399 // PLI{<c>}{<q>} <label> ; T3
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008400 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8401 !location->IsBound())) {
8402 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008403 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008404 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008405 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008406 Location::Offset pc,
8407 const Location* location) const VIXL_OVERRIDE {
8408 pc += kT32PcDelta;
8409 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008410 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008411 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008412 int32_t target = abs(offset) | (U << 12);
8413 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8414 }
8415 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008416 EmitT32_32(Link(0xf91ff000U, location, immop, &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008417 AdvanceIT();
8418 return;
8419 }
8420 } else {
8421 // PLI{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008422 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8423 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008424 if (cond.Is(al)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008425 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008426 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008427 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008428 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008429 Location::Offset pc,
8430 const Location* location) const
8431 VIXL_OVERRIDE {
8432 pc += kA32PcDelta;
8433 Location::Offset offset =
8434 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008435 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008436 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008437 int32_t target = abs(offset) | (U << 12);
8438 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8439 }
8440 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008441 EmitA32(Link(0xf45ff000U, location, immop, &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008442 return;
8443 }
8444 }
8445 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008446 Delegate(kPli, &Assembler::pli, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008447}
8448
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008449bool Assembler::pli_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008450 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008451 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008452 VIXL_ASSERT(!location->IsBound());
8453 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008454 USE(cond);
8455 if (IsUsingT32()) {
8456 // PLI{<c>}{<q>} <label> ; T3
8457 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008458 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008459 return true;
8460 }
8461 } else {
8462 // PLI{<c>}{<q>} <label> ; A1
8463 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008464 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008465 return true;
8466 }
8467 }
8468 return false;
8469}
8470
Alexandre Ramesd3832962016-07-04 15:03:43 +01008471void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008472 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008473 CheckIT(cond);
Peter Collingbourne920189b2021-01-22 17:42:36 -08008474 if (!registers.IsEmpty() || AllowUnpredictable()) {
8475 if (IsUsingT32()) {
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008476 // A branch out of an IT block should be the last instruction in the
8477 // block.
8478 if (!registers.Includes(pc) || OutsideITBlockAndAlOrLast(cond) ||
8479 AllowUnpredictable()) {
8480 // POP{<c>}{<q>} <registers> ; T1
8481 if (!size.IsWide() && registers.IsR0toR7orPC()) {
8482 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
8483 GetRegisterListEncoding(registers, 0, 8));
8484 AdvanceIT();
8485 return;
8486 }
8487 // POP{<c>}{<q>} <registers> ; T2
8488 // Alias of: LDM{<c>}{<q>} SP!, <registers> ; T2
8489 if (!size.IsNarrow() &&
8490 ((!registers.Includes(sp) && (registers.GetCount() > 1) &&
8491 !(registers.Includes(pc) && registers.Includes(lr))) ||
8492 AllowUnpredictable())) {
8493 EmitT32_32(0xe8bd0000U | GetRegisterListEncoding(registers, 0, 16));
8494 AdvanceIT();
8495 return;
8496 }
Peter Collingbourne920189b2021-01-22 17:42:36 -08008497 }
8498 } else {
8499 // POP{<c>}{<q>} <registers> ; A1
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008500 // Alias of: LDM{<c>}{<q>} SP!, <registers> ; A1
Peter Collingbourne920189b2021-01-22 17:42:36 -08008501 if (cond.IsNotNever() &&
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008502 (!registers.Includes(sp) || AllowUnpredictable())) {
Peter Collingbourne920189b2021-01-22 17:42:36 -08008503 EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
8504 GetRegisterListEncoding(registers, 0, 16));
8505 return;
8506 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008507 }
8508 }
8509 Delegate(kPop, &Assembler::pop, cond, size, registers);
8510}
8511
8512void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008513 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008514 CheckIT(cond);
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008515 if (!rt.IsSP() || AllowUnpredictable()) {
8516 if (IsUsingT32()) {
8517 // POP{<c>}{<q>} <single_register_list> ; T4
8518 // Alias of: LDR{<c>}{<q>} <Rt>, [SP], #4 ; T4
8519 if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond) ||
8520 AllowUnpredictable())) {
8521 EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
8522 AdvanceIT();
8523 return;
8524 }
8525 } else {
8526 // POP{<c>}{<q>} <single_register_list> ; A1
8527 // Alias of: LDR{<c>}{<q>} <Rt>, [SP], #4 ; T1
8528 if (cond.IsNotNever()) {
8529 EmitA32(0x049d0004U | (cond.GetCondition() << 28) |
8530 (rt.GetCode() << 12));
8531 return;
8532 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008533 }
8534 }
8535 Delegate(kPop, &Assembler::pop, cond, size, rt);
8536}
8537
8538void Assembler::push(Condition cond,
8539 EncodingSize size,
8540 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008541 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008542 CheckIT(cond);
Peter Collingbourne920189b2021-01-22 17:42:36 -08008543 if (!registers.IsEmpty() || AllowUnpredictable()) {
8544 if (IsUsingT32()) {
8545 // PUSH{<c>}{<q>} <registers> ; T1
8546 if (!size.IsWide() && registers.IsR0toR7orLR()) {
8547 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
8548 GetRegisterListEncoding(registers, 0, 8));
8549 AdvanceIT();
8550 return;
8551 }
8552 // PUSH{<c>}{<q>} <registers> ; T1
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008553 // Alias of: STMDB SP!, <registers> ; T1
8554 if (!size.IsNarrow() && !registers.Includes(pc) &&
8555 ((!registers.Includes(sp) && (registers.GetCount() > 1)) ||
8556 AllowUnpredictable())) {
8557 EmitT32_32(0xe92d0000U | GetRegisterListEncoding(registers, 0, 15));
Peter Collingbourne920189b2021-01-22 17:42:36 -08008558 AdvanceIT();
8559 return;
8560 }
8561 } else {
8562 // PUSH{<c>}{<q>} <registers> ; A1
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008563 // Alias of: STMDB SP!, <registers> ; A1
8564 if (cond.IsNotNever() &&
8565 // For A32, sp can appear in the list, but stores an UNKNOWN value if
8566 // it is not the lowest-valued register.
8567 (!registers.Includes(sp) ||
8568 registers.GetFirstAvailableRegister().IsSP() ||
8569 AllowUnpredictable())) {
Peter Collingbourne920189b2021-01-22 17:42:36 -08008570 EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
8571 GetRegisterListEncoding(registers, 0, 16));
8572 return;
8573 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008574 }
8575 }
8576 Delegate(kPush, &Assembler::push, cond, size, registers);
8577}
8578
8579void Assembler::push(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008580 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008581 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008582 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008583 // PUSH{<c>}{<q>} <single_register_list> ; T4
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008584 // Alias of: STR{<c>}{<q>} <Rt>, [SP, #4]! ; T4
8585 if (!size.IsNarrow() &&
8586 ((!rt.IsPC() && !rt.IsSP()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008587 EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
8588 AdvanceIT();
8589 return;
8590 }
8591 } else {
8592 // PUSH{<c>}{<q>} <single_register_list> ; A1
Jacob Bramley5dc3c762021-02-08 14:39:30 +00008593 // Alias of: STR{<c>}{<q>} <Rt>, [SP, #4]! ; A1
8594 if (cond.IsNotNever() && (!rt.IsSP() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008595 EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8596 return;
8597 }
8598 }
8599 Delegate(kPush, &Assembler::push, cond, size, rt);
8600}
8601
8602void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008603 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008604 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008605 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008606 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008607 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8608 EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
8609 (rn.GetCode() << 16));
8610 AdvanceIT();
8611 return;
8612 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008613 } else {
8614 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008615 if (cond.IsNotNever() &&
8616 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008617 EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8618 rm.GetCode() | (rn.GetCode() << 16));
8619 return;
8620 }
8621 }
8622 Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
8623}
8624
8625void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008626 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008627 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008628 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008629 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008630 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8631 EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8632 rm.GetCode());
8633 AdvanceIT();
8634 return;
8635 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008636 } else {
8637 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008638 if (cond.IsNotNever() &&
8639 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008640 EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8641 (rn.GetCode() << 16) | rm.GetCode());
8642 return;
8643 }
8644 }
8645 Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
8646}
8647
8648void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008649 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008650 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008652 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008653 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8654 EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8655 rm.GetCode());
8656 AdvanceIT();
8657 return;
8658 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008659 } else {
8660 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008661 if (cond.IsNotNever() &&
8662 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008663 EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8664 (rn.GetCode() << 16) | rm.GetCode());
8665 return;
8666 }
8667 }
8668 Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
8669}
8670
8671void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008672 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008673 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008674 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008675 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008676 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8677 EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8678 rm.GetCode());
8679 AdvanceIT();
8680 return;
8681 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008682 } else {
8683 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008684 if (cond.IsNotNever() &&
8685 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008686 EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8687 (rn.GetCode() << 16) | rm.GetCode());
8688 return;
8689 }
8690 }
8691 Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
8692}
8693
8694void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008695 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008696 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008697 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008698 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008699 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8700 EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
8701 (rn.GetCode() << 16));
8702 AdvanceIT();
8703 return;
8704 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008705 } else {
8706 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008707 if (cond.IsNotNever() &&
8708 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008709 EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8710 rm.GetCode() | (rn.GetCode() << 16));
8711 return;
8712 }
8713 }
8714 Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
8715}
8716
8717void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008718 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008719 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008720 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008721 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008722 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8723 EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8724 (rn.GetCode() << 16));
8725 AdvanceIT();
8726 return;
8727 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008728 } else {
8729 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008730 if (cond.IsNotNever() &&
8731 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008732 EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8733 rm.GetCode() | (rn.GetCode() << 16));
8734 return;
8735 }
8736 }
8737 Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
8738}
8739
8740void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008741 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008742 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008743 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008744 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008745 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8746 EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8747 rm.GetCode());
8748 AdvanceIT();
8749 return;
8750 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008751 } else {
8752 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008753 if (cond.IsNotNever() &&
8754 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008755 EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8756 (rn.GetCode() << 16) | rm.GetCode());
8757 return;
8758 }
8759 }
8760 Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
8761}
8762
8763void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008764 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008765 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008766 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008767 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008768 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8769 EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8770 (rn.GetCode() << 16));
8771 AdvanceIT();
8772 return;
8773 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008774 } else {
8775 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008776 if (cond.IsNotNever() &&
8777 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008778 EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8779 rm.GetCode() | (rn.GetCode() << 16));
8780 return;
8781 }
8782 }
8783 Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8784}
8785
8786void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008787 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008788 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008789 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008790 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008791 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8792 EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8793 rm.GetCode());
8794 AdvanceIT();
8795 return;
8796 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008797 } else {
8798 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008799 if (cond.IsNotNever() &&
8800 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008801 EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8802 (rn.GetCode() << 16) | rm.GetCode());
8803 return;
8804 }
8805 }
8806 Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8807}
8808
8809void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008810 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008811 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008812 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008813 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008814 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8815 EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8816 rm.GetCode());
8817 AdvanceIT();
8818 return;
8819 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008820 } else {
8821 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008822 if (cond.IsNotNever() &&
8823 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008824 EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8825 (rn.GetCode() << 16) | rm.GetCode());
8826 return;
8827 }
8828 }
8829 Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8830}
8831
8832void Assembler::rbit(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008833 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008834 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008835 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008836 // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008837 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8838 EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8839 (rm.GetCode() << 16));
8840 AdvanceIT();
8841 return;
8842 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008843 } else {
8844 // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008845 if (cond.IsNotNever() &&
8846 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008847 EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8848 rm.GetCode());
8849 return;
8850 }
8851 }
8852 Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8853}
8854
8855void Assembler::rev(Condition cond,
8856 EncodingSize size,
8857 Register rd,
8858 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008859 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008860 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008861 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008862 // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8863 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8864 EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8865 AdvanceIT();
8866 return;
8867 }
8868 // REV{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008869 if (!size.IsNarrow() &&
8870 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008871 EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8872 (rm.GetCode() << 16));
8873 AdvanceIT();
8874 return;
8875 }
8876 } else {
8877 // REV{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008878 if (cond.IsNotNever() &&
8879 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008880 EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8881 rm.GetCode());
8882 return;
8883 }
8884 }
8885 Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8886}
8887
8888void Assembler::rev16(Condition cond,
8889 EncodingSize size,
8890 Register rd,
8891 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008892 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008893 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008894 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008895 // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8896 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8897 EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8898 AdvanceIT();
8899 return;
8900 }
8901 // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008902 if (!size.IsNarrow() &&
8903 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008904 EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8905 (rm.GetCode() << 16));
8906 AdvanceIT();
8907 return;
8908 }
8909 } else {
8910 // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008911 if (cond.IsNotNever() &&
8912 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008913 EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8914 rm.GetCode());
8915 return;
8916 }
8917 }
8918 Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8919}
8920
8921void Assembler::revsh(Condition cond,
8922 EncodingSize size,
8923 Register rd,
8924 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008925 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008926 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008927 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008928 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8929 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8930 EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8931 AdvanceIT();
8932 return;
8933 }
8934 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008935 if (!size.IsNarrow() &&
8936 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008937 EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8938 (rm.GetCode() << 16));
8939 AdvanceIT();
8940 return;
8941 }
8942 } else {
8943 // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008944 if (cond.IsNotNever() &&
8945 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008946 EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8947 rm.GetCode());
8948 return;
8949 }
8950 }
8951 Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8952}
8953
8954void Assembler::ror(Condition cond,
8955 EncodingSize size,
8956 Register rd,
8957 Register rm,
8958 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008959 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008960 CheckIT(cond);
8961 if (operand.IsImmediate()) {
8962 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008963 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008964 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008965 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8966 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008967 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8968 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8969 AdvanceIT();
8970 return;
8971 }
8972 } else {
8973 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8974 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8975 EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8976 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8977 return;
8978 }
8979 }
8980 }
8981 if (operand.IsPlainRegister()) {
8982 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008983 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008984 // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8985 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8986 rs.IsLow()) {
8987 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8988 AdvanceIT();
8989 return;
8990 }
8991 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008992 if (!size.IsNarrow() &&
8993 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008994 EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8995 rs.GetCode());
8996 AdvanceIT();
8997 return;
8998 }
8999 } else {
9000 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009001 if (cond.IsNotNever() &&
9002 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009003 EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
9004 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9005 return;
9006 }
9007 }
9008 }
9009 Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
9010}
9011
9012void Assembler::rors(Condition cond,
9013 EncodingSize size,
9014 Register rd,
9015 Register rm,
9016 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009017 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009018 CheckIT(cond);
9019 if (operand.IsImmediate()) {
9020 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009021 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009022 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009023 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
9024 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009025 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
9026 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
9027 AdvanceIT();
9028 return;
9029 }
9030 } else {
9031 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
9032 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
9033 EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
9034 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
9035 return;
9036 }
9037 }
9038 }
9039 if (operand.IsPlainRegister()) {
9040 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009041 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009042 // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
9043 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
9044 rs.IsLow()) {
9045 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
9046 AdvanceIT();
9047 return;
9048 }
9049 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009050 if (!size.IsNarrow() &&
9051 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009052 EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
9053 rs.GetCode());
9054 AdvanceIT();
9055 return;
9056 }
9057 } else {
9058 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009059 if (cond.IsNotNever() &&
9060 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009061 EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
9062 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9063 return;
9064 }
9065 }
9066 }
9067 Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
9068}
9069
9070void Assembler::rrx(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009071 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009072 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009074 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009075 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9076 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
9077 AdvanceIT();
9078 return;
9079 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009080 } else {
9081 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
9082 if (cond.IsNotNever()) {
9083 EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9084 rm.GetCode());
9085 return;
9086 }
9087 }
9088 Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
9089}
9090
9091void Assembler::rrxs(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009092 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009093 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009094 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009095 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009096 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9097 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
9098 AdvanceIT();
9099 return;
9100 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009101 } else {
9102 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
9103 if (cond.IsNotNever()) {
9104 EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9105 rm.GetCode());
9106 return;
9107 }
9108 }
9109 Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
9110}
9111
9112void Assembler::rsb(Condition cond,
9113 EncodingSize size,
9114 Register rd,
9115 Register rn,
9116 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009117 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009118 CheckIT(cond);
9119 if (operand.IsImmediate()) {
9120 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009121 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009122 ImmediateT32 immediate_t32(imm);
9123 // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
9124 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9125 (imm == 0)) {
9126 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9127 AdvanceIT();
9128 return;
9129 }
9130 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009131 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9132 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009133 EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9134 (immediate_t32.GetEncodingValue() & 0xff) |
9135 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9136 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9137 AdvanceIT();
9138 return;
9139 }
9140 } else {
9141 ImmediateA32 immediate_a32(imm);
9142 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9143 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9144 EmitA32(0x02600000U | (cond.GetCondition() << 28) |
9145 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9146 immediate_a32.GetEncodingValue());
9147 return;
9148 }
9149 }
9150 }
9151 if (operand.IsImmediateShiftedRegister()) {
9152 Register rm = operand.GetBaseRegister();
9153 Shift shift = operand.GetShift();
9154 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009155 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009156 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009157 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9158 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009159 uint32_t amount_ = amount % 32;
9160 EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9161 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9162 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9163 AdvanceIT();
9164 return;
9165 }
9166 } else {
9167 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9168 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9169 uint32_t amount_ = amount % 32;
9170 EmitA32(0x00600000U | (cond.GetCondition() << 28) |
9171 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9172 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9173 return;
9174 }
9175 }
9176 }
9177 if (operand.IsRegisterShiftedRegister()) {
9178 Register rm = operand.GetBaseRegister();
9179 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009180 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009181 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009182 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009183 if (cond.IsNotNever() &&
9184 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9185 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009186 EmitA32(0x00600010U | (cond.GetCondition() << 28) |
9187 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009188 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009189 return;
9190 }
9191 }
9192 }
9193 Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
9194}
9195
9196void Assembler::rsbs(Condition cond,
9197 EncodingSize size,
9198 Register rd,
9199 Register rn,
9200 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009201 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009202 CheckIT(cond);
9203 if (operand.IsImmediate()) {
9204 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009205 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009206 ImmediateT32 immediate_t32(imm);
9207 // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
9208 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9209 (imm == 0)) {
9210 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9211 AdvanceIT();
9212 return;
9213 }
9214 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009215 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9216 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009217 EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9218 (immediate_t32.GetEncodingValue() & 0xff) |
9219 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9220 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9221 AdvanceIT();
9222 return;
9223 }
9224 } else {
9225 ImmediateA32 immediate_a32(imm);
9226 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9227 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9228 EmitA32(0x02700000U | (cond.GetCondition() << 28) |
9229 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9230 immediate_a32.GetEncodingValue());
9231 return;
9232 }
9233 }
9234 }
9235 if (operand.IsImmediateShiftedRegister()) {
9236 Register rm = operand.GetBaseRegister();
9237 Shift shift = operand.GetShift();
9238 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009239 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009240 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009241 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9242 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009243 uint32_t amount_ = amount % 32;
9244 EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9245 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9246 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9247 AdvanceIT();
9248 return;
9249 }
9250 } else {
9251 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9252 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9253 uint32_t amount_ = amount % 32;
9254 EmitA32(0x00700000U | (cond.GetCondition() << 28) |
9255 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9256 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9257 return;
9258 }
9259 }
9260 }
9261 if (operand.IsRegisterShiftedRegister()) {
9262 Register rm = operand.GetBaseRegister();
9263 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009264 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009265 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009266 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009267 if (cond.IsNotNever() &&
9268 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9269 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009270 EmitA32(0x00700010U | (cond.GetCondition() << 28) |
9271 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009272 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009273 return;
9274 }
9275 }
9276 }
9277 Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
9278}
9279
9280void Assembler::rsc(Condition cond,
9281 Register rd,
9282 Register rn,
9283 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009284 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009285 CheckIT(cond);
9286 if (operand.IsImmediate()) {
9287 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009288 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009289 ImmediateA32 immediate_a32(imm);
9290 // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9291 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9292 EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
9293 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9294 immediate_a32.GetEncodingValue());
9295 return;
9296 }
9297 }
9298 }
9299 if (operand.IsImmediateShiftedRegister()) {
9300 Register rm = operand.GetBaseRegister();
9301 Shift shift = operand.GetShift();
9302 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009303 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009304 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9305 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9306 uint32_t amount_ = amount % 32;
9307 EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
9308 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9309 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9310 return;
9311 }
9312 }
9313 }
9314 if (operand.IsRegisterShiftedRegister()) {
9315 Register rm = operand.GetBaseRegister();
9316 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009317 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009318 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009319 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009320 if (cond.IsNotNever() &&
9321 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9322 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009323 EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
9324 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009325 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009326 return;
9327 }
9328 }
9329 }
9330 Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
9331}
9332
9333void Assembler::rscs(Condition cond,
9334 Register rd,
9335 Register rn,
9336 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009337 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009338 CheckIT(cond);
9339 if (operand.IsImmediate()) {
9340 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009341 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009342 ImmediateA32 immediate_a32(imm);
9343 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9344 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9345 EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
9346 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9347 immediate_a32.GetEncodingValue());
9348 return;
9349 }
9350 }
9351 }
9352 if (operand.IsImmediateShiftedRegister()) {
9353 Register rm = operand.GetBaseRegister();
9354 Shift shift = operand.GetShift();
9355 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009356 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009357 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9358 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9359 uint32_t amount_ = amount % 32;
9360 EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
9361 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9362 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9363 return;
9364 }
9365 }
9366 }
9367 if (operand.IsRegisterShiftedRegister()) {
9368 Register rm = operand.GetBaseRegister();
9369 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009370 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009371 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009372 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009373 if (cond.IsNotNever() &&
9374 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9375 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009376 EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
9377 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009378 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009379 return;
9380 }
9381 }
9382 }
9383 Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
9384}
9385
9386void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009387 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009388 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009389 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009390 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009391 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9392 EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9393 rm.GetCode());
9394 AdvanceIT();
9395 return;
9396 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009397 } else {
9398 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009399 if (cond.IsNotNever() &&
9400 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009401 EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9402 (rn.GetCode() << 16) | rm.GetCode());
9403 return;
9404 }
9405 }
9406 Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
9407}
9408
9409void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009410 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009411 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009412 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009413 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009414 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9415 EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9416 rm.GetCode());
9417 AdvanceIT();
9418 return;
9419 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009420 } else {
9421 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009422 if (cond.IsNotNever() &&
9423 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009424 EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9425 (rn.GetCode() << 16) | rm.GetCode());
9426 return;
9427 }
9428 }
9429 Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
9430}
9431
9432void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009433 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009434 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009435 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009436 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009437 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9438 EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9439 rm.GetCode());
9440 AdvanceIT();
9441 return;
9442 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009443 } else {
9444 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009445 if (cond.IsNotNever() &&
9446 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009447 EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9448 (rn.GetCode() << 16) | rm.GetCode());
9449 return;
9450 }
9451 }
9452 Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
9453}
9454
9455void Assembler::sbc(Condition cond,
9456 EncodingSize size,
9457 Register rd,
9458 Register rn,
9459 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009460 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009461 CheckIT(cond);
9462 if (operand.IsImmediate()) {
9463 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009465 ImmediateT32 immediate_t32(imm);
9466 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009467 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9468 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009469 EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9470 (immediate_t32.GetEncodingValue() & 0xff) |
9471 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9472 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9473 AdvanceIT();
9474 return;
9475 }
9476 } else {
9477 ImmediateA32 immediate_a32(imm);
9478 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9479 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9480 EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
9481 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9482 immediate_a32.GetEncodingValue());
9483 return;
9484 }
9485 }
9486 }
9487 if (operand.IsImmediateShiftedRegister()) {
9488 Register rm = operand.GetBaseRegister();
9489 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009490 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009491 // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9492 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9493 rm.IsLow()) {
9494 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9495 AdvanceIT();
9496 return;
9497 }
9498 }
9499 }
9500 Shift shift = operand.GetShift();
9501 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009502 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009503 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009504 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9505 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009506 uint32_t amount_ = amount % 32;
9507 EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9508 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9509 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9510 AdvanceIT();
9511 return;
9512 }
9513 } else {
9514 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9515 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9516 uint32_t amount_ = amount % 32;
9517 EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
9518 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9519 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9520 return;
9521 }
9522 }
9523 }
9524 if (operand.IsRegisterShiftedRegister()) {
9525 Register rm = operand.GetBaseRegister();
9526 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009527 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009528 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009529 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009530 if (cond.IsNotNever() &&
9531 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9532 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009533 EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
9534 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009535 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009536 return;
9537 }
9538 }
9539 }
9540 Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
9541}
9542
9543void Assembler::sbcs(Condition cond,
9544 EncodingSize size,
9545 Register rd,
9546 Register rn,
9547 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009548 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009549 CheckIT(cond);
9550 if (operand.IsImmediate()) {
9551 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009552 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009553 ImmediateT32 immediate_t32(imm);
9554 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009555 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9556 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009557 EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9558 (immediate_t32.GetEncodingValue() & 0xff) |
9559 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9560 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9561 AdvanceIT();
9562 return;
9563 }
9564 } else {
9565 ImmediateA32 immediate_a32(imm);
9566 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9567 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9568 EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
9569 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9570 immediate_a32.GetEncodingValue());
9571 return;
9572 }
9573 }
9574 }
9575 if (operand.IsImmediateShiftedRegister()) {
9576 Register rm = operand.GetBaseRegister();
9577 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009578 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009579 // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9580 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9581 rm.IsLow()) {
9582 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9583 AdvanceIT();
9584 return;
9585 }
9586 }
9587 }
9588 Shift shift = operand.GetShift();
9589 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009590 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009591 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009592 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9593 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009594 uint32_t amount_ = amount % 32;
9595 EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9596 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9597 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9598 AdvanceIT();
9599 return;
9600 }
9601 } else {
9602 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9603 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9604 uint32_t amount_ = amount % 32;
9605 EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
9606 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9607 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9608 return;
9609 }
9610 }
9611 }
9612 if (operand.IsRegisterShiftedRegister()) {
9613 Register rm = operand.GetBaseRegister();
9614 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009615 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009616 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009617 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009618 if (cond.IsNotNever() &&
9619 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9620 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009621 EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
9622 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009623 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009624 return;
9625 }
9626 }
9627 }
9628 Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
9629}
9630
Vincent Belliard609821f2017-02-08 14:17:25 -08009631void Assembler::sbfx(
9632 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009633 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009634 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08009635 if (IsUsingT32()) {
9636 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
9637 if ((lsb <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00009638 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9639 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08009640 uint32_t widthm1 = width - 1;
9641 EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9642 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
9643 AdvanceIT();
9644 return;
9645 }
9646 } else {
9647 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
9648 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00009649 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9650 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08009651 uint32_t widthm1 = width - 1;
9652 EmitA32(0x07a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9653 rn.GetCode() | (lsb << 7) | (widthm1 << 16));
9654 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01009655 }
9656 }
Vincent Belliard609821f2017-02-08 14:17:25 -08009657 Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009658}
9659
9660void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009661 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009662 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009663 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009664 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009665 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9666 EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9667 rm.GetCode());
9668 AdvanceIT();
9669 return;
9670 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009671 } else {
9672 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009673 if (cond.IsNotNever() &&
9674 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009675 EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9676 rn.GetCode() | (rm.GetCode() << 8));
9677 return;
9678 }
9679 }
9680 Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
9681}
9682
9683void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009684 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009685 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009686 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009687 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009688 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9689 EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9690 rm.GetCode());
9691 AdvanceIT();
9692 return;
9693 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009694 } else {
9695 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009696 if (cond.IsNotNever() &&
9697 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009698 EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9699 (rn.GetCode() << 16) | rm.GetCode());
9700 return;
9701 }
9702 }
9703 Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
9704}
9705
9706void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009707 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009708 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009709 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009710 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009711 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9712 EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9713 rm.GetCode());
9714 AdvanceIT();
9715 return;
9716 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009717 } else {
9718 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009719 if (cond.IsNotNever() &&
9720 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009721 EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9722 (rn.GetCode() << 16) | rm.GetCode());
9723 return;
9724 }
9725 }
9726 Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
9727}
9728
9729void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009730 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009731 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009732 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009733 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009734 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9735 EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9736 rm.GetCode());
9737 AdvanceIT();
9738 return;
9739 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009740 } else {
9741 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009742 if (cond.IsNotNever() &&
9743 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009744 EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9745 (rn.GetCode() << 16) | rm.GetCode());
9746 return;
9747 }
9748 }
9749 Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
9750}
9751
9752void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009753 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009754 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009756 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009757 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9758 EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9759 rm.GetCode());
9760 AdvanceIT();
9761 return;
9762 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009763 } else {
9764 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009765 if (cond.IsNotNever() &&
9766 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009767 EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9768 (rn.GetCode() << 16) | rm.GetCode());
9769 return;
9770 }
9771 }
9772 Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
9773}
9774
9775void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009776 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009777 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009778 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009779 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009780 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9781 EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9782 rm.GetCode());
9783 AdvanceIT();
9784 return;
9785 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009786 } else {
9787 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009788 if (cond.IsNotNever() &&
9789 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009790 EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9791 (rn.GetCode() << 16) | rm.GetCode());
9792 return;
9793 }
9794 }
9795 Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
9796}
9797
9798void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009799 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009800 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009801 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009802 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009803 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9804 EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9805 rm.GetCode());
9806 AdvanceIT();
9807 return;
9808 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009809 } else {
9810 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009811 if (cond.IsNotNever() &&
9812 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009813 EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9814 (rn.GetCode() << 16) | rm.GetCode());
9815 return;
9816 }
9817 }
9818 Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
9819}
9820
9821void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009822 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009823 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009824 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009825 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009826 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9827 EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9828 rm.GetCode());
9829 AdvanceIT();
9830 return;
9831 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009832 } else {
9833 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009834 if (cond.IsNotNever() &&
9835 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009836 EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9837 (rn.GetCode() << 16) | rm.GetCode());
9838 return;
9839 }
9840 }
9841 Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
9842}
9843
9844void Assembler::smlabb(
9845 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009846 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009847 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009848 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009849 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009850 if (!ra.Is(pc) &&
9851 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009852 EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9853 rm.GetCode() | (ra.GetCode() << 12));
9854 AdvanceIT();
9855 return;
9856 }
9857 } else {
9858 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009859 if (cond.IsNotNever() &&
9860 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9861 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009862 EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9863 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9864 return;
9865 }
9866 }
9867 Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9868}
9869
9870void Assembler::smlabt(
9871 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009872 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009873 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009874 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009875 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009876 if (!ra.Is(pc) &&
9877 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009878 EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9879 rm.GetCode() | (ra.GetCode() << 12));
9880 AdvanceIT();
9881 return;
9882 }
9883 } else {
9884 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009885 if (cond.IsNotNever() &&
9886 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9887 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009888 EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9889 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9890 return;
9891 }
9892 }
9893 Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9894}
9895
9896void Assembler::smlad(
9897 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009898 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009899 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009900 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009901 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009902 if (!ra.Is(pc) &&
9903 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009904 EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9905 rm.GetCode() | (ra.GetCode() << 12));
9906 AdvanceIT();
9907 return;
9908 }
9909 } else {
9910 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009911 if (cond.IsNotNever() && !ra.Is(pc) &&
9912 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009913 EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9914 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9915 return;
9916 }
9917 }
9918 Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9919}
9920
9921void Assembler::smladx(
9922 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009923 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009924 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009925 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009926 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009927 if (!ra.Is(pc) &&
9928 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009929 EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9930 rm.GetCode() | (ra.GetCode() << 12));
9931 AdvanceIT();
9932 return;
9933 }
9934 } else {
9935 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009936 if (cond.IsNotNever() && !ra.Is(pc) &&
9937 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009938 EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9939 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9940 return;
9941 }
9942 }
9943 Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9944}
9945
9946void Assembler::smlal(
9947 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009948 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009949 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009950 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009951 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009952 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9953 AllowUnpredictable())) {
9954 EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9955 (rn.GetCode() << 16) | rm.GetCode());
9956 AdvanceIT();
9957 return;
9958 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009959 } else {
9960 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009961 if (cond.IsNotNever() &&
9962 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9963 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009964 EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9965 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9966 (rm.GetCode() << 8));
9967 return;
9968 }
9969 }
9970 Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9971}
9972
9973void Assembler::smlalbb(
9974 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009975 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009976 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009977 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009978 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009979 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9980 AllowUnpredictable())) {
9981 EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9982 (rn.GetCode() << 16) | rm.GetCode());
9983 AdvanceIT();
9984 return;
9985 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009986 } else {
9987 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009988 if (cond.IsNotNever() &&
9989 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9990 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009991 EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9992 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9993 (rm.GetCode() << 8));
9994 return;
9995 }
9996 }
9997 Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9998}
9999
10000void Assembler::smlalbt(
10001 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010002 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010003 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010004 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010005 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010006 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10007 AllowUnpredictable())) {
10008 EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10009 (rn.GetCode() << 16) | rm.GetCode());
10010 AdvanceIT();
10011 return;
10012 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010013 } else {
10014 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010015 if (cond.IsNotNever() &&
10016 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10017 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010018 EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
10019 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10020 (rm.GetCode() << 8));
10021 return;
10022 }
10023 }
10024 Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
10025}
10026
10027void Assembler::smlald(
10028 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010029 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010030 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010031 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010032 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010033 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10034 AllowUnpredictable())) {
10035 EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10036 (rn.GetCode() << 16) | rm.GetCode());
10037 AdvanceIT();
10038 return;
10039 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010040 } else {
10041 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010042 if (cond.IsNotNever() &&
10043 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10044 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010045 EmitA32(0x07400010U | (cond.GetCondition() << 28) |
10046 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10047 (rm.GetCode() << 8));
10048 return;
10049 }
10050 }
10051 Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
10052}
10053
10054void Assembler::smlaldx(
10055 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010056 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010057 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010058 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010059 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010060 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10061 AllowUnpredictable())) {
10062 EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10063 (rn.GetCode() << 16) | rm.GetCode());
10064 AdvanceIT();
10065 return;
10066 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010067 } else {
10068 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010069 if (cond.IsNotNever() &&
10070 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10071 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010072 EmitA32(0x07400030U | (cond.GetCondition() << 28) |
10073 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10074 (rm.GetCode() << 8));
10075 return;
10076 }
10077 }
10078 Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
10079}
10080
10081void Assembler::smlals(
10082 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010083 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010084 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010085 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010086 // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010087 if (cond.IsNotNever() &&
10088 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10089 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010090 EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
10091 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10092 (rm.GetCode() << 8));
10093 return;
10094 }
10095 }
10096 Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
10097}
10098
10099void Assembler::smlaltb(
10100 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010101 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010102 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010103 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010104 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010105 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10106 AllowUnpredictable())) {
10107 EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10108 (rn.GetCode() << 16) | rm.GetCode());
10109 AdvanceIT();
10110 return;
10111 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010112 } else {
10113 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010114 if (cond.IsNotNever() &&
10115 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10116 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010117 EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
10118 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10119 (rm.GetCode() << 8));
10120 return;
10121 }
10122 }
10123 Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
10124}
10125
10126void Assembler::smlaltt(
10127 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010128 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010129 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010130 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010131 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010132 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10133 AllowUnpredictable())) {
10134 EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10135 (rn.GetCode() << 16) | rm.GetCode());
10136 AdvanceIT();
10137 return;
10138 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010139 } else {
10140 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010141 if (cond.IsNotNever() &&
10142 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10143 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010144 EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
10145 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10146 (rm.GetCode() << 8));
10147 return;
10148 }
10149 }
10150 Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
10151}
10152
10153void Assembler::smlatb(
10154 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010155 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010156 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010157 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010158 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010159 if (!ra.Is(pc) &&
10160 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010161 EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10162 rm.GetCode() | (ra.GetCode() << 12));
10163 AdvanceIT();
10164 return;
10165 }
10166 } else {
10167 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010168 if (cond.IsNotNever() &&
10169 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10170 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010171 EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10172 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10173 return;
10174 }
10175 }
10176 Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
10177}
10178
10179void Assembler::smlatt(
10180 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010181 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010182 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010183 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010184 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010185 if (!ra.Is(pc) &&
10186 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010187 EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10188 rm.GetCode() | (ra.GetCode() << 12));
10189 AdvanceIT();
10190 return;
10191 }
10192 } else {
10193 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010194 if (cond.IsNotNever() &&
10195 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10196 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010197 EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10198 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10199 return;
10200 }
10201 }
10202 Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
10203}
10204
10205void Assembler::smlawb(
10206 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010207 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010208 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010209 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010210 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010211 if (!ra.Is(pc) &&
10212 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010213 EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10214 rm.GetCode() | (ra.GetCode() << 12));
10215 AdvanceIT();
10216 return;
10217 }
10218 } else {
10219 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010220 if (cond.IsNotNever() &&
10221 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10222 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010223 EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10224 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10225 return;
10226 }
10227 }
10228 Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
10229}
10230
10231void Assembler::smlawt(
10232 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010233 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010234 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010235 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010236 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010237 if (!ra.Is(pc) &&
10238 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010239 EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10240 rm.GetCode() | (ra.GetCode() << 12));
10241 AdvanceIT();
10242 return;
10243 }
10244 } else {
10245 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010246 if (cond.IsNotNever() &&
10247 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10248 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010249 EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10250 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10251 return;
10252 }
10253 }
10254 Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
10255}
10256
10257void Assembler::smlsd(
10258 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010259 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010260 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010261 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010262 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010263 if (!ra.Is(pc) &&
10264 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010265 EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10266 rm.GetCode() | (ra.GetCode() << 12));
10267 AdvanceIT();
10268 return;
10269 }
10270 } else {
10271 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010272 if (cond.IsNotNever() && !ra.Is(pc) &&
10273 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010274 EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10275 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10276 return;
10277 }
10278 }
10279 Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
10280}
10281
10282void Assembler::smlsdx(
10283 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010284 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010285 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010286 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010287 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010288 if (!ra.Is(pc) &&
10289 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010290 EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10291 rm.GetCode() | (ra.GetCode() << 12));
10292 AdvanceIT();
10293 return;
10294 }
10295 } else {
10296 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010297 if (cond.IsNotNever() && !ra.Is(pc) &&
10298 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010299 EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10300 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10301 return;
10302 }
10303 }
10304 Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
10305}
10306
10307void Assembler::smlsld(
10308 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010309 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010310 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010311 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010312 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010313 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10314 AllowUnpredictable())) {
10315 EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10316 (rn.GetCode() << 16) | rm.GetCode());
10317 AdvanceIT();
10318 return;
10319 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010320 } else {
10321 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010322 if (cond.IsNotNever() &&
10323 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10324 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010325 EmitA32(0x07400050U | (cond.GetCondition() << 28) |
10326 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10327 (rm.GetCode() << 8));
10328 return;
10329 }
10330 }
10331 Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
10332}
10333
10334void Assembler::smlsldx(
10335 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010336 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010337 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010338 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010339 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010340 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10341 AllowUnpredictable())) {
10342 EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10343 (rn.GetCode() << 16) | rm.GetCode());
10344 AdvanceIT();
10345 return;
10346 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010347 } else {
10348 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010349 if (cond.IsNotNever() &&
10350 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10351 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010352 EmitA32(0x07400070U | (cond.GetCondition() << 28) |
10353 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10354 (rm.GetCode() << 8));
10355 return;
10356 }
10357 }
10358 Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
10359}
10360
10361void Assembler::smmla(
10362 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010363 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010364 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010365 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010366 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010367 if (!ra.Is(pc) &&
10368 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010369 EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10370 rm.GetCode() | (ra.GetCode() << 12));
10371 AdvanceIT();
10372 return;
10373 }
10374 } else {
10375 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010376 if (cond.IsNotNever() && !ra.Is(pc) &&
10377 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010378 EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10379 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10380 return;
10381 }
10382 }
10383 Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
10384}
10385
10386void Assembler::smmlar(
10387 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010388 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010389 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010390 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010391 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010392 if (!ra.Is(pc) &&
10393 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010394 EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10395 rm.GetCode() | (ra.GetCode() << 12));
10396 AdvanceIT();
10397 return;
10398 }
10399 } else {
10400 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010401 if (cond.IsNotNever() && !ra.Is(pc) &&
10402 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010403 EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10404 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10405 return;
10406 }
10407 }
10408 Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
10409}
10410
10411void Assembler::smmls(
10412 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010413 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010414 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010415 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010416 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010417 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10418 AllowUnpredictable())) {
10419 EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10420 rm.GetCode() | (ra.GetCode() << 12));
10421 AdvanceIT();
10422 return;
10423 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010424 } else {
10425 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010426 if (cond.IsNotNever() &&
10427 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10428 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010429 EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10430 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10431 return;
10432 }
10433 }
10434 Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
10435}
10436
10437void Assembler::smmlsr(
10438 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010439 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010440 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010441 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010442 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010443 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10444 AllowUnpredictable())) {
10445 EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10446 rm.GetCode() | (ra.GetCode() << 12));
10447 AdvanceIT();
10448 return;
10449 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010450 } else {
10451 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010452 if (cond.IsNotNever() &&
10453 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10454 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010455 EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10456 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10457 return;
10458 }
10459 }
10460 Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
10461}
10462
10463void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010464 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010465 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010466 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010467 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010468 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10469 EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10470 rm.GetCode());
10471 AdvanceIT();
10472 return;
10473 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010474 } else {
10475 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010476 if (cond.IsNotNever() &&
10477 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010478 EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10479 rn.GetCode() | (rm.GetCode() << 8));
10480 return;
10481 }
10482 }
10483 Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
10484}
10485
10486void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010487 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010488 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010489 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010490 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010491 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10492 EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10493 rm.GetCode());
10494 AdvanceIT();
10495 return;
10496 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010497 } else {
10498 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010499 if (cond.IsNotNever() &&
10500 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010501 EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10502 rn.GetCode() | (rm.GetCode() << 8));
10503 return;
10504 }
10505 }
10506 Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
10507}
10508
10509void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010510 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010511 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010512 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010513 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010514 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10515 EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10516 rm.GetCode());
10517 AdvanceIT();
10518 return;
10519 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010520 } else {
10521 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010522 if (cond.IsNotNever() &&
10523 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010524 EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10525 rn.GetCode() | (rm.GetCode() << 8));
10526 return;
10527 }
10528 }
10529 Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
10530}
10531
10532void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010534 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010536 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010537 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10538 EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10539 rm.GetCode());
10540 AdvanceIT();
10541 return;
10542 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010543 } else {
10544 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010545 if (cond.IsNotNever() &&
10546 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010547 EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10548 rn.GetCode() | (rm.GetCode() << 8));
10549 return;
10550 }
10551 }
10552 Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
10553}
10554
10555void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010556 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010557 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010558 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010559 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010560 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10561 EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10562 rm.GetCode());
10563 AdvanceIT();
10564 return;
10565 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010566 } else {
10567 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010568 if (cond.IsNotNever() &&
10569 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010570 EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10571 rn.GetCode() | (rm.GetCode() << 8));
10572 return;
10573 }
10574 }
10575 Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
10576}
10577
10578void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010579 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010580 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010581 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010582 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010583 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10584 EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10585 rm.GetCode());
10586 AdvanceIT();
10587 return;
10588 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010589 } else {
10590 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010591 if (cond.IsNotNever() &&
10592 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010593 EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10594 rn.GetCode() | (rm.GetCode() << 8));
10595 return;
10596 }
10597 }
10598 Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
10599}
10600
10601void Assembler::smull(
10602 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010603 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010604 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010605 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010606 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010607 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10608 AllowUnpredictable())) {
10609 EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10610 (rn.GetCode() << 16) | rm.GetCode());
10611 AdvanceIT();
10612 return;
10613 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010614 } else {
10615 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010616 if (cond.IsNotNever() &&
10617 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10618 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010619 EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
10620 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10621 (rm.GetCode() << 8));
10622 return;
10623 }
10624 }
10625 Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
10626}
10627
10628void Assembler::smulls(
10629 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010630 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010631 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010632 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010633 // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010634 if (cond.IsNotNever() &&
10635 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10636 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010637 EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
10638 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10639 (rm.GetCode() << 8));
10640 return;
10641 }
10642 }
10643 Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
10644}
10645
10646void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010647 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010648 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010649 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010650 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010651 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10652 EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10653 rm.GetCode());
10654 AdvanceIT();
10655 return;
10656 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010657 } else {
10658 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010659 if (cond.IsNotNever() &&
10660 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010661 EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10662 rn.GetCode() | (rm.GetCode() << 8));
10663 return;
10664 }
10665 }
10666 Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
10667}
10668
10669void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010670 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010671 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010673 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010674 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10675 EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10676 rm.GetCode());
10677 AdvanceIT();
10678 return;
10679 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010680 } else {
10681 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010682 if (cond.IsNotNever() &&
10683 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010684 EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10685 rn.GetCode() | (rm.GetCode() << 8));
10686 return;
10687 }
10688 }
10689 Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
10690}
10691
10692void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010693 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010694 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010695 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010696 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010697 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10698 EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10699 rm.GetCode());
10700 AdvanceIT();
10701 return;
10702 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010703 } else {
10704 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010705 if (cond.IsNotNever() &&
10706 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010707 EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10708 rn.GetCode() | (rm.GetCode() << 8));
10709 return;
10710 }
10711 }
10712 Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
10713}
10714
10715void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010716 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010717 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010718 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010719 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010720 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10721 EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10722 rm.GetCode());
10723 AdvanceIT();
10724 return;
10725 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010726 } else {
10727 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010728 if (cond.IsNotNever() &&
10729 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010730 EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10731 rn.GetCode() | (rm.GetCode() << 8));
10732 return;
10733 }
10734 }
10735 Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
10736}
10737
10738void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010739 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010740 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010741 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010742 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010743 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10744 EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10745 rm.GetCode());
10746 AdvanceIT();
10747 return;
10748 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010749 } else {
10750 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010751 if (cond.IsNotNever() &&
10752 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010753 EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10754 rn.GetCode() | (rm.GetCode() << 8));
10755 return;
10756 }
10757 }
10758 Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
10759}
10760
10761void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010762 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010763 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010764 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010765 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010766 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10767 EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10768 rm.GetCode());
10769 AdvanceIT();
10770 return;
10771 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010772 } else {
10773 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010774 if (cond.IsNotNever() &&
10775 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010776 EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10777 rn.GetCode() | (rm.GetCode() << 8));
10778 return;
10779 }
10780 }
10781 Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
10782}
10783
10784void Assembler::ssat(Condition cond,
10785 Register rd,
10786 uint32_t imm,
10787 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010788 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010789 CheckIT(cond);
10790 if (operand.IsImmediateShiftedRegister()) {
10791 Register rn = operand.GetBaseRegister();
10792 Shift shift = operand.GetShift();
10793 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010794 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010795 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
10796 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010797 (amount <= 31) &&
10798 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010799 uint32_t imm_ = imm - 1;
10800 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10801 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10802 ((amount & 0x1c) << 10));
10803 AdvanceIT();
10804 return;
10805 }
10806 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010807 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10808 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010809 uint32_t imm_ = imm - 1;
10810 EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
10811 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10812 ((amount & 0x1c) << 10));
10813 AdvanceIT();
10814 return;
10815 }
10816 } else {
10817 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
10818 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010819 (amount <= 32) && cond.IsNotNever() &&
10820 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010821 uint32_t imm_ = imm - 1;
10822 uint32_t amount_ = amount % 32;
10823 EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
10824 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10825 (amount_ << 7));
10826 return;
10827 }
10828 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
10829 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010830 cond.IsNotNever() &&
10831 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010832 uint32_t imm_ = imm - 1;
10833 EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
10834 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10835 (amount << 7));
10836 return;
10837 }
10838 }
10839 }
10840 Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
10841}
10842
10843void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010844 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010845 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010846 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010847 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010848 if ((imm >= 1) && (imm <= 16) &&
10849 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010850 uint32_t imm_ = imm - 1;
10851 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10852 (rn.GetCode() << 16));
10853 AdvanceIT();
10854 return;
10855 }
10856 } else {
10857 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010858 if ((imm >= 1) && (imm <= 16) && cond.IsNotNever() &&
10859 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010860 uint32_t imm_ = imm - 1;
10861 EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10862 (imm_ << 16) | rn.GetCode());
10863 return;
10864 }
10865 }
10866 Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
10867}
10868
10869void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010870 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010871 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010872 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010873 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010874 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10875 EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10876 rm.GetCode());
10877 AdvanceIT();
10878 return;
10879 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010880 } else {
10881 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010882 if (cond.IsNotNever() &&
10883 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010884 EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10885 (rn.GetCode() << 16) | rm.GetCode());
10886 return;
10887 }
10888 }
10889 Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
10890}
10891
10892void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010893 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010894 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010896 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010897 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10898 EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10899 rm.GetCode());
10900 AdvanceIT();
10901 return;
10902 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010903 } else {
10904 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010905 if (cond.IsNotNever() &&
10906 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010907 EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10908 (rn.GetCode() << 16) | rm.GetCode());
10909 return;
10910 }
10911 }
10912 Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
10913}
10914
10915void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010916 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010917 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010918 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010919 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010920 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10921 EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10922 rm.GetCode());
10923 AdvanceIT();
10924 return;
10925 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010926 } else {
10927 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010928 if (cond.IsNotNever() &&
10929 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010930 EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10931 (rn.GetCode() << 16) | rm.GetCode());
10932 return;
10933 }
10934 }
10935 Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
10936}
10937
10938void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010939 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010940 CheckIT(cond);
10941 if (operand.IsImmediateZero()) {
10942 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010944 // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010945 if (operand.IsOffset() &&
10946 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010947 EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10948 AdvanceIT();
10949 return;
10950 }
10951 } else {
10952 // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010953 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010954 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010955 EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10956 (rn.GetCode() << 16));
10957 return;
10958 }
10959 }
10960 }
10961 Delegate(kStl, &Assembler::stl, cond, rt, operand);
10962}
10963
10964void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010965 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010966 CheckIT(cond);
10967 if (operand.IsImmediateZero()) {
10968 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010969 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010970 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010971 if (operand.IsOffset() &&
10972 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010973 EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10974 AdvanceIT();
10975 return;
10976 }
10977 } else {
10978 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010979 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010980 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010981 EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10982 (rn.GetCode() << 16));
10983 return;
10984 }
10985 }
10986 }
10987 Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
10988}
10989
10990void Assembler::stlex(Condition cond,
10991 Register rd,
10992 Register rt,
10993 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010994 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010995 CheckIT(cond);
10996 if (operand.IsImmediateZero()) {
10997 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010998 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010999 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011000 if (operand.IsOffset() &&
11001 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011002 EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
11003 (rn.GetCode() << 16));
11004 AdvanceIT();
11005 return;
11006 }
11007 } else {
11008 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011009 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011010 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011011 EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
11012 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11013 return;
11014 }
11015 }
11016 }
11017 Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
11018}
11019
11020void Assembler::stlexb(Condition cond,
11021 Register rd,
11022 Register rt,
11023 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011024 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011025 CheckIT(cond);
11026 if (operand.IsImmediateZero()) {
11027 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011028 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011029 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011030 if (operand.IsOffset() &&
11031 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011032 EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
11033 (rn.GetCode() << 16));
11034 AdvanceIT();
11035 return;
11036 }
11037 } else {
11038 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011039 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011040 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011041 EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
11042 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11043 return;
11044 }
11045 }
11046 }
11047 Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
11048}
11049
11050void Assembler::stlexd(Condition cond,
11051 Register rd,
11052 Register rt,
11053 Register rt2,
11054 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011055 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011056 CheckIT(cond);
11057 if (operand.IsImmediateZero()) {
11058 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011059 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011060 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011061 if (operand.IsOffset() &&
11062 ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11063 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011064 EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
11065 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11066 AdvanceIT();
11067 return;
11068 }
11069 } else {
11070 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11071 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011072 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011073 ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11074 !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +010011075 AllowUnpredictable())) {
11076 EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
11077 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11078 return;
11079 }
11080 }
11081 }
11082 Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
11083}
11084
11085void Assembler::stlexh(Condition cond,
11086 Register rd,
11087 Register rt,
11088 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011089 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011090 CheckIT(cond);
11091 if (operand.IsImmediateZero()) {
11092 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011093 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011094 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011095 if (operand.IsOffset() &&
11096 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011097 EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
11098 (rn.GetCode() << 16));
11099 AdvanceIT();
11100 return;
11101 }
11102 } else {
11103 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011104 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011105 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011106 EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
11107 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11108 return;
11109 }
11110 }
11111 }
11112 Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
11113}
11114
11115void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011116 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011117 CheckIT(cond);
11118 if (operand.IsImmediateZero()) {
11119 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011120 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011121 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011122 if (operand.IsOffset() &&
11123 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011124 EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
11125 AdvanceIT();
11126 return;
11127 }
11128 } else {
11129 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011130 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011131 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011132 EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
11133 (rn.GetCode() << 16));
11134 return;
11135 }
11136 }
11137 }
11138 Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
11139}
11140
11141void Assembler::stm(Condition cond,
11142 EncodingSize size,
11143 Register rn,
11144 WriteBack write_back,
11145 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011146 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011147 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011148 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011149 // STM{<c>}{<q>} <Rn>!, <registers> ; T1
11150 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11151 ((registers.GetList() & ~0xff) == 0)) {
11152 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11153 GetRegisterListEncoding(registers, 0, 8));
11154 AdvanceIT();
11155 return;
11156 }
11157 // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011158 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11159 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011160 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11161 (write_back.GetWriteBackUint32() << 21) |
11162 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11163 GetRegisterListEncoding(registers, 0, 13));
11164 AdvanceIT();
11165 return;
11166 }
11167 } else {
11168 // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011169 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011170 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11171 (write_back.GetWriteBackUint32() << 21) |
11172 GetRegisterListEncoding(registers, 0, 16));
11173 return;
11174 }
11175 }
11176 Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
11177}
11178
11179void Assembler::stmda(Condition cond,
11180 Register rn,
11181 WriteBack write_back,
11182 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011183 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011184 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011185 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011186 // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011187 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011188 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11189 (write_back.GetWriteBackUint32() << 21) |
11190 GetRegisterListEncoding(registers, 0, 16));
11191 return;
11192 }
11193 }
11194 Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
11195}
11196
11197void Assembler::stmdb(Condition cond,
11198 EncodingSize size,
11199 Register rn,
11200 WriteBack write_back,
11201 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011202 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011203 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011204 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011205 // STMDB{<c>}{<q>} SP!, <registers> ; T1
11206 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
Peter Collingbourne920189b2021-01-22 17:42:36 -080011207 registers.IsR0toR7orLR()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011208 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
11209 GetRegisterListEncoding(registers, 0, 8));
11210 AdvanceIT();
11211 return;
11212 }
11213 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011214 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11215 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011216 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11217 (write_back.GetWriteBackUint32() << 21) |
11218 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11219 GetRegisterListEncoding(registers, 0, 13));
11220 AdvanceIT();
11221 return;
11222 }
11223 } else {
11224 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011225 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011226 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11227 (write_back.GetWriteBackUint32() << 21) |
11228 GetRegisterListEncoding(registers, 0, 16));
11229 return;
11230 }
11231 }
11232 Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
11233}
11234
11235void Assembler::stmea(Condition cond,
11236 EncodingSize size,
11237 Register rn,
11238 WriteBack write_back,
11239 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011240 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011241 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011242 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011243 // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
11244 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11245 ((registers.GetList() & ~0xff) == 0)) {
11246 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11247 GetRegisterListEncoding(registers, 0, 8));
11248 AdvanceIT();
11249 return;
11250 }
11251 // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011252 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11253 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011254 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11255 (write_back.GetWriteBackUint32() << 21) |
11256 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11257 GetRegisterListEncoding(registers, 0, 13));
11258 AdvanceIT();
11259 return;
11260 }
11261 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011262 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11263 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011264 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11265 (write_back.GetWriteBackUint32() << 21) |
11266 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11267 GetRegisterListEncoding(registers, 0, 13));
11268 AdvanceIT();
11269 return;
11270 }
11271 } else {
11272 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011273 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011274 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11275 (write_back.GetWriteBackUint32() << 21) |
11276 GetRegisterListEncoding(registers, 0, 16));
11277 return;
11278 }
11279 }
11280 Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
11281}
11282
11283void Assembler::stmed(Condition cond,
11284 Register rn,
11285 WriteBack write_back,
11286 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011287 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011288 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011289 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011290 // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011291 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011292 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11293 (write_back.GetWriteBackUint32() << 21) |
11294 GetRegisterListEncoding(registers, 0, 16));
11295 return;
11296 }
11297 }
11298 Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
11299}
11300
11301void Assembler::stmfa(Condition cond,
11302 Register rn,
11303 WriteBack write_back,
11304 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011305 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011306 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011307 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011308 // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011309 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011310 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11311 (write_back.GetWriteBackUint32() << 21) |
11312 GetRegisterListEncoding(registers, 0, 16));
11313 return;
11314 }
11315 }
11316 Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
11317}
11318
11319void Assembler::stmfd(Condition cond,
11320 Register rn,
11321 WriteBack write_back,
11322 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011323 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011324 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011325 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011326 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011327 if (((registers.GetList() & ~0x5fff) == 0) &&
11328 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011329 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11330 (write_back.GetWriteBackUint32() << 21) |
11331 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11332 GetRegisterListEncoding(registers, 0, 13));
11333 AdvanceIT();
11334 return;
11335 }
11336 } else {
11337 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011338 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011339 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11340 (write_back.GetWriteBackUint32() << 21) |
11341 GetRegisterListEncoding(registers, 0, 16));
11342 return;
11343 }
11344 }
11345 Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
11346}
11347
11348void Assembler::stmib(Condition cond,
11349 Register rn,
11350 WriteBack write_back,
11351 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011352 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011353 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011354 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011355 // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011356 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011357 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11358 (write_back.GetWriteBackUint32() << 21) |
11359 GetRegisterListEncoding(registers, 0, 16));
11360 return;
11361 }
11362 }
11363 Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
11364}
11365
11366void Assembler::str(Condition cond,
11367 EncodingSize size,
11368 Register rt,
11369 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011370 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011371 CheckIT(cond);
11372 if (operand.IsImmediate()) {
11373 Register rn = operand.GetBaseRegister();
11374 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011375 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011376 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11377 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011378 (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011379 int32_t offset_ = offset >> 2;
11380 EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
11381 ((offset_ & 0x1f) << 6));
11382 AdvanceIT();
11383 return;
11384 }
11385 // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
11386 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011387 ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011388 int32_t offset_ = offset >> 2;
11389 EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
11390 AdvanceIT();
11391 return;
11392 }
11393 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
11394 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011395 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11396 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011397 EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11398 (offset & 0xfff));
11399 AdvanceIT();
11400 return;
11401 }
11402 // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
11403 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011404 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11405 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011406 EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11407 (-offset & 0xff));
11408 AdvanceIT();
11409 return;
11410 }
11411 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
11412 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011413 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11414 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011415 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11416 uint32_t offset_ = abs(offset);
11417 EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11418 offset_ | (sign << 9));
11419 AdvanceIT();
11420 return;
11421 }
11422 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
11423 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011424 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11425 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011426 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11427 uint32_t offset_ = abs(offset);
11428 EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11429 offset_ | (sign << 9));
11430 AdvanceIT();
11431 return;
11432 }
11433 } else {
11434 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011435 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11436 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011437 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11438 uint32_t offset_ = abs(offset);
11439 EmitA32(0x05000000U | (cond.GetCondition() << 28) |
11440 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11441 (sign << 23));
11442 return;
11443 }
11444 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011445 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11446 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011447 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11448 uint32_t offset_ = abs(offset);
11449 EmitA32(0x04000000U | (cond.GetCondition() << 28) |
11450 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11451 (sign << 23));
11452 return;
11453 }
11454 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011455 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11456 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011457 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11458 uint32_t offset_ = abs(offset);
11459 EmitA32(0x05200000U | (cond.GetCondition() << 28) |
11460 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11461 (sign << 23));
11462 return;
11463 }
11464 }
11465 }
11466 if (operand.IsPlainRegister()) {
11467 Register rn = operand.GetBaseRegister();
11468 Sign sign = operand.GetSign();
11469 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011470 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011471 // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11472 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011473 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011474 EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
11475 (rm.GetCode() << 6));
11476 AdvanceIT();
11477 return;
11478 }
11479 }
11480 }
11481 if (operand.IsShiftedRegister()) {
11482 Register rn = operand.GetBaseRegister();
11483 Sign sign = operand.GetSign();
11484 Register rm = operand.GetOffsetRegister();
11485 Shift shift = operand.GetShift();
11486 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011487 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011488 // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11489 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011490 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11491 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011492 EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11493 rm.GetCode() | (amount << 4));
11494 AdvanceIT();
11495 return;
11496 }
11497 } else {
11498 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011499 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11500 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011501 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11502 uint32_t shift_ = TypeEncodingValue(shift);
11503 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11504 EmitA32(0x07000000U | (cond.GetCondition() << 28) |
11505 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11506 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11507 return;
11508 }
11509 // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011510 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011511 cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011512 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11513 uint32_t shift_ = TypeEncodingValue(shift);
11514 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11515 EmitA32(0x06000000U | (cond.GetCondition() << 28) |
11516 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11517 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11518 return;
11519 }
11520 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011521 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11522 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011523 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11524 uint32_t shift_ = TypeEncodingValue(shift);
11525 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11526 EmitA32(0x07200000U | (cond.GetCondition() << 28) |
11527 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11528 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11529 return;
11530 }
11531 }
11532 }
11533 Delegate(kStr, &Assembler::str, cond, size, rt, operand);
11534}
11535
11536void Assembler::strb(Condition cond,
11537 EncodingSize size,
11538 Register rt,
11539 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011540 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011541 CheckIT(cond);
11542 if (operand.IsImmediate()) {
11543 Register rn = operand.GetBaseRegister();
11544 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011545 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011546 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11547 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011548 (offset <= 31) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011549 EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
11550 ((offset & 0x1f) << 6));
11551 AdvanceIT();
11552 return;
11553 }
11554 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11555 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011556 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11557 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011558 EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11559 (offset & 0xfff));
11560 AdvanceIT();
11561 return;
11562 }
11563 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11564 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011565 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11566 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011567 EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11568 (-offset & 0xff));
11569 AdvanceIT();
11570 return;
11571 }
11572 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11573 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011574 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11575 (!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 EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11579 offset_ | (sign << 9));
11580 AdvanceIT();
11581 return;
11582 }
11583 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11584 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011585 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11586 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011587 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11588 uint32_t offset_ = abs(offset);
11589 EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11590 offset_ | (sign << 9));
11591 AdvanceIT();
11592 return;
11593 }
11594 } else {
11595 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011596 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011597 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011598 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11599 uint32_t offset_ = abs(offset);
11600 EmitA32(0x05400000U | (cond.GetCondition() << 28) |
11601 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11602 (sign << 23));
11603 return;
11604 }
11605 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011606 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011607 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011608 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11609 uint32_t offset_ = abs(offset);
11610 EmitA32(0x04400000U | (cond.GetCondition() << 28) |
11611 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11612 (sign << 23));
11613 return;
11614 }
11615 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011616 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011617 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011618 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11619 uint32_t offset_ = abs(offset);
11620 EmitA32(0x05600000U | (cond.GetCondition() << 28) |
11621 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11622 (sign << 23));
11623 return;
11624 }
11625 }
11626 }
11627 if (operand.IsPlainRegister()) {
11628 Register rn = operand.GetBaseRegister();
11629 Sign sign = operand.GetSign();
11630 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011631 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011632 // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11633 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011634 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011635 EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
11636 (rm.GetCode() << 6));
11637 AdvanceIT();
11638 return;
11639 }
11640 }
11641 }
11642 if (operand.IsShiftedRegister()) {
11643 Register rn = operand.GetBaseRegister();
11644 Sign sign = operand.GetSign();
11645 Register rm = operand.GetOffsetRegister();
11646 Shift shift = operand.GetShift();
11647 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011648 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011649 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11650 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011651 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11652 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011653 EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11654 rm.GetCode() | (amount << 4));
11655 AdvanceIT();
11656 return;
11657 }
11658 } else {
11659 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011660 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11661 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011662 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11663 uint32_t shift_ = TypeEncodingValue(shift);
11664 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11665 EmitA32(0x07400000U | (cond.GetCondition() << 28) |
11666 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11667 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11668 return;
11669 }
11670 // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011671 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011672 cond.IsNotNever() &&
11673 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011674 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11675 uint32_t shift_ = TypeEncodingValue(shift);
11676 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11677 EmitA32(0x06400000U | (cond.GetCondition() << 28) |
11678 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11679 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11680 return;
11681 }
11682 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011683 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11684 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011685 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11686 uint32_t shift_ = TypeEncodingValue(shift);
11687 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11688 EmitA32(0x07600000U | (cond.GetCondition() << 28) |
11689 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11690 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11691 return;
11692 }
11693 }
11694 }
11695 Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
11696}
11697
11698void Assembler::strd(Condition cond,
11699 Register rt,
11700 Register rt2,
11701 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011702 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011703 CheckIT(cond);
11704 if (operand.IsImmediate()) {
11705 Register rn = operand.GetBaseRegister();
11706 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011707 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011708 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
11709 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011710 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11711 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011712 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11713 uint32_t offset_ = abs(offset) >> 2;
11714 EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11715 (rn.GetCode() << 16) | offset_ | (sign << 23));
11716 AdvanceIT();
11717 return;
11718 }
11719 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
11720 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011721 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11722 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011723 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11724 uint32_t offset_ = abs(offset) >> 2;
11725 EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11726 (rn.GetCode() << 16) | offset_ | (sign << 23));
11727 AdvanceIT();
11728 return;
11729 }
11730 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
11731 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011732 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11733 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011734 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11735 uint32_t offset_ = abs(offset) >> 2;
11736 EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11737 (rn.GetCode() << 16) | offset_ | (sign << 23));
11738 AdvanceIT();
11739 return;
11740 }
11741 } else {
11742 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
11743 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011744 (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011745 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11746 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011747 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11748 uint32_t offset_ = abs(offset);
11749 EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
11750 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11751 ((offset_ & 0xf0) << 4) | (sign << 23));
11752 return;
11753 }
11754 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
11755 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011756 (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011757 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11758 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011759 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11760 uint32_t offset_ = abs(offset);
11761 EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
11762 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11763 ((offset_ & 0xf0) << 4) | (sign << 23));
11764 return;
11765 }
11766 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
11767 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011768 (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011769 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11770 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011771 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11772 uint32_t offset_ = abs(offset);
11773 EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
11774 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11775 ((offset_ & 0xf0) << 4) | (sign << 23));
11776 return;
11777 }
11778 }
11779 }
11780 if (operand.IsPlainRegister()) {
11781 Register rn = operand.GetBaseRegister();
11782 Sign sign = operand.GetSign();
11783 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011784 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011785 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
11786 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011787 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011788 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011789 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011790 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11791 EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
11792 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11793 (sign_ << 23));
11794 return;
11795 }
11796 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
11797 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011798 operand.IsPostIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011799 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011800 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011801 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11802 EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
11803 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11804 (sign_ << 23));
11805 return;
11806 }
11807 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
11808 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011809 operand.IsPreIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011810 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011811 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011812 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11813 EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
11814 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11815 (sign_ << 23));
11816 return;
11817 }
11818 }
11819 }
11820 Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
11821}
11822
11823void Assembler::strex(Condition cond,
11824 Register rd,
11825 Register rt,
11826 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011827 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011828 CheckIT(cond);
11829 if (operand.IsImmediate()) {
11830 Register rn = operand.GetBaseRegister();
11831 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011832 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011833 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
11834 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011835 operand.IsOffset() &&
11836 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011837 int32_t offset_ = offset >> 2;
11838 EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
11839 (rn.GetCode() << 16) | (offset_ & 0xff));
11840 AdvanceIT();
11841 return;
11842 }
11843 } else {
11844 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011845 if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
11846 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011847 EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
11848 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11849 return;
11850 }
11851 }
11852 }
11853 Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
11854}
11855
11856void Assembler::strexb(Condition cond,
11857 Register rd,
11858 Register rt,
11859 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011860 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011861 CheckIT(cond);
11862 if (operand.IsImmediateZero()) {
11863 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011864 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011865 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011866 if (operand.IsOffset() &&
11867 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011868 EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
11869 (rn.GetCode() << 16));
11870 AdvanceIT();
11871 return;
11872 }
11873 } else {
11874 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011875 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011876 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011877 EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
11878 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11879 return;
11880 }
11881 }
11882 }
11883 Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
11884}
11885
11886void Assembler::strexd(Condition cond,
11887 Register rd,
11888 Register rt,
11889 Register rt2,
11890 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011891 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011892 CheckIT(cond);
11893 if (operand.IsImmediateZero()) {
11894 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011896 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011897 if (operand.IsOffset() &&
11898 ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11899 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011900 EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
11901 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11902 AdvanceIT();
11903 return;
11904 }
11905 } else {
11906 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11907 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011908 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011909 ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11910 !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +010011911 AllowUnpredictable())) {
11912 EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
11913 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11914 return;
11915 }
11916 }
11917 }
11918 Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
11919}
11920
11921void Assembler::strexh(Condition cond,
11922 Register rd,
11923 Register rt,
11924 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011925 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011926 CheckIT(cond);
11927 if (operand.IsImmediateZero()) {
11928 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011929 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011930 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011931 if (operand.IsOffset() &&
11932 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011933 EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
11934 (rn.GetCode() << 16));
11935 AdvanceIT();
11936 return;
11937 }
11938 } else {
11939 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011940 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011941 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011942 EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
11943 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11944 return;
11945 }
11946 }
11947 }
11948 Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
11949}
11950
11951void Assembler::strh(Condition cond,
11952 EncodingSize size,
11953 Register rt,
11954 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011955 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011956 CheckIT(cond);
11957 if (operand.IsImmediate()) {
11958 Register rn = operand.GetBaseRegister();
11959 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011960 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011961 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11962 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011963 (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011964 int32_t offset_ = offset >> 1;
11965 EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
11966 ((offset_ & 0x1f) << 6));
11967 AdvanceIT();
11968 return;
11969 }
11970 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11971 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011972 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11973 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011974 EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11975 (offset & 0xfff));
11976 AdvanceIT();
11977 return;
11978 }
11979 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11980 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011981 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11982 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011983 EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11984 (-offset & 0xff));
11985 AdvanceIT();
11986 return;
11987 }
11988 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11989 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011990 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11991 (!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 EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11995 offset_ | (sign << 9));
11996 AdvanceIT();
11997 return;
11998 }
11999 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
12000 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012001 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
12002 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012003 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12004 uint32_t offset_ = abs(offset);
12005 EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12006 offset_ | (sign << 9));
12007 AdvanceIT();
12008 return;
12009 }
12010 } else {
12011 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080012012 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012013 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012014 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12015 uint32_t offset_ = abs(offset);
12016 EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
12017 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
12018 ((offset_ & 0xf0) << 4) | (sign << 23));
12019 return;
12020 }
12021 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080012022 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012023 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012024 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12025 uint32_t offset_ = abs(offset);
12026 EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
12027 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
12028 ((offset_ & 0xf0) << 4) | (sign << 23));
12029 return;
12030 }
12031 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080012032 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012033 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012034 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
12035 uint32_t offset_ = abs(offset);
12036 EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
12037 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
12038 ((offset_ & 0xf0) << 4) | (sign << 23));
12039 return;
12040 }
12041 }
12042 }
12043 if (operand.IsPlainRegister()) {
12044 Register rn = operand.GetBaseRegister();
12045 Sign sign = operand.GetSign();
12046 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012047 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012048 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
12049 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080012050 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012051 EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
12052 (rm.GetCode() << 6));
12053 AdvanceIT();
12054 return;
12055 }
12056 } else {
12057 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012058 if (operand.IsOffset() && cond.IsNotNever() &&
12059 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012060 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12061 EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
12062 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12063 (sign_ << 23));
12064 return;
12065 }
12066 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012067 if (operand.IsPostIndex() && cond.IsNotNever() &&
12068 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012069 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12070 EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
12071 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12072 (sign_ << 23));
12073 return;
12074 }
12075 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012076 if (operand.IsPreIndex() && cond.IsNotNever() &&
12077 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012078 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12079 EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
12080 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12081 (sign_ << 23));
12082 return;
12083 }
12084 }
12085 }
12086 if (operand.IsShiftedRegister()) {
12087 Register rn = operand.GetBaseRegister();
12088 Sign sign = operand.GetSign();
12089 Register rm = operand.GetOffsetRegister();
12090 Shift shift = operand.GetShift();
12091 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012092 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012093 // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
12094 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012095 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
12096 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012097 EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12098 rm.GetCode() | (amount << 4));
12099 AdvanceIT();
12100 return;
12101 }
12102 }
12103 }
12104 Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
12105}
12106
12107void Assembler::sub(Condition cond,
12108 EncodingSize size,
12109 Register rd,
12110 Register rn,
12111 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012112 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012113 CheckIT(cond);
12114 if (operand.IsImmediate()) {
12115 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012116 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012117 ImmediateT32 immediate_t32(imm);
12118 // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
12119 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12120 (imm <= 7)) {
12121 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12122 AdvanceIT();
12123 return;
12124 }
12125 // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12126 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12127 (imm <= 255)) {
12128 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12129 AdvanceIT();
12130 return;
12131 }
12132 // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
12133 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
12134 ((imm % 4) == 0)) {
12135 uint32_t imm_ = imm >> 2;
12136 EmitT32_16(0xb080 | imm_);
12137 AdvanceIT();
12138 return;
12139 }
12140 // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +000012141 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
12142 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012143 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12144 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12145 AdvanceIT();
12146 return;
12147 }
12148 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012149 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12150 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012151 EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12152 (immediate_t32.GetEncodingValue() & 0xff) |
12153 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12154 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12155 AdvanceIT();
12156 return;
12157 }
12158 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Pierre Langlois960d28b2017-02-15 13:06:01 +000012159 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12160 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012161 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12162 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12163 AdvanceIT();
12164 return;
12165 }
12166 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012167 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12168 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012169 EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
12170 (immediate_t32.GetEncodingValue() & 0xff) |
12171 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12172 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12173 AdvanceIT();
12174 return;
12175 }
12176 // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012177 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
12178 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012179 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12180 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12181 AdvanceIT();
12182 return;
12183 }
12184 } else {
12185 ImmediateA32 immediate_a32(imm);
12186 // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
12187 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
12188 EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
12189 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12190 return;
12191 }
12192 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12193 if (immediate_a32.IsValid() && cond.IsNotNever() &&
12194 ((rn.GetCode() & 0xd) != 0xd)) {
12195 EmitA32(0x02400000U | (cond.GetCondition() << 28) |
12196 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12197 immediate_a32.GetEncodingValue());
12198 return;
12199 }
12200 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12201 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12202 EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
12203 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12204 return;
12205 }
12206 }
12207 }
12208 if (operand.IsImmediateShiftedRegister()) {
12209 Register rm = operand.GetBaseRegister();
12210 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012211 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012212 // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
12213 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12214 rm.IsLow()) {
12215 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12216 (rm.GetCode() << 6));
12217 AdvanceIT();
12218 return;
12219 }
12220 // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012221 if (rn.Is(sp) && ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012222 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
12223 AdvanceIT();
12224 return;
12225 }
12226 }
12227 }
12228 Shift shift = operand.GetShift();
12229 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012230 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012231 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012232 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12233 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012234 uint32_t amount_ = amount % 32;
12235 EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12236 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12237 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12238 AdvanceIT();
12239 return;
12240 }
12241 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012242 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12243 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012244 uint32_t amount_ = amount % 32;
12245 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
12246 (operand.GetTypeEncodingValue() << 4) |
12247 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12248 AdvanceIT();
12249 return;
12250 }
12251 } else {
12252 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12253 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12254 uint32_t amount_ = amount % 32;
12255 EmitA32(0x00400000U | (cond.GetCondition() << 28) |
12256 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12257 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12258 return;
12259 }
12260 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12261 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12262 uint32_t amount_ = amount % 32;
12263 EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
12264 (rd.GetCode() << 12) | rm.GetCode() |
12265 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12266 return;
12267 }
12268 }
12269 }
12270 if (operand.IsRegisterShiftedRegister()) {
12271 Register rm = operand.GetBaseRegister();
12272 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012273 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012274 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012275 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +000012276 if (cond.IsNotNever() &&
12277 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12278 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012279 EmitA32(0x00400010U | (cond.GetCondition() << 28) |
12280 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012281 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012282 return;
12283 }
12284 }
12285 }
12286 Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
12287}
12288
12289void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012290 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012291 CheckIT(cond);
12292 if (operand.IsImmediate()) {
12293 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012294 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012295 // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
12296 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
12297 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12298 AdvanceIT();
12299 return;
12300 }
12301 }
12302 }
12303 Delegate(kSub, &Assembler::sub, cond, rd, operand);
12304}
12305
12306void Assembler::subs(Condition cond,
12307 EncodingSize size,
12308 Register rd,
12309 Register rn,
12310 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012311 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012312 CheckIT(cond);
12313 if (operand.IsImmediate()) {
12314 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012315 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012316 ImmediateT32 immediate_t32(imm);
12317 // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
12318 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12319 (imm <= 7)) {
12320 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12321 AdvanceIT();
12322 return;
12323 }
12324 // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12325 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12326 (imm <= 255)) {
12327 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12328 AdvanceIT();
12329 return;
12330 }
12331 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12332 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012333 !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012334 EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12335 (immediate_t32.GetEncodingValue() & 0xff) |
12336 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12337 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12338 AdvanceIT();
12339 return;
12340 }
12341 // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
Pierre Langloisdc626f32017-02-15 13:31:28 +000012342 if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255) &&
12343 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012344 EmitT32_32(0xf3de8f00U | imm);
12345 AdvanceIT();
12346 return;
12347 }
12348 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12349 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12350 !rd.Is(pc)) {
12351 EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
12352 (immediate_t32.GetEncodingValue() & 0xff) |
12353 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12354 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12355 AdvanceIT();
12356 return;
12357 }
12358 } else {
12359 ImmediateA32 immediate_a32(imm);
12360 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12361 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
12362 EmitA32(0x02500000U | (cond.GetCondition() << 28) |
12363 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12364 immediate_a32.GetEncodingValue());
12365 return;
12366 }
12367 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12368 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12369 EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
12370 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12371 return;
12372 }
12373 }
12374 }
12375 if (operand.IsImmediateShiftedRegister()) {
12376 Register rm = operand.GetBaseRegister();
12377 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012378 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012379 // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12380 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12381 rm.IsLow()) {
12382 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12383 (rm.GetCode() << 6));
12384 AdvanceIT();
12385 return;
12386 }
12387 }
12388 }
12389 Shift shift = operand.GetShift();
12390 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012391 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012392 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12393 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012394 !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012395 uint32_t amount_ = amount % 32;
12396 EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12397 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12398 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12399 AdvanceIT();
12400 return;
12401 }
12402 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12403 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012404 !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012405 uint32_t amount_ = amount % 32;
12406 EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
12407 (operand.GetTypeEncodingValue() << 4) |
12408 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12409 AdvanceIT();
12410 return;
12411 }
12412 } else {
12413 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12414 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12415 uint32_t amount_ = amount % 32;
12416 EmitA32(0x00500000U | (cond.GetCondition() << 28) |
12417 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12418 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12419 return;
12420 }
12421 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12422 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12423 uint32_t amount_ = amount % 32;
12424 EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
12425 (rd.GetCode() << 12) | rm.GetCode() |
12426 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12427 return;
12428 }
12429 }
12430 }
12431 if (operand.IsRegisterShiftedRegister()) {
12432 Register rm = operand.GetBaseRegister();
12433 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012434 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012435 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012436 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +000012437 if (cond.IsNotNever() &&
12438 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12439 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012440 EmitA32(0x00500010U | (cond.GetCondition() << 28) |
12441 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012442 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012443 return;
12444 }
12445 }
12446 }
12447 Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
12448}
12449
12450void Assembler::subs(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012451 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012452 CheckIT(al);
12453 if (operand.IsImmediate()) {
12454 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012455 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012456 // SUBS{<q>} <Rdn>, #<imm8> ; T2
12457 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
12458 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12459 AdvanceIT();
12460 return;
12461 }
12462 }
12463 }
12464 Delegate(kSubs, &Assembler::subs, rd, operand);
12465}
12466
12467void Assembler::subw(Condition cond,
12468 Register rd,
12469 Register rn,
12470 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012471 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012472 CheckIT(cond);
12473 if (operand.IsImmediate()) {
12474 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012475 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012476 // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Pierre Langlois960d28b2017-02-15 13:06:01 +000012477 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12478 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012479 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12480 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12481 AdvanceIT();
12482 return;
12483 }
12484 // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012485 if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012486 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12487 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12488 AdvanceIT();
12489 return;
12490 }
12491 }
12492 }
12493 Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
12494}
12495
12496void Assembler::svc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012497 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012498 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012499 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012500 // SVC{<c>}{<q>} {#}<imm> ; T1
12501 if ((imm <= 255)) {
12502 EmitT32_16(0xdf00 | imm);
12503 AdvanceIT();
12504 return;
12505 }
12506 } else {
12507 // SVC{<c>}{<q>} {#}<imm> ; A1
12508 if ((imm <= 16777215) && cond.IsNotNever()) {
12509 EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
12510 return;
12511 }
12512 }
12513 Delegate(kSvc, &Assembler::svc, cond, imm);
12514}
12515
12516void Assembler::sxtab(Condition cond,
12517 Register rd,
12518 Register rn,
12519 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012520 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012521 CheckIT(cond);
12522 if (operand.IsImmediateShiftedRegister()) {
12523 Register rm = operand.GetBaseRegister();
12524 Shift shift = operand.GetShift();
12525 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012526 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012527 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12528 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012529 ((amount % 8) == 0) && !rn.Is(pc) &&
12530 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012531 uint32_t amount_ = amount / 8;
12532 EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12533 rm.GetCode() | (amount_ << 4));
12534 AdvanceIT();
12535 return;
12536 }
12537 } else {
12538 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12539 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012540 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12541 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012542 uint32_t amount_ = amount / 8;
12543 EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
12544 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12545 (amount_ << 10));
12546 return;
12547 }
12548 }
12549 }
12550 Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
12551}
12552
12553void Assembler::sxtab16(Condition cond,
12554 Register rd,
12555 Register rn,
12556 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012557 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012558 CheckIT(cond);
12559 if (operand.IsImmediateShiftedRegister()) {
12560 Register rm = operand.GetBaseRegister();
12561 Shift shift = operand.GetShift();
12562 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012563 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012564 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12565 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012566 ((amount % 8) == 0) && !rn.Is(pc) &&
12567 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012568 uint32_t amount_ = amount / 8;
12569 EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12570 rm.GetCode() | (amount_ << 4));
12571 AdvanceIT();
12572 return;
12573 }
12574 } else {
12575 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12576 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012577 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12578 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012579 uint32_t amount_ = amount / 8;
12580 EmitA32(0x06800070U | (cond.GetCondition() << 28) |
12581 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12582 (amount_ << 10));
12583 return;
12584 }
12585 }
12586 }
12587 Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
12588}
12589
12590void Assembler::sxtah(Condition cond,
12591 Register rd,
12592 Register rn,
12593 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012594 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012595 CheckIT(cond);
12596 if (operand.IsImmediateShiftedRegister()) {
12597 Register rm = operand.GetBaseRegister();
12598 Shift shift = operand.GetShift();
12599 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012600 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012601 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12602 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012603 ((amount % 8) == 0) && !rn.Is(pc) &&
12604 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012605 uint32_t amount_ = amount / 8;
12606 EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12607 rm.GetCode() | (amount_ << 4));
12608 AdvanceIT();
12609 return;
12610 }
12611 } else {
12612 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12613 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012614 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12615 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012616 uint32_t amount_ = amount / 8;
12617 EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
12618 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12619 (amount_ << 10));
12620 return;
12621 }
12622 }
12623 }
12624 Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
12625}
12626
12627void Assembler::sxtb(Condition cond,
12628 EncodingSize size,
12629 Register rd,
12630 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012631 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012632 CheckIT(cond);
12633 if (operand.IsImmediateShiftedRegister()) {
12634 Register rm = operand.GetBaseRegister();
12635 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012636 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012637 // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12638 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12639 EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
12640 AdvanceIT();
12641 return;
12642 }
12643 }
12644 }
12645 Shift shift = operand.GetShift();
12646 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012647 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012648 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12649 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012650 (amount <= 24) && ((amount % 8) == 0) &&
12651 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012652 uint32_t amount_ = amount / 8;
12653 EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12654 (amount_ << 4));
12655 AdvanceIT();
12656 return;
12657 }
12658 } else {
12659 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12660 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012661 ((amount % 8) == 0) && cond.IsNotNever() &&
12662 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012663 uint32_t amount_ = amount / 8;
12664 EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
12665 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12666 return;
12667 }
12668 }
12669 }
12670 Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
12671}
12672
12673void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012674 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012675 CheckIT(cond);
12676 if (operand.IsImmediateShiftedRegister()) {
12677 Register rm = operand.GetBaseRegister();
12678 Shift shift = operand.GetShift();
12679 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012680 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012681 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12682 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012683 ((amount % 8) == 0) &&
12684 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012685 uint32_t amount_ = amount / 8;
12686 EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12687 (amount_ << 4));
12688 AdvanceIT();
12689 return;
12690 }
12691 } else {
12692 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12693 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012694 ((amount % 8) == 0) && cond.IsNotNever() &&
12695 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012696 uint32_t amount_ = amount / 8;
12697 EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
12698 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12699 return;
12700 }
12701 }
12702 }
12703 Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
12704}
12705
12706void Assembler::sxth(Condition cond,
12707 EncodingSize size,
12708 Register rd,
12709 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012710 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012711 CheckIT(cond);
12712 if (operand.IsImmediateShiftedRegister()) {
12713 Register rm = operand.GetBaseRegister();
12714 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012715 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012716 // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12717 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12718 EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
12719 AdvanceIT();
12720 return;
12721 }
12722 }
12723 }
12724 Shift shift = operand.GetShift();
12725 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012726 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012727 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12728 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012729 (amount <= 24) && ((amount % 8) == 0) &&
12730 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012731 uint32_t amount_ = amount / 8;
12732 EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12733 (amount_ << 4));
12734 AdvanceIT();
12735 return;
12736 }
12737 } else {
12738 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12739 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012740 ((amount % 8) == 0) && cond.IsNotNever() &&
12741 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012742 uint32_t amount_ = amount / 8;
12743 EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
12744 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12745 return;
12746 }
12747 }
12748 }
12749 Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
12750}
12751
12752void Assembler::tbb(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012753 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012754 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012756 // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
12757 if (OutsideITBlockAndAlOrLast(cond) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080012758 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012759 EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
12760 AdvanceIT();
12761 return;
12762 }
12763 }
12764 Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
12765}
12766
12767void Assembler::tbh(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012768 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012769 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012770 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012771 // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
12772 if (OutsideITBlockAndAlOrLast(cond) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080012773 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012774 EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
12775 AdvanceIT();
12776 return;
12777 }
12778 }
12779 Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
12780}
12781
12782void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012783 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012784 CheckIT(cond);
12785 if (operand.IsImmediate()) {
12786 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012787 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012788 ImmediateT32 immediate_t32(imm);
12789 // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012790 if (immediate_t32.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012791 EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
12792 (immediate_t32.GetEncodingValue() & 0xff) |
12793 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12794 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12795 AdvanceIT();
12796 return;
12797 }
12798 } else {
12799 ImmediateA32 immediate_a32(imm);
12800 // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
12801 if (immediate_a32.IsValid() && cond.IsNotNever()) {
12802 EmitA32(0x03300000U | (cond.GetCondition() << 28) |
12803 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12804 return;
12805 }
12806 }
12807 }
12808 if (operand.IsImmediateShiftedRegister()) {
12809 Register rm = operand.GetBaseRegister();
12810 Shift shift = operand.GetShift();
12811 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012812 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012813 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012814 if (shift.IsValidAmount(amount) &&
12815 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012816 uint32_t amount_ = amount % 32;
12817 EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
12818 (operand.GetTypeEncodingValue() << 4) |
12819 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12820 AdvanceIT();
12821 return;
12822 }
12823 } else {
12824 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12825 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12826 uint32_t amount_ = amount % 32;
12827 EmitA32(0x01300000U | (cond.GetCondition() << 28) |
12828 (rn.GetCode() << 16) | rm.GetCode() |
12829 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12830 return;
12831 }
12832 }
12833 }
12834 if (operand.IsRegisterShiftedRegister()) {
12835 Register rm = operand.GetBaseRegister();
12836 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012837 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012838 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012839 // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012840 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +000012841 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012842 EmitA32(0x01300010U | (cond.GetCondition() << 28) |
12843 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012844 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012845 return;
12846 }
12847 }
12848 }
12849 Delegate(kTeq, &Assembler::teq, cond, rn, operand);
12850}
12851
12852void Assembler::tst(Condition cond,
12853 EncodingSize size,
12854 Register rn,
12855 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012856 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012857 CheckIT(cond);
12858 if (operand.IsImmediate()) {
12859 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012860 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012861 ImmediateT32 immediate_t32(imm);
12862 // TST{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012863 if (!size.IsNarrow() && immediate_t32.IsValid() &&
12864 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012865 EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
12866 (immediate_t32.GetEncodingValue() & 0xff) |
12867 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12868 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12869 AdvanceIT();
12870 return;
12871 }
12872 } else {
12873 ImmediateA32 immediate_a32(imm);
12874 // TST{<c>}{<q>} <Rn>, #<const> ; A1
12875 if (immediate_a32.IsValid() && cond.IsNotNever()) {
12876 EmitA32(0x03100000U | (cond.GetCondition() << 28) |
12877 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12878 return;
12879 }
12880 }
12881 }
12882 if (operand.IsImmediateShiftedRegister()) {
12883 Register rm = operand.GetBaseRegister();
12884 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012885 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012886 // TST{<c>}{<q>} <Rn>, <Rm> ; T1
12887 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
12888 EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
12889 AdvanceIT();
12890 return;
12891 }
12892 }
12893 }
12894 Shift shift = operand.GetShift();
12895 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012896 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012897 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012898 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
12899 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012900 uint32_t amount_ = amount % 32;
12901 EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
12902 (operand.GetTypeEncodingValue() << 4) |
12903 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12904 AdvanceIT();
12905 return;
12906 }
12907 } else {
12908 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12909 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12910 uint32_t amount_ = amount % 32;
12911 EmitA32(0x01100000U | (cond.GetCondition() << 28) |
12912 (rn.GetCode() << 16) | rm.GetCode() |
12913 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12914 return;
12915 }
12916 }
12917 }
12918 if (operand.IsRegisterShiftedRegister()) {
12919 Register rm = operand.GetBaseRegister();
12920 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012921 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012922 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012923 // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012924 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +000012925 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012926 EmitA32(0x01100010U | (cond.GetCondition() << 28) |
12927 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012928 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012929 return;
12930 }
12931 }
12932 }
12933 Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
12934}
12935
12936void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012937 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012938 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012939 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012940 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012941 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12942 EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12943 rm.GetCode());
12944 AdvanceIT();
12945 return;
12946 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012947 } else {
12948 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012949 if (cond.IsNotNever() &&
12950 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012951 EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12952 (rn.GetCode() << 16) | rm.GetCode());
12953 return;
12954 }
12955 }
12956 Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
12957}
12958
12959void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012960 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012961 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012962 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012963 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012964 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12965 EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12966 rm.GetCode());
12967 AdvanceIT();
12968 return;
12969 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012970 } else {
12971 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012972 if (cond.IsNotNever() &&
12973 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012974 EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12975 (rn.GetCode() << 16) | rm.GetCode());
12976 return;
12977 }
12978 }
12979 Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
12980}
12981
12982void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012983 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012984 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012985 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012986 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012987 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12988 EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12989 rm.GetCode());
12990 AdvanceIT();
12991 return;
12992 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012993 } else {
12994 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012995 if (cond.IsNotNever() &&
12996 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012997 EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12998 (rn.GetCode() << 16) | rm.GetCode());
12999 return;
13000 }
13001 }
13002 Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
13003}
13004
Vincent Belliard609821f2017-02-08 14:17:25 -080013005void Assembler::ubfx(
13006 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013007 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013008 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -080013009 if (IsUsingT32()) {
13010 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
13011 if ((lsb <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013012 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
13013 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -080013014 uint32_t widthm1 = width - 1;
13015 EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13016 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
13017 AdvanceIT();
13018 return;
13019 }
13020 } else {
13021 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
13022 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013023 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
13024 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -080013025 uint32_t widthm1 = width - 1;
13026 EmitA32(0x07e00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13027 rn.GetCode() | (lsb << 7) | (widthm1 << 16));
13028 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +010013029 }
13030 }
Vincent Belliard609821f2017-02-08 14:17:25 -080013031 Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +010013032}
13033
13034void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013035 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013036 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013037 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013038 // UDF{<c>}{<q>} {#}<imm> ; T1
13039 if (!size.IsWide() && (imm <= 255)) {
13040 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13041 EmitT32_16(0xde00 | imm);
13042 AdvanceIT();
13043 return;
13044 }
13045 }
13046 // UDF{<c>}{<q>} {#}<imm> ; T2
13047 if (!size.IsNarrow() && (imm <= 65535)) {
13048 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13049 EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
13050 AdvanceIT();
13051 return;
13052 }
13053 }
13054 } else {
13055 // UDF{<c>}{<q>} {#}<imm> ; A1
13056 if ((imm <= 65535)) {
13057 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13058 EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
13059 return;
13060 }
13061 }
13062 }
13063 Delegate(kUdf, &Assembler::udf, cond, size, imm);
13064}
13065
13066void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013067 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013068 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013069 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013070 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013071 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13072 EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13073 rm.GetCode());
13074 AdvanceIT();
13075 return;
13076 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013077 } else {
13078 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013079 if (cond.IsNotNever() &&
13080 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013081 EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13082 rn.GetCode() | (rm.GetCode() << 8));
13083 return;
13084 }
13085 }
13086 Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
13087}
13088
13089void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013090 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013091 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013092 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013093 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013094 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13095 EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13096 rm.GetCode());
13097 AdvanceIT();
13098 return;
13099 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013100 } else {
13101 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013102 if (cond.IsNotNever() &&
13103 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013104 EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13105 (rn.GetCode() << 16) | rm.GetCode());
13106 return;
13107 }
13108 }
13109 Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
13110}
13111
13112void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013113 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013114 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013115 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013116 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013117 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13118 EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13119 rm.GetCode());
13120 AdvanceIT();
13121 return;
13122 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013123 } else {
13124 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013125 if (cond.IsNotNever() &&
13126 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013127 EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13128 (rn.GetCode() << 16) | rm.GetCode());
13129 return;
13130 }
13131 }
13132 Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
13133}
13134
13135void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013136 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013137 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013138 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013139 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013140 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13141 EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13142 rm.GetCode());
13143 AdvanceIT();
13144 return;
13145 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013146 } else {
13147 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013148 if (cond.IsNotNever() &&
13149 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013150 EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13151 (rn.GetCode() << 16) | rm.GetCode());
13152 return;
13153 }
13154 }
13155 Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
13156}
13157
13158void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013159 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013160 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013161 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013162 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013163 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13164 EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13165 rm.GetCode());
13166 AdvanceIT();
13167 return;
13168 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013169 } else {
13170 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013171 if (cond.IsNotNever() &&
13172 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013173 EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13174 (rn.GetCode() << 16) | rm.GetCode());
13175 return;
13176 }
13177 }
13178 Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
13179}
13180
13181void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013182 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013183 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013184 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013185 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013186 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13187 EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13188 rm.GetCode());
13189 AdvanceIT();
13190 return;
13191 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013192 } else {
13193 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013194 if (cond.IsNotNever() &&
13195 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013196 EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13197 (rn.GetCode() << 16) | rm.GetCode());
13198 return;
13199 }
13200 }
13201 Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
13202}
13203
13204void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013205 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013206 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013207 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013208 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013209 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13210 EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13211 rm.GetCode());
13212 AdvanceIT();
13213 return;
13214 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013215 } else {
13216 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013217 if (cond.IsNotNever() &&
13218 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013219 EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13220 (rn.GetCode() << 16) | rm.GetCode());
13221 return;
13222 }
13223 }
13224 Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
13225}
13226
13227void Assembler::umaal(
13228 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013229 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013230 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013231 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013232 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013233 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13234 AllowUnpredictable())) {
13235 EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13236 (rn.GetCode() << 16) | rm.GetCode());
13237 AdvanceIT();
13238 return;
13239 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013240 } else {
13241 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013242 if (cond.IsNotNever() &&
13243 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13244 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013245 EmitA32(0x00400090U | (cond.GetCondition() << 28) |
13246 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13247 (rm.GetCode() << 8));
13248 return;
13249 }
13250 }
13251 Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
13252}
13253
13254void Assembler::umlal(
13255 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013256 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013257 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013258 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013259 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013260 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13261 AllowUnpredictable())) {
13262 EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13263 (rn.GetCode() << 16) | rm.GetCode());
13264 AdvanceIT();
13265 return;
13266 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013267 } else {
13268 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013269 if (cond.IsNotNever() &&
13270 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13271 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013272 EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
13273 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13274 (rm.GetCode() << 8));
13275 return;
13276 }
13277 }
13278 Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
13279}
13280
13281void Assembler::umlals(
13282 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013283 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013284 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013285 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013286 // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013287 if (cond.IsNotNever() &&
13288 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13289 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013290 EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
13291 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13292 (rm.GetCode() << 8));
13293 return;
13294 }
13295 }
13296 Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
13297}
13298
13299void Assembler::umull(
13300 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013301 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013302 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013303 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013304 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013305 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13306 AllowUnpredictable())) {
13307 EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13308 (rn.GetCode() << 16) | rm.GetCode());
13309 AdvanceIT();
13310 return;
13311 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013312 } else {
13313 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013314 if (cond.IsNotNever() &&
13315 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13316 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013317 EmitA32(0x00800090U | (cond.GetCondition() << 28) |
13318 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13319 (rm.GetCode() << 8));
13320 return;
13321 }
13322 }
13323 Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
13324}
13325
13326void Assembler::umulls(
13327 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013328 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013329 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013330 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013331 // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013332 if (cond.IsNotNever() &&
13333 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13334 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013335 EmitA32(0x00900090U | (cond.GetCondition() << 28) |
13336 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13337 (rm.GetCode() << 8));
13338 return;
13339 }
13340 }
13341 Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
13342}
13343
13344void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013345 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013346 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013347 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013348 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013349 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13350 EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13351 rm.GetCode());
13352 AdvanceIT();
13353 return;
13354 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013355 } else {
13356 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013357 if (cond.IsNotNever() &&
13358 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013359 EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13360 (rn.GetCode() << 16) | rm.GetCode());
13361 return;
13362 }
13363 }
13364 Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
13365}
13366
13367void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013369 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013370 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013371 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013372 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13373 EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13374 rm.GetCode());
13375 AdvanceIT();
13376 return;
13377 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013378 } else {
13379 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013380 if (cond.IsNotNever() &&
13381 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013382 EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13383 (rn.GetCode() << 16) | rm.GetCode());
13384 return;
13385 }
13386 }
13387 Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
13388}
13389
13390void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013391 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013392 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013393 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013394 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013395 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13396 EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13397 rm.GetCode());
13398 AdvanceIT();
13399 return;
13400 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013401 } else {
13402 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013403 if (cond.IsNotNever() &&
13404 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013405 EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13406 (rn.GetCode() << 16) | rm.GetCode());
13407 return;
13408 }
13409 }
13410 Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
13411}
13412
13413void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013414 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013415 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013416 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013417 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013418 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13419 EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13420 rm.GetCode());
13421 AdvanceIT();
13422 return;
13423 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013424 } else {
13425 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013426 if (cond.IsNotNever() &&
13427 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013428 EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13429 (rn.GetCode() << 16) | rm.GetCode());
13430 return;
13431 }
13432 }
13433 Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
13434}
13435
13436void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013437 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013438 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013439 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013440 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013441 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13442 EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13443 rm.GetCode());
13444 AdvanceIT();
13445 return;
13446 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013447 } else {
13448 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013449 if (cond.IsNotNever() &&
13450 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013451 EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13452 (rn.GetCode() << 16) | rm.GetCode());
13453 return;
13454 }
13455 }
13456 Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
13457}
13458
13459void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013460 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013461 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013462 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013463 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013464 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13465 EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13466 rm.GetCode());
13467 AdvanceIT();
13468 return;
13469 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013470 } else {
13471 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013472 if (cond.IsNotNever() &&
13473 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013474 EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13475 (rn.GetCode() << 16) | rm.GetCode());
13476 return;
13477 }
13478 }
13479 Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
13480}
13481
13482void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013483 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013484 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013485 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013486 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013487 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13488 EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13489 rm.GetCode());
13490 AdvanceIT();
13491 return;
13492 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013493 } else {
13494 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013495 if (cond.IsNotNever() &&
13496 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013497 EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13498 rn.GetCode() | (rm.GetCode() << 8));
13499 return;
13500 }
13501 }
13502 Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
13503}
13504
13505void Assembler::usada8(
13506 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013507 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013508 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013509 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013510 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013511 if (!ra.Is(pc) &&
13512 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013513 EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13514 rm.GetCode() | (ra.GetCode() << 12));
13515 AdvanceIT();
13516 return;
13517 }
13518 } else {
13519 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013520 if (cond.IsNotNever() && !ra.Is(pc) &&
13521 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013522 EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13523 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
13524 return;
13525 }
13526 }
13527 Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
13528}
13529
13530void Assembler::usat(Condition cond,
13531 Register rd,
13532 uint32_t imm,
13533 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013534 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013535 CheckIT(cond);
13536 if (operand.IsImmediateShiftedRegister()) {
13537 Register rn = operand.GetBaseRegister();
13538 Shift shift = operand.GetShift();
13539 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013540 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013541 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013542 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31) &&
13543 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013544 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13545 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13546 ((amount & 0x1c) << 10));
13547 AdvanceIT();
13548 return;
13549 }
13550 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013551 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) &&
13552 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013553 EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
13554 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13555 ((amount & 0x1c) << 10));
13556 AdvanceIT();
13557 return;
13558 }
13559 } else {
13560 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
13561 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013562 cond.IsNotNever() &&
13563 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013564 uint32_t amount_ = amount % 32;
13565 EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
13566 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13567 (amount_ << 7));
13568 return;
13569 }
13570 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013571 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever() &&
13572 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013573 EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
13574 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13575 (amount << 7));
13576 return;
13577 }
13578 }
13579 }
13580 Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
13581}
13582
13583void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013584 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013585 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013586 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013587 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013588 if ((imm <= 15) && ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013589 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13590 (rn.GetCode() << 16));
13591 AdvanceIT();
13592 return;
13593 }
13594 } else {
13595 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013596 if ((imm <= 15) && cond.IsNotNever() &&
13597 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013598 EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13599 (imm << 16) | rn.GetCode());
13600 return;
13601 }
13602 }
13603 Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
13604}
13605
13606void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013607 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013608 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013609 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013610 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013611 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13612 EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13613 rm.GetCode());
13614 AdvanceIT();
13615 return;
13616 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013617 } else {
13618 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013619 if (cond.IsNotNever() &&
13620 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013621 EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13622 (rn.GetCode() << 16) | rm.GetCode());
13623 return;
13624 }
13625 }
13626 Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
13627}
13628
13629void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013630 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013631 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013632 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013633 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013634 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13635 EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13636 rm.GetCode());
13637 AdvanceIT();
13638 return;
13639 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013640 } else {
13641 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013642 if (cond.IsNotNever() &&
13643 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013644 EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13645 (rn.GetCode() << 16) | rm.GetCode());
13646 return;
13647 }
13648 }
13649 Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
13650}
13651
13652void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013653 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013654 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013655 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013656 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013657 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13658 EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13659 rm.GetCode());
13660 AdvanceIT();
13661 return;
13662 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013663 } else {
13664 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013665 if (cond.IsNotNever() &&
13666 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013667 EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13668 (rn.GetCode() << 16) | rm.GetCode());
13669 return;
13670 }
13671 }
13672 Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
13673}
13674
13675void Assembler::uxtab(Condition cond,
13676 Register rd,
13677 Register rn,
13678 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013679 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013680 CheckIT(cond);
13681 if (operand.IsImmediateShiftedRegister()) {
13682 Register rm = operand.GetBaseRegister();
13683 Shift shift = operand.GetShift();
13684 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013685 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013686 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13687 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013688 ((amount % 8) == 0) && !rn.Is(pc) &&
13689 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013690 uint32_t amount_ = amount / 8;
13691 EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13692 rm.GetCode() | (amount_ << 4));
13693 AdvanceIT();
13694 return;
13695 }
13696 } else {
13697 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13698 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013699 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13700 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013701 uint32_t amount_ = amount / 8;
13702 EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
13703 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13704 (amount_ << 10));
13705 return;
13706 }
13707 }
13708 }
13709 Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
13710}
13711
13712void Assembler::uxtab16(Condition cond,
13713 Register rd,
13714 Register rn,
13715 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013716 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013717 CheckIT(cond);
13718 if (operand.IsImmediateShiftedRegister()) {
13719 Register rm = operand.GetBaseRegister();
13720 Shift shift = operand.GetShift();
13721 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013722 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013723 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13724 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013725 ((amount % 8) == 0) && !rn.Is(pc) &&
13726 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013727 uint32_t amount_ = amount / 8;
13728 EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13729 rm.GetCode() | (amount_ << 4));
13730 AdvanceIT();
13731 return;
13732 }
13733 } else {
13734 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13735 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013736 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13737 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013738 uint32_t amount_ = amount / 8;
13739 EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
13740 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13741 (amount_ << 10));
13742 return;
13743 }
13744 }
13745 }
13746 Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
13747}
13748
13749void Assembler::uxtah(Condition cond,
13750 Register rd,
13751 Register rn,
13752 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013753 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013754 CheckIT(cond);
13755 if (operand.IsImmediateShiftedRegister()) {
13756 Register rm = operand.GetBaseRegister();
13757 Shift shift = operand.GetShift();
13758 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013759 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013760 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13761 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013762 ((amount % 8) == 0) && !rn.Is(pc) &&
13763 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013764 uint32_t amount_ = amount / 8;
13765 EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13766 rm.GetCode() | (amount_ << 4));
13767 AdvanceIT();
13768 return;
13769 }
13770 } else {
13771 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13772 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013773 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13774 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013775 uint32_t amount_ = amount / 8;
13776 EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
13777 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13778 (amount_ << 10));
13779 return;
13780 }
13781 }
13782 }
13783 Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
13784}
13785
13786void Assembler::uxtb(Condition cond,
13787 EncodingSize size,
13788 Register rd,
13789 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013790 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013791 CheckIT(cond);
13792 if (operand.IsImmediateShiftedRegister()) {
13793 Register rm = operand.GetBaseRegister();
13794 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013795 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013796 // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
13797 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13798 EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
13799 AdvanceIT();
13800 return;
13801 }
13802 }
13803 }
13804 Shift shift = operand.GetShift();
13805 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013806 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013807 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13808 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013809 (amount <= 24) && ((amount % 8) == 0) &&
13810 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013811 uint32_t amount_ = amount / 8;
13812 EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13813 (amount_ << 4));
13814 AdvanceIT();
13815 return;
13816 }
13817 } else {
13818 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13819 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013820 ((amount % 8) == 0) && cond.IsNotNever() &&
13821 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013822 uint32_t amount_ = amount / 8;
13823 EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
13824 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13825 return;
13826 }
13827 }
13828 }
13829 Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
13830}
13831
13832void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013833 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013834 CheckIT(cond);
13835 if (operand.IsImmediateShiftedRegister()) {
13836 Register rm = operand.GetBaseRegister();
13837 Shift shift = operand.GetShift();
13838 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013839 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013840 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
13841 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013842 ((amount % 8) == 0) &&
13843 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013844 uint32_t amount_ = amount / 8;
13845 EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13846 (amount_ << 4));
13847 AdvanceIT();
13848 return;
13849 }
13850 } else {
13851 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13852 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013853 ((amount % 8) == 0) && cond.IsNotNever() &&
13854 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013855 uint32_t amount_ = amount / 8;
13856 EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
13857 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13858 return;
13859 }
13860 }
13861 }
13862 Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
13863}
13864
13865void Assembler::uxth(Condition cond,
13866 EncodingSize size,
13867 Register rd,
13868 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013869 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013870 CheckIT(cond);
13871 if (operand.IsImmediateShiftedRegister()) {
13872 Register rm = operand.GetBaseRegister();
13873 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013874 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013875 // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
13876 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13877 EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
13878 AdvanceIT();
13879 return;
13880 }
13881 }
13882 }
13883 Shift shift = operand.GetShift();
13884 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013885 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013886 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13887 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013888 (amount <= 24) && ((amount % 8) == 0) &&
13889 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013890 uint32_t amount_ = amount / 8;
13891 EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13892 (amount_ << 4));
13893 AdvanceIT();
13894 return;
13895 }
13896 } else {
13897 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13898 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013899 ((amount % 8) == 0) && cond.IsNotNever() &&
13900 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013901 uint32_t amount_ = amount / 8;
13902 EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
13903 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13904 return;
13905 }
13906 }
13907 }
13908 Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
13909}
13910
13911void Assembler::vaba(
13912 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013913 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013914 CheckIT(cond);
13915 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013916 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013917 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
13918 if (encoded_dt.IsValid()) {
13919 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13920 EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13921 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13922 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13923 AdvanceIT();
13924 return;
13925 }
13926 }
13927 } else {
13928 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
13929 if (encoded_dt.IsValid()) {
13930 if (cond.Is(al)) {
13931 EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13932 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13933 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13934 return;
13935 }
13936 }
13937 }
13938 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13939}
13940
13941void Assembler::vaba(
13942 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013943 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013944 CheckIT(cond);
13945 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013946 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013947 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
13948 if (encoded_dt.IsValid()) {
13949 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13950 EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13951 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13952 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13953 AdvanceIT();
13954 return;
13955 }
13956 }
13957 } else {
13958 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
13959 if (encoded_dt.IsValid()) {
13960 if (cond.Is(al)) {
13961 EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13962 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13963 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13964 return;
13965 }
13966 }
13967 }
13968 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13969}
13970
13971void Assembler::vabal(
13972 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013973 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013974 CheckIT(cond);
13975 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013976 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013977 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13978 if (encoded_dt.IsValid()) {
13979 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13980 EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13981 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13982 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13983 AdvanceIT();
13984 return;
13985 }
13986 }
13987 } else {
13988 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13989 if (encoded_dt.IsValid()) {
13990 if (cond.Is(al)) {
13991 EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13992 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13993 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13994 return;
13995 }
13996 }
13997 }
13998 Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
13999}
14000
14001void Assembler::vabd(
14002 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014003 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014004 CheckIT(cond);
14005 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014006 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014007 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14008 if (dt.Is(F32)) {
14009 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14010 EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14011 rm.Encode(5, 0));
14012 AdvanceIT();
14013 return;
14014 }
14015 }
14016 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14017 if (encoded_dt.IsValid()) {
14018 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14019 EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14020 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14021 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14022 AdvanceIT();
14023 return;
14024 }
14025 }
14026 } else {
14027 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14028 if (dt.Is(F32)) {
14029 if (cond.Is(al)) {
14030 EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14031 rm.Encode(5, 0));
14032 return;
14033 }
14034 }
14035 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14036 if (encoded_dt.IsValid()) {
14037 if (cond.Is(al)) {
14038 EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14039 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14040 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14041 return;
14042 }
14043 }
14044 }
14045 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14046}
14047
14048void Assembler::vabd(
14049 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014050 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014051 CheckIT(cond);
14052 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014053 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014054 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14055 if (dt.Is(F32)) {
14056 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14057 EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14058 rm.Encode(5, 0));
14059 AdvanceIT();
14060 return;
14061 }
14062 }
14063 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14064 if (encoded_dt.IsValid()) {
14065 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14066 EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14067 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14068 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14069 AdvanceIT();
14070 return;
14071 }
14072 }
14073 } else {
14074 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14075 if (dt.Is(F32)) {
14076 if (cond.Is(al)) {
14077 EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14078 rm.Encode(5, 0));
14079 return;
14080 }
14081 }
14082 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14083 if (encoded_dt.IsValid()) {
14084 if (cond.Is(al)) {
14085 EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14086 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14087 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14088 return;
14089 }
14090 }
14091 }
14092 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14093}
14094
14095void Assembler::vabdl(
14096 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014097 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014098 CheckIT(cond);
14099 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014100 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014101 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14102 if (encoded_dt.IsValid()) {
14103 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14104 EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14105 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14106 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14107 AdvanceIT();
14108 return;
14109 }
14110 }
14111 } else {
14112 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14113 if (encoded_dt.IsValid()) {
14114 if (cond.Is(al)) {
14115 EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14116 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14117 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14118 return;
14119 }
14120 }
14121 }
14122 Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
14123}
14124
14125void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014126 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014127 CheckIT(cond);
14128 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014129 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014130 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14131 if (encoded_dt.IsValid()) {
14132 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14133 EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14134 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14135 rd.Encode(22, 12) | rm.Encode(5, 0));
14136 AdvanceIT();
14137 return;
14138 }
14139 }
14140 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
14141 if (dt.Is(F64)) {
14142 EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14143 AdvanceIT();
14144 return;
14145 }
14146 } else {
14147 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14148 if (encoded_dt.IsValid()) {
14149 if (cond.Is(al)) {
14150 EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14151 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14152 rd.Encode(22, 12) | rm.Encode(5, 0));
14153 return;
14154 }
14155 }
14156 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
14157 if (dt.Is(F64) && cond.IsNotNever()) {
14158 EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14159 rm.Encode(5, 0));
14160 return;
14161 }
14162 }
14163 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14164}
14165
14166void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014167 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014168 CheckIT(cond);
14169 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014170 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014171 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14172 if (encoded_dt.IsValid()) {
14173 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14174 EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14175 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14176 rd.Encode(22, 12) | rm.Encode(5, 0));
14177 AdvanceIT();
14178 return;
14179 }
14180 }
14181 } else {
14182 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14183 if (encoded_dt.IsValid()) {
14184 if (cond.Is(al)) {
14185 EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14186 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14187 rd.Encode(22, 12) | rm.Encode(5, 0));
14188 return;
14189 }
14190 }
14191 }
14192 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14193}
14194
14195void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014196 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014197 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014198 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014199 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
14200 if (dt.Is(F32)) {
14201 EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14202 AdvanceIT();
14203 return;
14204 }
14205 } else {
14206 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
14207 if (dt.Is(F32) && cond.IsNotNever()) {
14208 EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14209 rm.Encode(5, 0));
14210 return;
14211 }
14212 }
14213 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14214}
14215
14216void Assembler::vacge(
14217 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014218 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014219 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014220 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014221 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14222 if (dt.Is(F32)) {
14223 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14224 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14225 rm.Encode(5, 0));
14226 AdvanceIT();
14227 return;
14228 }
14229 }
14230 } else {
14231 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14232 if (dt.Is(F32)) {
14233 if (cond.Is(al)) {
14234 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14235 rm.Encode(5, 0));
14236 return;
14237 }
14238 }
14239 }
14240 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14241}
14242
14243void Assembler::vacge(
14244 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014245 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014246 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014247 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014248 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14249 if (dt.Is(F32)) {
14250 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14251 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14252 rm.Encode(5, 0));
14253 AdvanceIT();
14254 return;
14255 }
14256 }
14257 } else {
14258 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14259 if (dt.Is(F32)) {
14260 if (cond.Is(al)) {
14261 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14262 rm.Encode(5, 0));
14263 return;
14264 }
14265 }
14266 }
14267 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14268}
14269
14270void Assembler::vacgt(
14271 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014272 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014273 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014274 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014275 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14276 if (dt.Is(F32)) {
14277 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14278 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14279 rm.Encode(5, 0));
14280 AdvanceIT();
14281 return;
14282 }
14283 }
14284 } else {
14285 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14286 if (dt.Is(F32)) {
14287 if (cond.Is(al)) {
14288 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14289 rm.Encode(5, 0));
14290 return;
14291 }
14292 }
14293 }
14294 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14295}
14296
14297void Assembler::vacgt(
14298 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014299 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014300 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014301 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014302 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14303 if (dt.Is(F32)) {
14304 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14305 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14306 rm.Encode(5, 0));
14307 AdvanceIT();
14308 return;
14309 }
14310 }
14311 } else {
14312 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14313 if (dt.Is(F32)) {
14314 if (cond.Is(al)) {
14315 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14316 rm.Encode(5, 0));
14317 return;
14318 }
14319 }
14320 }
14321 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14322}
14323
14324void Assembler::vacle(
14325 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014326 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014327 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014328 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014329 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14330 if (dt.Is(F32)) {
14331 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14332 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14333 rm.Encode(5, 0));
14334 AdvanceIT();
14335 return;
14336 }
14337 }
14338 } else {
14339 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14340 if (dt.Is(F32)) {
14341 if (cond.Is(al)) {
14342 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14343 rm.Encode(5, 0));
14344 return;
14345 }
14346 }
14347 }
14348 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14349}
14350
14351void Assembler::vacle(
14352 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014353 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014354 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014355 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014356 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14357 if (dt.Is(F32)) {
14358 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14359 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14360 rm.Encode(5, 0));
14361 AdvanceIT();
14362 return;
14363 }
14364 }
14365 } else {
14366 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14367 if (dt.Is(F32)) {
14368 if (cond.Is(al)) {
14369 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14370 rm.Encode(5, 0));
14371 return;
14372 }
14373 }
14374 }
14375 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14376}
14377
14378void Assembler::vaclt(
14379 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014380 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014381 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014382 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014383 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14384 if (dt.Is(F32)) {
14385 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14386 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14387 rm.Encode(5, 0));
14388 AdvanceIT();
14389 return;
14390 }
14391 }
14392 } else {
14393 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14394 if (dt.Is(F32)) {
14395 if (cond.Is(al)) {
14396 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14397 rm.Encode(5, 0));
14398 return;
14399 }
14400 }
14401 }
14402 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14403}
14404
14405void Assembler::vaclt(
14406 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014407 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014408 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014409 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014410 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14411 if (dt.Is(F32)) {
14412 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14413 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14414 rm.Encode(5, 0));
14415 AdvanceIT();
14416 return;
14417 }
14418 }
14419 } else {
14420 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14421 if (dt.Is(F32)) {
14422 if (cond.Is(al)) {
14423 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14424 rm.Encode(5, 0));
14425 return;
14426 }
14427 }
14428 }
14429 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14430}
14431
14432void Assembler::vadd(
14433 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014434 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014435 CheckIT(cond);
14436 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014437 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014438 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14439 if (dt.Is(F32)) {
14440 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14441 EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14442 rm.Encode(5, 0));
14443 AdvanceIT();
14444 return;
14445 }
14446 }
14447 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
14448 if (dt.Is(F64)) {
14449 EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14450 rm.Encode(5, 0));
14451 AdvanceIT();
14452 return;
14453 }
14454 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14455 if (encoded_dt.IsValid()) {
14456 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14457 EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
14458 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14459 AdvanceIT();
14460 return;
14461 }
14462 }
14463 } else {
14464 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14465 if (dt.Is(F32)) {
14466 if (cond.Is(al)) {
14467 EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14468 rm.Encode(5, 0));
14469 return;
14470 }
14471 }
14472 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
14473 if (dt.Is(F64) && cond.IsNotNever()) {
14474 EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14475 rn.Encode(7, 16) | rm.Encode(5, 0));
14476 return;
14477 }
14478 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14479 if (encoded_dt.IsValid()) {
14480 if (cond.Is(al)) {
14481 EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
14482 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14483 return;
14484 }
14485 }
14486 }
14487 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14488}
14489
14490void Assembler::vadd(
14491 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014493 CheckIT(cond);
14494 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014495 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014496 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14497 if (dt.Is(F32)) {
14498 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14499 EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14500 rm.Encode(5, 0));
14501 AdvanceIT();
14502 return;
14503 }
14504 }
14505 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14506 if (encoded_dt.IsValid()) {
14507 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14508 EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
14509 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14510 AdvanceIT();
14511 return;
14512 }
14513 }
14514 } else {
14515 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14516 if (dt.Is(F32)) {
14517 if (cond.Is(al)) {
14518 EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14519 rm.Encode(5, 0));
14520 return;
14521 }
14522 }
14523 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14524 if (encoded_dt.IsValid()) {
14525 if (cond.Is(al)) {
14526 EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
14527 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14528 return;
14529 }
14530 }
14531 }
14532 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14533}
14534
14535void Assembler::vadd(
14536 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014537 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014538 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014539 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014540 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
14541 if (dt.Is(F32)) {
14542 EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14543 rm.Encode(5, 0));
14544 AdvanceIT();
14545 return;
14546 }
14547 } else {
14548 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
14549 if (dt.Is(F32) && cond.IsNotNever()) {
14550 EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14551 rn.Encode(7, 16) | rm.Encode(5, 0));
14552 return;
14553 }
14554 }
14555 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14556}
14557
14558void Assembler::vaddhn(
14559 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014560 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014561 CheckIT(cond);
14562 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014563 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014564 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
14565 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14566 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14567 EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
14568 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14569 AdvanceIT();
14570 return;
14571 }
14572 }
14573 } else {
14574 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
14575 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14576 if (cond.Is(al)) {
14577 EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
14578 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14579 return;
14580 }
14581 }
14582 }
14583 Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
14584}
14585
14586void Assembler::vaddl(
14587 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014588 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014589 CheckIT(cond);
14590 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014591 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014592 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14593 if (encoded_dt.IsValid()) {
14594 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14595 EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14596 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14597 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14598 AdvanceIT();
14599 return;
14600 }
14601 }
14602 } else {
14603 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14604 if (encoded_dt.IsValid()) {
14605 if (cond.Is(al)) {
14606 EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14607 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14608 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14609 return;
14610 }
14611 }
14612 }
14613 Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
14614}
14615
14616void Assembler::vaddw(
14617 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014618 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014619 CheckIT(cond);
14620 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014621 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014622 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
14623 if (encoded_dt.IsValid()) {
14624 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14625 EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14626 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14627 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14628 AdvanceIT();
14629 return;
14630 }
14631 }
14632 } else {
14633 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
14634 if (encoded_dt.IsValid()) {
14635 if (cond.Is(al)) {
14636 EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14637 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14638 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14639 return;
14640 }
14641 }
14642 }
14643 Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
14644}
14645
14646void Assembler::vand(Condition cond,
14647 DataType dt,
14648 DRegister rd,
14649 DRegister rn,
14650 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014651 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014652 CheckIT(cond);
14653 if (operand.IsImmediate()) {
14654 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014655 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014656 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14657 if (encoded_dt.IsValid() && rd.Is(rn)) {
14658 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14659 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14660 rd.Encode(22, 12) |
14661 (encoded_dt.GetEncodedImmediate() & 0xf) |
14662 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14663 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14664 AdvanceIT();
14665 return;
14666 }
14667 }
14668 } else {
14669 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14670 if (encoded_dt.IsValid() && rd.Is(rn)) {
14671 if (cond.Is(al)) {
14672 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14673 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14674 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14675 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14676 return;
14677 }
14678 }
14679 }
14680 }
14681 if (operand.IsRegister()) {
14682 DRegister rm = operand.GetRegister();
14683 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014684 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014685 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14686 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14687 EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14688 rm.Encode(5, 0));
14689 AdvanceIT();
14690 return;
14691 }
14692 } else {
14693 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14694 if (cond.Is(al)) {
14695 EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14696 rm.Encode(5, 0));
14697 return;
14698 }
14699 }
14700 }
14701 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14702}
14703
14704void Assembler::vand(Condition cond,
14705 DataType dt,
14706 QRegister rd,
14707 QRegister rn,
14708 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014709 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014710 CheckIT(cond);
14711 if (operand.IsImmediate()) {
14712 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014713 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014714 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14715 if (encoded_dt.IsValid() && rd.Is(rn)) {
14716 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14717 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14718 rd.Encode(22, 12) |
14719 (encoded_dt.GetEncodedImmediate() & 0xf) |
14720 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14721 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14722 AdvanceIT();
14723 return;
14724 }
14725 }
14726 } else {
14727 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14728 if (encoded_dt.IsValid() && rd.Is(rn)) {
14729 if (cond.Is(al)) {
14730 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14731 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14732 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14733 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14734 return;
14735 }
14736 }
14737 }
14738 }
14739 if (operand.IsRegister()) {
14740 QRegister rm = operand.GetRegister();
14741 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014743 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14744 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14745 EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14746 rm.Encode(5, 0));
14747 AdvanceIT();
14748 return;
14749 }
14750 } else {
14751 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14752 if (cond.Is(al)) {
14753 EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14754 rm.Encode(5, 0));
14755 return;
14756 }
14757 }
14758 }
14759 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14760}
14761
14762void Assembler::vbic(Condition cond,
14763 DataType dt,
14764 DRegister rd,
14765 DRegister rn,
14766 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014767 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014768 CheckIT(cond);
14769 if (operand.IsImmediate()) {
14770 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014771 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014772 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14773 if (encoded_dt.IsValid() && rd.Is(rn)) {
14774 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14775 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14776 rd.Encode(22, 12) |
14777 (encoded_dt.GetEncodedImmediate() & 0xf) |
14778 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14779 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14780 AdvanceIT();
14781 return;
14782 }
14783 }
14784 } else {
14785 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14786 if (encoded_dt.IsValid() && rd.Is(rn)) {
14787 if (cond.Is(al)) {
14788 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14789 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14790 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14791 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14792 return;
14793 }
14794 }
14795 }
14796 }
14797 if (operand.IsRegister()) {
14798 DRegister rm = operand.GetRegister();
14799 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014800 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014801 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14802 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14803 EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14804 rm.Encode(5, 0));
14805 AdvanceIT();
14806 return;
14807 }
14808 } else {
14809 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14810 if (cond.Is(al)) {
14811 EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14812 rm.Encode(5, 0));
14813 return;
14814 }
14815 }
14816 }
14817 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14818}
14819
14820void Assembler::vbic(Condition cond,
14821 DataType dt,
14822 QRegister rd,
14823 QRegister rn,
14824 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014825 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014826 CheckIT(cond);
14827 if (operand.IsImmediate()) {
14828 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014829 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014830 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14831 if (encoded_dt.IsValid() && rd.Is(rn)) {
14832 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14833 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14834 rd.Encode(22, 12) |
14835 (encoded_dt.GetEncodedImmediate() & 0xf) |
14836 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14837 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14838 AdvanceIT();
14839 return;
14840 }
14841 }
14842 } else {
14843 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14844 if (encoded_dt.IsValid() && rd.Is(rn)) {
14845 if (cond.Is(al)) {
14846 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14847 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14848 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14849 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14850 return;
14851 }
14852 }
14853 }
14854 }
14855 if (operand.IsRegister()) {
14856 QRegister rm = operand.GetRegister();
14857 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014858 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014859 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14860 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14861 EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14862 rm.Encode(5, 0));
14863 AdvanceIT();
14864 return;
14865 }
14866 } else {
14867 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14868 if (cond.Is(al)) {
14869 EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14870 rm.Encode(5, 0));
14871 return;
14872 }
14873 }
14874 }
14875 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14876}
14877
14878void Assembler::vbif(
14879 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014880 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014881 CheckIT(cond);
14882 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014883 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014884 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14885 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14886 EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14887 rm.Encode(5, 0));
14888 AdvanceIT();
14889 return;
14890 }
14891 } else {
14892 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14893 if (cond.Is(al)) {
14894 EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14895 rm.Encode(5, 0));
14896 return;
14897 }
14898 }
14899 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14900}
14901
14902void Assembler::vbif(
14903 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014904 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014905 CheckIT(cond);
14906 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014907 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014908 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14910 EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14911 rm.Encode(5, 0));
14912 AdvanceIT();
14913 return;
14914 }
14915 } else {
14916 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14917 if (cond.Is(al)) {
14918 EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14919 rm.Encode(5, 0));
14920 return;
14921 }
14922 }
14923 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14924}
14925
14926void Assembler::vbit(
14927 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014928 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014929 CheckIT(cond);
14930 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014931 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014932 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14933 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14934 EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14935 rm.Encode(5, 0));
14936 AdvanceIT();
14937 return;
14938 }
14939 } else {
14940 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14941 if (cond.Is(al)) {
14942 EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14943 rm.Encode(5, 0));
14944 return;
14945 }
14946 }
14947 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14948}
14949
14950void Assembler::vbit(
14951 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014952 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014953 CheckIT(cond);
14954 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014955 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014956 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14957 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14958 EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14959 rm.Encode(5, 0));
14960 AdvanceIT();
14961 return;
14962 }
14963 } else {
14964 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14965 if (cond.Is(al)) {
14966 EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14967 rm.Encode(5, 0));
14968 return;
14969 }
14970 }
14971 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14972}
14973
14974void Assembler::vbsl(
14975 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014976 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014977 CheckIT(cond);
14978 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014979 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014980 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14981 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14982 EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14983 rm.Encode(5, 0));
14984 AdvanceIT();
14985 return;
14986 }
14987 } else {
14988 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14989 if (cond.Is(al)) {
14990 EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14991 rm.Encode(5, 0));
14992 return;
14993 }
14994 }
14995 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14996}
14997
14998void Assembler::vbsl(
14999 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015000 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015001 CheckIT(cond);
15002 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015003 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015004 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
15005 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15006 EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15007 rm.Encode(5, 0));
15008 AdvanceIT();
15009 return;
15010 }
15011 } else {
15012 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
15013 if (cond.Is(al)) {
15014 EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15015 rm.Encode(5, 0));
15016 return;
15017 }
15018 }
15019 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
15020}
15021
15022void Assembler::vceq(Condition cond,
15023 DataType dt,
15024 DRegister rd,
15025 DRegister rm,
15026 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015027 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015028 CheckIT(cond);
15029 if (operand.IsImmediate()) {
15030 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15031 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15032 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015033 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015034 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15035 if (encoded_dt.IsValid() && (imm == 0)) {
15036 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15037 EmitT32_32(0xffb10100U |
15038 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15039 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15040 rd.Encode(22, 12) | rm.Encode(5, 0));
15041 AdvanceIT();
15042 return;
15043 }
15044 }
15045 } else {
15046 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15047 if (encoded_dt.IsValid() && (imm == 0)) {
15048 if (cond.Is(al)) {
15049 EmitA32(0xf3b10100U |
15050 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15051 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15052 rd.Encode(22, 12) | rm.Encode(5, 0));
15053 return;
15054 }
15055 }
15056 }
15057 }
15058 }
15059 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15060}
15061
15062void Assembler::vceq(Condition cond,
15063 DataType dt,
15064 QRegister rd,
15065 QRegister rm,
15066 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015067 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015068 CheckIT(cond);
15069 if (operand.IsImmediate()) {
15070 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15071 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15072 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015074 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15075 if (encoded_dt.IsValid() && (imm == 0)) {
15076 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15077 EmitT32_32(0xffb10140U |
15078 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15079 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15080 rd.Encode(22, 12) | rm.Encode(5, 0));
15081 AdvanceIT();
15082 return;
15083 }
15084 }
15085 } else {
15086 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15087 if (encoded_dt.IsValid() && (imm == 0)) {
15088 if (cond.Is(al)) {
15089 EmitA32(0xf3b10140U |
15090 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15091 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15092 rd.Encode(22, 12) | rm.Encode(5, 0));
15093 return;
15094 }
15095 }
15096 }
15097 }
15098 }
15099 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15100}
15101
15102void Assembler::vceq(
15103 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015104 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015105 CheckIT(cond);
15106 Dt_size_4 encoded_dt(dt);
15107 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015108 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015109 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15110 if (encoded_dt.IsValid()) {
15111 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15112 EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
15113 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15114 AdvanceIT();
15115 return;
15116 }
15117 }
15118 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
15119 if (encoded_dt_2.IsValid()) {
15120 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15121 EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15122 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15123 AdvanceIT();
15124 return;
15125 }
15126 }
15127 } else {
15128 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15129 if (encoded_dt.IsValid()) {
15130 if (cond.Is(al)) {
15131 EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
15132 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15133 return;
15134 }
15135 }
15136 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
15137 if (encoded_dt_2.IsValid()) {
15138 if (cond.Is(al)) {
15139 EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15140 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15141 return;
15142 }
15143 }
15144 }
15145 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15146}
15147
15148void Assembler::vceq(
15149 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015150 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015151 CheckIT(cond);
15152 Dt_size_4 encoded_dt(dt);
15153 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015154 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015155 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15156 if (encoded_dt.IsValid()) {
15157 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15158 EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
15159 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15160 AdvanceIT();
15161 return;
15162 }
15163 }
15164 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
15165 if (encoded_dt_2.IsValid()) {
15166 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15167 EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15168 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15169 AdvanceIT();
15170 return;
15171 }
15172 }
15173 } else {
15174 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15175 if (encoded_dt.IsValid()) {
15176 if (cond.Is(al)) {
15177 EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
15178 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15179 return;
15180 }
15181 }
15182 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
15183 if (encoded_dt_2.IsValid()) {
15184 if (cond.Is(al)) {
15185 EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15186 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15187 return;
15188 }
15189 }
15190 }
15191 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15192}
15193
15194void Assembler::vcge(Condition cond,
15195 DataType dt,
15196 DRegister rd,
15197 DRegister rm,
15198 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015199 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015200 CheckIT(cond);
15201 if (operand.IsImmediate()) {
15202 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15203 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15204 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015205 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015206 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15207 if (encoded_dt.IsValid() && (imm == 0)) {
15208 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15209 EmitT32_32(0xffb10080U |
15210 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15211 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15212 rd.Encode(22, 12) | rm.Encode(5, 0));
15213 AdvanceIT();
15214 return;
15215 }
15216 }
15217 } else {
15218 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15219 if (encoded_dt.IsValid() && (imm == 0)) {
15220 if (cond.Is(al)) {
15221 EmitA32(0xf3b10080U |
15222 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15223 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15224 rd.Encode(22, 12) | rm.Encode(5, 0));
15225 return;
15226 }
15227 }
15228 }
15229 }
15230 }
15231 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15232}
15233
15234void Assembler::vcge(Condition cond,
15235 DataType dt,
15236 QRegister rd,
15237 QRegister rm,
15238 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015239 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015240 CheckIT(cond);
15241 if (operand.IsImmediate()) {
15242 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15243 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15244 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015245 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015246 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15247 if (encoded_dt.IsValid() && (imm == 0)) {
15248 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15249 EmitT32_32(0xffb100c0U |
15250 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15251 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15252 rd.Encode(22, 12) | rm.Encode(5, 0));
15253 AdvanceIT();
15254 return;
15255 }
15256 }
15257 } else {
15258 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15259 if (encoded_dt.IsValid() && (imm == 0)) {
15260 if (cond.Is(al)) {
15261 EmitA32(0xf3b100c0U |
15262 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15263 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15264 rd.Encode(22, 12) | rm.Encode(5, 0));
15265 return;
15266 }
15267 }
15268 }
15269 }
15270 }
15271 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15272}
15273
15274void Assembler::vcge(
15275 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015276 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015277 CheckIT(cond);
15278 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015279 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015280 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15281 if (encoded_dt.IsValid()) {
15282 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15283 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15284 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015285 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015286 AdvanceIT();
15287 return;
15288 }
15289 }
15290 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15291 if (dt.Is(F32)) {
15292 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15293 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15294 rm.Encode(5, 0));
15295 AdvanceIT();
15296 return;
15297 }
15298 }
15299 } else {
15300 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15301 if (encoded_dt.IsValid()) {
15302 if (cond.Is(al)) {
15303 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15304 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15305 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15306 return;
15307 }
15308 }
15309 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15310 if (dt.Is(F32)) {
15311 if (cond.Is(al)) {
15312 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15313 rm.Encode(5, 0));
15314 return;
15315 }
15316 }
15317 }
15318 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15319}
15320
15321void Assembler::vcge(
15322 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015323 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015324 CheckIT(cond);
15325 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015326 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015327 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15328 if (encoded_dt.IsValid()) {
15329 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15330 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15331 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015332 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015333 AdvanceIT();
15334 return;
15335 }
15336 }
15337 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15338 if (dt.Is(F32)) {
15339 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15340 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15341 rm.Encode(5, 0));
15342 AdvanceIT();
15343 return;
15344 }
15345 }
15346 } else {
15347 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15348 if (encoded_dt.IsValid()) {
15349 if (cond.Is(al)) {
15350 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15351 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15352 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15353 return;
15354 }
15355 }
15356 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15357 if (dt.Is(F32)) {
15358 if (cond.Is(al)) {
15359 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15360 rm.Encode(5, 0));
15361 return;
15362 }
15363 }
15364 }
15365 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15366}
15367
15368void Assembler::vcgt(Condition cond,
15369 DataType dt,
15370 DRegister rd,
15371 DRegister rm,
15372 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015373 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015374 CheckIT(cond);
15375 if (operand.IsImmediate()) {
15376 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15377 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15378 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015379 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015380 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15381 if (encoded_dt.IsValid() && (imm == 0)) {
15382 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15383 EmitT32_32(0xffb10000U |
15384 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15385 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15386 rd.Encode(22, 12) | rm.Encode(5, 0));
15387 AdvanceIT();
15388 return;
15389 }
15390 }
15391 } else {
15392 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15393 if (encoded_dt.IsValid() && (imm == 0)) {
15394 if (cond.Is(al)) {
15395 EmitA32(0xf3b10000U |
15396 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15397 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15398 rd.Encode(22, 12) | rm.Encode(5, 0));
15399 return;
15400 }
15401 }
15402 }
15403 }
15404 }
15405 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15406}
15407
15408void Assembler::vcgt(Condition cond,
15409 DataType dt,
15410 QRegister rd,
15411 QRegister rm,
15412 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015413 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015414 CheckIT(cond);
15415 if (operand.IsImmediate()) {
15416 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15417 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15418 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015419 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015420 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15421 if (encoded_dt.IsValid() && (imm == 0)) {
15422 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15423 EmitT32_32(0xffb10040U |
15424 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15425 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15426 rd.Encode(22, 12) | rm.Encode(5, 0));
15427 AdvanceIT();
15428 return;
15429 }
15430 }
15431 } else {
15432 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15433 if (encoded_dt.IsValid() && (imm == 0)) {
15434 if (cond.Is(al)) {
15435 EmitA32(0xf3b10040U |
15436 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15437 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15438 rd.Encode(22, 12) | rm.Encode(5, 0));
15439 return;
15440 }
15441 }
15442 }
15443 }
15444 }
15445 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15446}
15447
15448void Assembler::vcgt(
15449 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015450 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015451 CheckIT(cond);
15452 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015453 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015454 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15455 if (encoded_dt.IsValid()) {
15456 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15457 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15458 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015459 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015460 AdvanceIT();
15461 return;
15462 }
15463 }
15464 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15465 if (dt.Is(F32)) {
15466 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15467 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15468 rm.Encode(5, 0));
15469 AdvanceIT();
15470 return;
15471 }
15472 }
15473 } else {
15474 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15475 if (encoded_dt.IsValid()) {
15476 if (cond.Is(al)) {
15477 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15478 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15479 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15480 return;
15481 }
15482 }
15483 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15484 if (dt.Is(F32)) {
15485 if (cond.Is(al)) {
15486 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15487 rm.Encode(5, 0));
15488 return;
15489 }
15490 }
15491 }
15492 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15493}
15494
15495void Assembler::vcgt(
15496 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015497 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015498 CheckIT(cond);
15499 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015500 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015501 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15502 if (encoded_dt.IsValid()) {
15503 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15504 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15505 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015506 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015507 AdvanceIT();
15508 return;
15509 }
15510 }
15511 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15512 if (dt.Is(F32)) {
15513 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15514 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15515 rm.Encode(5, 0));
15516 AdvanceIT();
15517 return;
15518 }
15519 }
15520 } else {
15521 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15522 if (encoded_dt.IsValid()) {
15523 if (cond.Is(al)) {
15524 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15525 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15526 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15527 return;
15528 }
15529 }
15530 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15531 if (dt.Is(F32)) {
15532 if (cond.Is(al)) {
15533 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15534 rm.Encode(5, 0));
15535 return;
15536 }
15537 }
15538 }
15539 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15540}
15541
15542void Assembler::vcle(Condition cond,
15543 DataType dt,
15544 DRegister rd,
15545 DRegister rm,
15546 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015547 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015548 CheckIT(cond);
15549 if (operand.IsImmediate()) {
15550 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15551 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15552 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015553 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015554 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15555 if (encoded_dt.IsValid() && (imm == 0)) {
15556 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15557 EmitT32_32(0xffb10180U |
15558 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15559 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15560 rd.Encode(22, 12) | rm.Encode(5, 0));
15561 AdvanceIT();
15562 return;
15563 }
15564 }
15565 } else {
15566 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15567 if (encoded_dt.IsValid() && (imm == 0)) {
15568 if (cond.Is(al)) {
15569 EmitA32(0xf3b10180U |
15570 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15571 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15572 rd.Encode(22, 12) | rm.Encode(5, 0));
15573 return;
15574 }
15575 }
15576 }
15577 }
15578 }
15579 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15580}
15581
15582void Assembler::vcle(Condition cond,
15583 DataType dt,
15584 QRegister rd,
15585 QRegister rm,
15586 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015587 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015588 CheckIT(cond);
15589 if (operand.IsImmediate()) {
15590 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15591 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15592 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015593 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015594 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15595 if (encoded_dt.IsValid() && (imm == 0)) {
15596 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15597 EmitT32_32(0xffb101c0U |
15598 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15599 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15600 rd.Encode(22, 12) | rm.Encode(5, 0));
15601 AdvanceIT();
15602 return;
15603 }
15604 }
15605 } else {
15606 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15607 if (encoded_dt.IsValid() && (imm == 0)) {
15608 if (cond.Is(al)) {
15609 EmitA32(0xf3b101c0U |
15610 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15611 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15612 rd.Encode(22, 12) | rm.Encode(5, 0));
15613 return;
15614 }
15615 }
15616 }
15617 }
15618 }
15619 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15620}
15621
15622void Assembler::vcle(
15623 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015624 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015625 CheckIT(cond);
15626 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015627 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015628 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15629 if (encoded_dt.IsValid()) {
15630 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15631 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15632 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015633 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015634 AdvanceIT();
15635 return;
15636 }
15637 }
15638 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15639 if (dt.Is(F32)) {
15640 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015641 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15642 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015643 AdvanceIT();
15644 return;
15645 }
15646 }
15647 } else {
15648 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15649 if (encoded_dt.IsValid()) {
15650 if (cond.Is(al)) {
15651 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15652 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015653 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015654 return;
15655 }
15656 }
15657 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15658 if (dt.Is(F32)) {
15659 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015660 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15661 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015662 return;
15663 }
15664 }
15665 }
15666 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15667}
15668
15669void Assembler::vcle(
15670 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015671 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015672 CheckIT(cond);
15673 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015674 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015675 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15676 if (encoded_dt.IsValid()) {
15677 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15678 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15679 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015680 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015681 AdvanceIT();
15682 return;
15683 }
15684 }
15685 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15686 if (dt.Is(F32)) {
15687 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015688 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15689 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015690 AdvanceIT();
15691 return;
15692 }
15693 }
15694 } else {
15695 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15696 if (encoded_dt.IsValid()) {
15697 if (cond.Is(al)) {
15698 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15699 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015700 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015701 return;
15702 }
15703 }
15704 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15705 if (dt.Is(F32)) {
15706 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015707 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15708 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015709 return;
15710 }
15711 }
15712 }
15713 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15714}
15715
15716void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015717 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015718 CheckIT(cond);
15719 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015720 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015721 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15722 if (encoded_dt.IsValid()) {
15723 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15724 EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
15725 rd.Encode(22, 12) | rm.Encode(5, 0));
15726 AdvanceIT();
15727 return;
15728 }
15729 }
15730 } else {
15731 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15732 if (encoded_dt.IsValid()) {
15733 if (cond.Is(al)) {
15734 EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
15735 rd.Encode(22, 12) | rm.Encode(5, 0));
15736 return;
15737 }
15738 }
15739 }
15740 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15741}
15742
15743void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015744 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015745 CheckIT(cond);
15746 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015747 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015748 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15749 if (encoded_dt.IsValid()) {
15750 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15751 EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
15752 rd.Encode(22, 12) | rm.Encode(5, 0));
15753 AdvanceIT();
15754 return;
15755 }
15756 }
15757 } else {
15758 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15759 if (encoded_dt.IsValid()) {
15760 if (cond.Is(al)) {
15761 EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
15762 rd.Encode(22, 12) | rm.Encode(5, 0));
15763 return;
15764 }
15765 }
15766 }
15767 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15768}
15769
15770void Assembler::vclt(Condition cond,
15771 DataType dt,
15772 DRegister rd,
15773 DRegister rm,
15774 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015775 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015776 CheckIT(cond);
15777 if (operand.IsImmediate()) {
15778 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15779 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15780 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015781 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015782 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15783 if (encoded_dt.IsValid() && (imm == 0)) {
15784 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15785 EmitT32_32(0xffb10200U |
15786 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15787 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15788 rd.Encode(22, 12) | rm.Encode(5, 0));
15789 AdvanceIT();
15790 return;
15791 }
15792 }
15793 } else {
15794 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15795 if (encoded_dt.IsValid() && (imm == 0)) {
15796 if (cond.Is(al)) {
15797 EmitA32(0xf3b10200U |
15798 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15799 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15800 rd.Encode(22, 12) | rm.Encode(5, 0));
15801 return;
15802 }
15803 }
15804 }
15805 }
15806 }
15807 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15808}
15809
15810void Assembler::vclt(Condition cond,
15811 DataType dt,
15812 QRegister rd,
15813 QRegister rm,
15814 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015815 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015816 CheckIT(cond);
15817 if (operand.IsImmediate()) {
15818 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15819 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15820 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015821 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015822 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15823 if (encoded_dt.IsValid() && (imm == 0)) {
15824 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15825 EmitT32_32(0xffb10240U |
15826 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15827 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15828 rd.Encode(22, 12) | rm.Encode(5, 0));
15829 AdvanceIT();
15830 return;
15831 }
15832 }
15833 } else {
15834 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15835 if (encoded_dt.IsValid() && (imm == 0)) {
15836 if (cond.Is(al)) {
15837 EmitA32(0xf3b10240U |
15838 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15839 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15840 rd.Encode(22, 12) | rm.Encode(5, 0));
15841 return;
15842 }
15843 }
15844 }
15845 }
15846 }
15847 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15848}
15849
15850void Assembler::vclt(
15851 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015852 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015853 CheckIT(cond);
15854 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015855 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015856 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15857 if (encoded_dt.IsValid()) {
15858 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15859 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15860 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015861 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015862 AdvanceIT();
15863 return;
15864 }
15865 }
15866 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15867 if (dt.Is(F32)) {
15868 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015869 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15870 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015871 AdvanceIT();
15872 return;
15873 }
15874 }
15875 } else {
15876 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15877 if (encoded_dt.IsValid()) {
15878 if (cond.Is(al)) {
15879 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15880 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015881 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015882 return;
15883 }
15884 }
15885 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15886 if (dt.Is(F32)) {
15887 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015888 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15889 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015890 return;
15891 }
15892 }
15893 }
15894 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15895}
15896
15897void Assembler::vclt(
15898 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015899 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015900 CheckIT(cond);
15901 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015902 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015903 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15904 if (encoded_dt.IsValid()) {
15905 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15906 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15907 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015908 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015909 AdvanceIT();
15910 return;
15911 }
15912 }
15913 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15914 if (dt.Is(F32)) {
15915 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015916 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15917 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015918 AdvanceIT();
15919 return;
15920 }
15921 }
15922 } else {
15923 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15924 if (encoded_dt.IsValid()) {
15925 if (cond.Is(al)) {
15926 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15927 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015928 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015929 return;
15930 }
15931 }
15932 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15933 if (dt.Is(F32)) {
15934 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015935 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15936 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015937 return;
15938 }
15939 }
15940 }
15941 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15942}
15943
15944void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015945 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015946 CheckIT(cond);
15947 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015948 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015949 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15950 if (encoded_dt.IsValid()) {
15951 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15952 EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
15953 rd.Encode(22, 12) | rm.Encode(5, 0));
15954 AdvanceIT();
15955 return;
15956 }
15957 }
15958 } else {
15959 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15960 if (encoded_dt.IsValid()) {
15961 if (cond.Is(al)) {
15962 EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
15963 rd.Encode(22, 12) | rm.Encode(5, 0));
15964 return;
15965 }
15966 }
15967 }
15968 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15969}
15970
15971void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015972 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015973 CheckIT(cond);
15974 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015975 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015976 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15977 if (encoded_dt.IsValid()) {
15978 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15979 EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
15980 rd.Encode(22, 12) | rm.Encode(5, 0));
15981 AdvanceIT();
15982 return;
15983 }
15984 }
15985 } else {
15986 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15987 if (encoded_dt.IsValid()) {
15988 if (cond.Is(al)) {
15989 EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
15990 rd.Encode(22, 12) | rm.Encode(5, 0));
15991 return;
15992 }
15993 }
15994 }
15995 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15996}
15997
Vincent Belliard07f9e742017-04-21 13:10:07 -070015998void Assembler::vcmp(Condition cond,
15999 DataType dt,
16000 SRegister rd,
16001 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016002 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016003 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016004 if (operand.IsRegister()) {
16005 SRegister rm = operand.GetRegister();
16006 if (IsUsingT32()) {
16007 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16008 if (dt.Is(F32)) {
16009 EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16010 AdvanceIT();
16011 return;
16012 }
16013 } else {
16014 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16015 if (dt.Is(F32) && cond.IsNotNever()) {
16016 EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16017 rm.Encode(5, 0));
16018 return;
16019 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016020 }
16021 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016022 if (operand.IsImmediate()) {
16023 if (IsUsingT32()) {
16024 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16025 if (dt.Is(F32) && (operand.IsFloatZero())) {
16026 EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
16027 AdvanceIT();
16028 return;
16029 }
16030 } else {
16031 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16032 if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16033 EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16034 return;
16035 }
16036 }
16037 }
16038 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016039}
16040
Vincent Belliard07f9e742017-04-21 13:10:07 -070016041void Assembler::vcmp(Condition cond,
16042 DataType dt,
16043 DRegister rd,
16044 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016045 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016046 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016047 if (operand.IsRegister()) {
16048 DRegister rm = operand.GetRegister();
16049 if (IsUsingT32()) {
16050 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16051 if (dt.Is(F64)) {
16052 EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16053 AdvanceIT();
16054 return;
16055 }
16056 } else {
16057 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16058 if (dt.Is(F64) && cond.IsNotNever()) {
16059 EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16060 rm.Encode(5, 0));
16061 return;
16062 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016063 }
16064 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016065 if (operand.IsImmediate()) {
16066 if (IsUsingT32()) {
16067 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16068 if (dt.Is(F64) && (operand.IsFloatZero())) {
16069 EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
16070 AdvanceIT();
16071 return;
16072 }
16073 } else {
16074 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16075 if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16076 EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16077 return;
16078 }
16079 }
16080 }
16081 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016082}
16083
Vincent Belliard07f9e742017-04-21 13:10:07 -070016084void Assembler::vcmpe(Condition cond,
16085 DataType dt,
16086 SRegister rd,
16087 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016088 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016089 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016090 if (operand.IsRegister()) {
16091 SRegister rm = operand.GetRegister();
16092 if (IsUsingT32()) {
16093 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16094 if (dt.Is(F32)) {
16095 EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16096 AdvanceIT();
16097 return;
16098 }
16099 } else {
16100 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16101 if (dt.Is(F32) && cond.IsNotNever()) {
16102 EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16103 rm.Encode(5, 0));
16104 return;
16105 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016106 }
16107 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016108 if (operand.IsImmediate()) {
16109 if (IsUsingT32()) {
16110 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16111 if (dt.Is(F32) && (operand.IsFloatZero())) {
16112 EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
16113 AdvanceIT();
16114 return;
16115 }
16116 } else {
16117 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16118 if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16119 EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16120 return;
16121 }
16122 }
16123 }
16124 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016125}
16126
Vincent Belliard07f9e742017-04-21 13:10:07 -070016127void Assembler::vcmpe(Condition cond,
16128 DataType dt,
16129 DRegister rd,
16130 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016131 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016132 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016133 if (operand.IsRegister()) {
16134 DRegister rm = operand.GetRegister();
16135 if (IsUsingT32()) {
16136 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16137 if (dt.Is(F64)) {
16138 EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16139 AdvanceIT();
16140 return;
16141 }
16142 } else {
16143 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16144 if (dt.Is(F64) && cond.IsNotNever()) {
16145 EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16146 rm.Encode(5, 0));
16147 return;
16148 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016149 }
16150 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016151 if (operand.IsImmediate()) {
16152 if (IsUsingT32()) {
16153 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16154 if (dt.Is(F64) && (operand.IsFloatZero())) {
16155 EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
16156 AdvanceIT();
16157 return;
16158 }
16159 } else {
16160 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16161 if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16162 EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16163 return;
16164 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016165 }
16166 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016167 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016168}
16169
16170void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016171 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016172 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016173 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016174 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
16175 if (dt.Is(Untyped8)) {
16176 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16177 EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16178 AdvanceIT();
16179 return;
16180 }
16181 }
16182 } else {
16183 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
16184 if (dt.Is(Untyped8)) {
16185 if (cond.Is(al)) {
16186 EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16187 return;
16188 }
16189 }
16190 }
16191 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16192}
16193
16194void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016195 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016196 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016197 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016198 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
16199 if (dt.Is(Untyped8)) {
16200 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16201 EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16202 AdvanceIT();
16203 return;
16204 }
16205 }
16206 } else {
16207 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
16208 if (dt.Is(Untyped8)) {
16209 if (cond.Is(al)) {
16210 EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16211 return;
16212 }
16213 }
16214 }
16215 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16216}
16217
16218void Assembler::vcvt(
16219 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016220 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016221 CheckIT(cond);
16222 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016223 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016224 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
16225 if (dt1.Is(F64) && dt2.Is(F32)) {
16226 EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16227 AdvanceIT();
16228 return;
16229 }
16230 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
16231 if (dt1.Is(F64) && encoded_dt.IsValid()) {
16232 EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
16233 rd.Encode(22, 12) | rm.Encode(5, 0));
16234 AdvanceIT();
16235 return;
16236 }
16237 } else {
16238 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
16239 if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
16240 EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16241 rm.Encode(5, 0));
16242 return;
16243 }
16244 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
16245 if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
16246 EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
16247 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16248 rm.Encode(5, 0));
16249 return;
16250 }
16251 }
16252 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16253}
16254
16255void Assembler::vcvt(
16256 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016257 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016258 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016259 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016260 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
16261 if (dt1.Is(F32) && dt2.Is(F64)) {
16262 EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16263 AdvanceIT();
16264 return;
16265 }
16266 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16267 if (dt1.Is(U32) && dt2.Is(F64)) {
16268 EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16269 AdvanceIT();
16270 return;
16271 }
16272 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16273 if (dt1.Is(S32) && dt2.Is(F64)) {
16274 EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16275 AdvanceIT();
16276 return;
16277 }
16278 } else {
16279 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
16280 if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
16281 EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16282 rm.Encode(5, 0));
16283 return;
16284 }
16285 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16286 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16287 EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16288 rm.Encode(5, 0));
16289 return;
16290 }
16291 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16292 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16293 EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16294 rm.Encode(5, 0));
16295 return;
16296 }
16297 }
16298 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16299}
16300
16301void Assembler::vcvt(Condition cond,
16302 DataType dt1,
16303 DataType dt2,
16304 DRegister rd,
16305 DRegister rm,
16306 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016307 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016308 CheckIT(cond);
16309 Dt_op_U_1 encoded_dt(dt1, dt2);
16310 Dt_U_sx_1 encoded_dt_2(dt2);
16311 Dt_U_sx_1 encoded_dt_3(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016312 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016313 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
16314 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16315 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16316 uint32_t fbits_ = 64 - fbits;
16317 EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16318 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16319 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16320 AdvanceIT();
16321 return;
16322 }
16323 }
16324 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
16325 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16326 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16327 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16328 unsigned offset = 32;
16329 if (dt2.Is(S16) || dt2.Is(U16)) {
16330 offset = 16;
16331 }
16332 uint32_t fbits_ = offset - fbits;
16333 EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16334 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16335 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16336 ((fbits_ & 0x1e) >> 1));
16337 AdvanceIT();
16338 return;
16339 }
16340 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
16341 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16342 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16343 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16344 unsigned offset = 32;
16345 if (dt1.Is(S16) || dt1.Is(U16)) {
16346 offset = 16;
16347 }
16348 uint32_t fbits_ = offset - fbits;
16349 EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16350 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16351 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16352 ((fbits_ & 0x1e) >> 1));
16353 AdvanceIT();
16354 return;
16355 }
16356 } else {
16357 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
16358 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16359 if (cond.Is(al)) {
16360 uint32_t fbits_ = 64 - fbits;
16361 EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16362 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16363 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16364 return;
16365 }
16366 }
16367 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
16368 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16369 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16370 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16371 cond.IsNotNever()) {
16372 unsigned offset = 32;
16373 if (dt2.Is(S16) || dt2.Is(U16)) {
16374 offset = 16;
16375 }
16376 uint32_t fbits_ = offset - fbits;
16377 EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
16378 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16379 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16380 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16381 ((fbits_ & 0x1e) >> 1));
16382 return;
16383 }
16384 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
16385 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16386 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16387 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16388 cond.IsNotNever()) {
16389 unsigned offset = 32;
16390 if (dt1.Is(S16) || dt1.Is(U16)) {
16391 offset = 16;
16392 }
16393 uint32_t fbits_ = offset - fbits;
16394 EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
16395 ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16396 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16397 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16398 ((fbits_ & 0x1e) >> 1));
16399 return;
16400 }
16401 }
16402 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16403}
16404
16405void Assembler::vcvt(Condition cond,
16406 DataType dt1,
16407 DataType dt2,
16408 QRegister rd,
16409 QRegister rm,
16410 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016411 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016412 CheckIT(cond);
16413 Dt_op_U_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016414 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016415 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
16416 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16417 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16418 uint32_t fbits_ = 64 - fbits;
16419 EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16420 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16421 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16422 AdvanceIT();
16423 return;
16424 }
16425 }
16426 } else {
16427 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
16428 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16429 if (cond.Is(al)) {
16430 uint32_t fbits_ = 64 - fbits;
16431 EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16432 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16433 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16434 return;
16435 }
16436 }
16437 }
16438 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16439}
16440
16441void Assembler::vcvt(Condition cond,
16442 DataType dt1,
16443 DataType dt2,
16444 SRegister rd,
16445 SRegister rm,
16446 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016447 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016448 CheckIT(cond);
16449 Dt_U_sx_1 encoded_dt(dt2);
16450 Dt_U_sx_1 encoded_dt_2(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016451 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016452 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
16453 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16454 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16455 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16456 unsigned offset = 32;
16457 if (dt2.Is(S16) || dt2.Is(U16)) {
16458 offset = 16;
16459 }
16460 uint32_t fbits_ = offset - fbits;
16461 EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16462 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16463 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16464 ((fbits_ & 0x1e) >> 1));
16465 AdvanceIT();
16466 return;
16467 }
16468 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
16469 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16470 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16471 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16472 unsigned offset = 32;
16473 if (dt1.Is(S16) || dt1.Is(U16)) {
16474 offset = 16;
16475 }
16476 uint32_t fbits_ = offset - fbits;
16477 EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16478 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16479 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16480 ((fbits_ & 0x1e) >> 1));
16481 AdvanceIT();
16482 return;
16483 }
16484 } else {
16485 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
16486 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16487 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16488 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16489 cond.IsNotNever()) {
16490 unsigned offset = 32;
16491 if (dt2.Is(S16) || dt2.Is(U16)) {
16492 offset = 16;
16493 }
16494 uint32_t fbits_ = offset - fbits;
16495 EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
16496 ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16497 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16498 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16499 ((fbits_ & 0x1e) >> 1));
16500 return;
16501 }
16502 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
16503 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16504 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16505 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16506 cond.IsNotNever()) {
16507 unsigned offset = 32;
16508 if (dt1.Is(S16) || dt1.Is(U16)) {
16509 offset = 16;
16510 }
16511 uint32_t fbits_ = offset - fbits;
16512 EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
16513 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16514 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16515 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16516 ((fbits_ & 0x1e) >> 1));
16517 return;
16518 }
16519 }
16520 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16521}
16522
16523void Assembler::vcvt(
16524 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016525 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016526 CheckIT(cond);
16527 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016528 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016529 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
16530 if (encoded_dt.IsValid()) {
16531 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16532 EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
16533 rd.Encode(22, 12) | rm.Encode(5, 0));
16534 AdvanceIT();
16535 return;
16536 }
16537 }
16538 } else {
16539 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
16540 if (encoded_dt.IsValid()) {
16541 if (cond.Is(al)) {
16542 EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
16543 rd.Encode(22, 12) | rm.Encode(5, 0));
16544 return;
16545 }
16546 }
16547 }
16548 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16549}
16550
16551void Assembler::vcvt(
16552 Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016553 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016554 CheckIT(cond);
16555 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016556 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016557 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
16558 if (encoded_dt.IsValid()) {
16559 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16560 EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
16561 rd.Encode(22, 12) | rm.Encode(5, 0));
16562 AdvanceIT();
16563 return;
16564 }
16565 }
16566 } else {
16567 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
16568 if (encoded_dt.IsValid()) {
16569 if (cond.Is(al)) {
16570 EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
16571 rd.Encode(22, 12) | rm.Encode(5, 0));
16572 return;
16573 }
16574 }
16575 }
16576 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16577}
16578
16579void Assembler::vcvt(
16580 Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016581 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016582 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016583 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016584 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
16585 if (dt1.Is(F16) && dt2.Is(F32)) {
16586 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16587 EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16588 AdvanceIT();
16589 return;
16590 }
16591 }
16592 } else {
16593 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
16594 if (dt1.Is(F16) && dt2.Is(F32)) {
16595 if (cond.Is(al)) {
16596 EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16597 return;
16598 }
16599 }
16600 }
16601 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16602}
16603
16604void Assembler::vcvt(
16605 Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016606 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016607 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016608 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016609 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
16610 if (dt1.Is(F32) && dt2.Is(F16)) {
16611 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16612 EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16613 AdvanceIT();
16614 return;
16615 }
16616 }
16617 } else {
16618 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
16619 if (dt1.Is(F32) && dt2.Is(F16)) {
16620 if (cond.Is(al)) {
16621 EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16622 return;
16623 }
16624 }
16625 }
16626 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16627}
16628
16629void Assembler::vcvt(
16630 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016631 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016632 CheckIT(cond);
16633 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016634 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016635 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
16636 if (dt1.Is(U32) && dt2.Is(F32)) {
16637 EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16638 AdvanceIT();
16639 return;
16640 }
16641 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
16642 if (dt1.Is(S32) && dt2.Is(F32)) {
16643 EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16644 AdvanceIT();
16645 return;
16646 }
16647 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
16648 if (dt1.Is(F32) && encoded_dt.IsValid()) {
16649 EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
16650 rd.Encode(22, 12) | rm.Encode(5, 0));
16651 AdvanceIT();
16652 return;
16653 }
16654 } else {
16655 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
16656 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
16657 EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16658 rm.Encode(5, 0));
16659 return;
16660 }
16661 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
16662 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
16663 EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16664 rm.Encode(5, 0));
16665 return;
16666 }
16667 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
16668 if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
16669 EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
16670 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16671 rm.Encode(5, 0));
16672 return;
16673 }
16674 }
16675 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16676}
16677
16678void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016679 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016680 CheckIT(al);
16681 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016682 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016683 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16684 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16685 EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
16686 rd.Encode(22, 12) | rm.Encode(5, 0));
16687 AdvanceIT();
16688 return;
16689 }
16690 } else {
16691 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16692 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16693 EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
16694 rd.Encode(22, 12) | rm.Encode(5, 0));
16695 return;
16696 }
16697 }
16698 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16699}
16700
16701void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016702 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016703 CheckIT(al);
16704 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016705 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016706 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16707 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16708 EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
16709 rd.Encode(22, 12) | rm.Encode(5, 0));
16710 AdvanceIT();
16711 return;
16712 }
16713 } else {
16714 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16715 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16716 EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
16717 rd.Encode(22, 12) | rm.Encode(5, 0));
16718 return;
16719 }
16720 }
16721 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16722}
16723
16724void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016725 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016726 CheckIT(al);
16727 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016728 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016729 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16730 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16731 EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16732 rd.Encode(22, 12) | rm.Encode(5, 0));
16733 AdvanceIT();
16734 return;
16735 }
16736 } else {
16737 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16738 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16739 EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16740 rd.Encode(22, 12) | rm.Encode(5, 0));
16741 return;
16742 }
16743 }
16744 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16745}
16746
16747void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016748 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016749 CheckIT(al);
16750 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016751 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016752 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16753 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16754 EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16755 rd.Encode(22, 12) | rm.Encode(5, 0));
16756 AdvanceIT();
16757 return;
16758 }
16759 } else {
16760 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16761 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16762 EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16763 rd.Encode(22, 12) | rm.Encode(5, 0));
16764 return;
16765 }
16766 }
16767 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16768}
16769
16770void Assembler::vcvtb(
16771 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016772 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016773 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016774 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016775 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16776 if (dt1.Is(F32) && dt2.Is(F16)) {
16777 EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16778 AdvanceIT();
16779 return;
16780 }
16781 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16782 if (dt1.Is(F16) && dt2.Is(F32)) {
16783 EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16784 AdvanceIT();
16785 return;
16786 }
16787 } else {
16788 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16789 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16790 EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16791 rm.Encode(5, 0));
16792 return;
16793 }
16794 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16795 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16796 EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16797 rm.Encode(5, 0));
16798 return;
16799 }
16800 }
16801 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16802}
16803
16804void Assembler::vcvtb(
16805 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016806 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016807 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016808 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016809 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16810 if (dt1.Is(F64) && dt2.Is(F16)) {
16811 EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16812 AdvanceIT();
16813 return;
16814 }
16815 } else {
16816 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16817 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16818 EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16819 rm.Encode(5, 0));
16820 return;
16821 }
16822 }
16823 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16824}
16825
16826void Assembler::vcvtb(
16827 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016828 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016829 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016831 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16832 if (dt1.Is(F16) && dt2.Is(F64)) {
16833 EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16834 AdvanceIT();
16835 return;
16836 }
16837 } else {
16838 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16839 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16840 EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16841 rm.Encode(5, 0));
16842 return;
16843 }
16844 }
16845 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16846}
16847
16848void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016849 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016850 CheckIT(al);
16851 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016852 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016853 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16854 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16855 EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
16856 rd.Encode(22, 12) | rm.Encode(5, 0));
16857 AdvanceIT();
16858 return;
16859 }
16860 } else {
16861 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16862 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16863 EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
16864 rd.Encode(22, 12) | rm.Encode(5, 0));
16865 return;
16866 }
16867 }
16868 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16869}
16870
16871void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016872 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016873 CheckIT(al);
16874 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016875 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016876 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16877 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16878 EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
16879 rd.Encode(22, 12) | rm.Encode(5, 0));
16880 AdvanceIT();
16881 return;
16882 }
16883 } else {
16884 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16885 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16886 EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
16887 rd.Encode(22, 12) | rm.Encode(5, 0));
16888 return;
16889 }
16890 }
16891 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16892}
16893
16894void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016895 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016896 CheckIT(al);
16897 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016898 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016899 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16900 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16901 EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16902 rd.Encode(22, 12) | rm.Encode(5, 0));
16903 AdvanceIT();
16904 return;
16905 }
16906 } else {
16907 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16908 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16909 EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16910 rd.Encode(22, 12) | rm.Encode(5, 0));
16911 return;
16912 }
16913 }
16914 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16915}
16916
16917void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016918 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016919 CheckIT(al);
16920 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016921 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016922 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16923 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16924 EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16925 rd.Encode(22, 12) | rm.Encode(5, 0));
16926 AdvanceIT();
16927 return;
16928 }
16929 } else {
16930 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16931 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16932 EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16933 rd.Encode(22, 12) | rm.Encode(5, 0));
16934 return;
16935 }
16936 }
16937 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16938}
16939
16940void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016941 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016942 CheckIT(al);
16943 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016944 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016945 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16946 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16947 EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
16948 rd.Encode(22, 12) | rm.Encode(5, 0));
16949 AdvanceIT();
16950 return;
16951 }
16952 } else {
16953 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16954 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16955 EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
16956 rd.Encode(22, 12) | rm.Encode(5, 0));
16957 return;
16958 }
16959 }
16960 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16961}
16962
16963void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016964 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016965 CheckIT(al);
16966 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016968 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16969 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16970 EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
16971 rd.Encode(22, 12) | rm.Encode(5, 0));
16972 AdvanceIT();
16973 return;
16974 }
16975 } else {
16976 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16977 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16978 EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
16979 rd.Encode(22, 12) | rm.Encode(5, 0));
16980 return;
16981 }
16982 }
16983 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16984}
16985
16986void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016987 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016988 CheckIT(al);
16989 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016990 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016991 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16992 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16993 EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16994 rd.Encode(22, 12) | rm.Encode(5, 0));
16995 AdvanceIT();
16996 return;
16997 }
16998 } else {
16999 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17000 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17001 EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
17002 rd.Encode(22, 12) | rm.Encode(5, 0));
17003 return;
17004 }
17005 }
17006 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
17007}
17008
17009void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017010 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017011 CheckIT(al);
17012 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017013 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017014 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17015 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17016 EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
17017 rd.Encode(22, 12) | rm.Encode(5, 0));
17018 AdvanceIT();
17019 return;
17020 }
17021 } else {
17022 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17023 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17024 EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
17025 rd.Encode(22, 12) | rm.Encode(5, 0));
17026 return;
17027 }
17028 }
17029 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
17030}
17031
17032void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017033 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017034 CheckIT(al);
17035 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017036 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017037 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
17038 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17039 EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
17040 rd.Encode(22, 12) | rm.Encode(5, 0));
17041 AdvanceIT();
17042 return;
17043 }
17044 } else {
17045 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
17046 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17047 EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
17048 rd.Encode(22, 12) | rm.Encode(5, 0));
17049 return;
17050 }
17051 }
17052 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17053}
17054
17055void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017056 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017057 CheckIT(al);
17058 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017059 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017060 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
17061 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17062 EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
17063 rd.Encode(22, 12) | rm.Encode(5, 0));
17064 AdvanceIT();
17065 return;
17066 }
17067 } else {
17068 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
17069 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17070 EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
17071 rd.Encode(22, 12) | rm.Encode(5, 0));
17072 return;
17073 }
17074 }
17075 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17076}
17077
17078void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017079 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017080 CheckIT(al);
17081 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017082 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017083 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
17084 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17085 EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17086 rd.Encode(22, 12) | rm.Encode(5, 0));
17087 AdvanceIT();
17088 return;
17089 }
17090 } else {
17091 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17092 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17093 EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17094 rd.Encode(22, 12) | rm.Encode(5, 0));
17095 return;
17096 }
17097 }
17098 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17099}
17100
17101void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017102 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017103 CheckIT(al);
17104 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017105 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017106 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17107 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17108 EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17109 rd.Encode(22, 12) | rm.Encode(5, 0));
17110 AdvanceIT();
17111 return;
17112 }
17113 } else {
17114 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17115 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17116 EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17117 rd.Encode(22, 12) | rm.Encode(5, 0));
17118 return;
17119 }
17120 }
17121 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17122}
17123
17124void Assembler::vcvtr(
17125 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017126 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017127 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017128 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017129 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
17130 if (dt1.Is(U32) && dt2.Is(F32)) {
17131 EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17132 AdvanceIT();
17133 return;
17134 }
17135 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
17136 if (dt1.Is(S32) && dt2.Is(F32)) {
17137 EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17138 AdvanceIT();
17139 return;
17140 }
17141 } else {
17142 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
17143 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
17144 EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17145 rm.Encode(5, 0));
17146 return;
17147 }
17148 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
17149 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
17150 EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17151 rm.Encode(5, 0));
17152 return;
17153 }
17154 }
17155 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17156}
17157
17158void Assembler::vcvtr(
17159 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017160 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017161 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017162 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017163 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
17164 if (dt1.Is(U32) && dt2.Is(F64)) {
17165 EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17166 AdvanceIT();
17167 return;
17168 }
17169 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
17170 if (dt1.Is(S32) && dt2.Is(F64)) {
17171 EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17172 AdvanceIT();
17173 return;
17174 }
17175 } else {
17176 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
17177 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
17178 EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17179 rm.Encode(5, 0));
17180 return;
17181 }
17182 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
17183 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
17184 EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17185 rm.Encode(5, 0));
17186 return;
17187 }
17188 }
17189 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17190}
17191
17192void Assembler::vcvtt(
17193 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017194 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017195 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017196 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017197 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
17198 if (dt1.Is(F32) && dt2.Is(F16)) {
17199 EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17200 AdvanceIT();
17201 return;
17202 }
17203 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
17204 if (dt1.Is(F16) && dt2.Is(F32)) {
17205 EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17206 AdvanceIT();
17207 return;
17208 }
17209 } else {
17210 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
17211 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
17212 EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17213 rm.Encode(5, 0));
17214 return;
17215 }
17216 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
17217 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
17218 EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17219 rm.Encode(5, 0));
17220 return;
17221 }
17222 }
17223 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17224}
17225
17226void Assembler::vcvtt(
17227 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017228 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017229 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017230 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017231 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
17232 if (dt1.Is(F64) && dt2.Is(F16)) {
17233 EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17234 AdvanceIT();
17235 return;
17236 }
17237 } else {
17238 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
17239 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
17240 EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17241 rm.Encode(5, 0));
17242 return;
17243 }
17244 }
17245 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17246}
17247
17248void Assembler::vcvtt(
17249 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017250 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017251 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017252 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017253 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
17254 if (dt1.Is(F16) && dt2.Is(F64)) {
17255 EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17256 AdvanceIT();
17257 return;
17258 }
17259 } else {
17260 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
17261 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
17262 EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17263 rm.Encode(5, 0));
17264 return;
17265 }
17266 }
17267 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17268}
17269
17270void Assembler::vdiv(
17271 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017272 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017273 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017274 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017275 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
17276 if (dt.Is(F32)) {
17277 EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17278 rm.Encode(5, 0));
17279 AdvanceIT();
17280 return;
17281 }
17282 } else {
17283 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
17284 if (dt.Is(F32) && cond.IsNotNever()) {
17285 EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17286 rn.Encode(7, 16) | rm.Encode(5, 0));
17287 return;
17288 }
17289 }
17290 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17291}
17292
17293void Assembler::vdiv(
17294 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017295 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017296 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017297 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017298 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
17299 if (dt.Is(F64)) {
17300 EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17301 rm.Encode(5, 0));
17302 AdvanceIT();
17303 return;
17304 }
17305 } else {
17306 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
17307 if (dt.Is(F64) && cond.IsNotNever()) {
17308 EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17309 rn.Encode(7, 16) | rm.Encode(5, 0));
17310 return;
17311 }
17312 }
17313 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17314}
17315
17316void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017317 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017318 CheckIT(cond);
17319 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017320 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017321 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017322 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017323 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17324 EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17325 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17326 rd.Encode(7, 16) | (rt.GetCode() << 12));
17327 AdvanceIT();
17328 return;
17329 }
17330 }
17331 } else {
17332 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017333 if (encoded_dt.IsValid() && cond.IsNotNever() &&
17334 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017335 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17336 EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
17337 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17338 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17339 rd.Encode(7, 16) | (rt.GetCode() << 12));
17340 return;
17341 }
17342 }
17343 }
17344 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17345}
17346
17347void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017349 CheckIT(cond);
17350 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017352 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017353 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017354 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17355 EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17356 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17357 rd.Encode(7, 16) | (rt.GetCode() << 12));
17358 AdvanceIT();
17359 return;
17360 }
17361 }
17362 } else {
17363 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017364 if (encoded_dt.IsValid() && cond.IsNotNever() &&
17365 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017366 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17367 EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
17368 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17369 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17370 rd.Encode(7, 16) | (rt.GetCode() << 12));
17371 return;
17372 }
17373 }
17374 }
17375 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17376}
17377
17378void Assembler::vdup(Condition cond,
17379 DataType dt,
17380 DRegister rd,
17381 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017382 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017383 CheckIT(cond);
17384 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017385 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017386 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
17387 if (encoded_dt.IsValid()) {
17388 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17389 EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
17390 rd.Encode(22, 12) | rm.Encode(5, 0));
17391 AdvanceIT();
17392 return;
17393 }
17394 }
17395 } else {
17396 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
17397 if (encoded_dt.IsValid()) {
17398 if (cond.Is(al)) {
17399 EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
17400 rd.Encode(22, 12) | rm.Encode(5, 0));
17401 return;
17402 }
17403 }
17404 }
17405 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17406}
17407
17408void Assembler::vdup(Condition cond,
17409 DataType dt,
17410 QRegister rd,
17411 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017412 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017413 CheckIT(cond);
17414 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017415 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017416 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
17417 if (encoded_dt.IsValid()) {
17418 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17419 EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
17420 rd.Encode(22, 12) | rm.Encode(5, 0));
17421 AdvanceIT();
17422 return;
17423 }
17424 }
17425 } else {
17426 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
17427 if (encoded_dt.IsValid()) {
17428 if (cond.Is(al)) {
17429 EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
17430 rd.Encode(22, 12) | rm.Encode(5, 0));
17431 return;
17432 }
17433 }
17434 }
17435 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17436}
17437
17438void Assembler::veor(
17439 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017440 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017441 CheckIT(cond);
17442 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017443 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017444 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
17445 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17446 EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17447 rm.Encode(5, 0));
17448 AdvanceIT();
17449 return;
17450 }
17451 } else {
17452 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
17453 if (cond.Is(al)) {
17454 EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17455 rm.Encode(5, 0));
17456 return;
17457 }
17458 }
17459 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17460}
17461
17462void Assembler::veor(
17463 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017464 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017465 CheckIT(cond);
17466 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017467 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017468 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
17469 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17470 EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17471 rm.Encode(5, 0));
17472 AdvanceIT();
17473 return;
17474 }
17475 } else {
17476 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
17477 if (cond.Is(al)) {
17478 EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17479 rm.Encode(5, 0));
17480 return;
17481 }
17482 }
17483 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17484}
17485
17486void Assembler::vext(Condition cond,
17487 DataType dt,
17488 DRegister rd,
17489 DRegister rn,
17490 DRegister rm,
17491 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017493 CheckIT(cond);
17494 if (operand.IsImmediate()) {
17495 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17496 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017497 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017498 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17499 if (dt.Is(Untyped8) && (imm <= 7)) {
17500 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17501 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17502 rm.Encode(5, 0) | (imm << 8));
17503 AdvanceIT();
17504 return;
17505 }
17506 }
17507 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17508 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17509 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17510 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17511 uint32_t imm4 = imm / dt.GetSize();
17512 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17513 rm.Encode(5, 0) | (imm4 << 8));
17514 AdvanceIT();
17515 return;
17516 }
17517 }
17518 } else {
17519 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17520 if (dt.Is(Untyped8) && (imm <= 7)) {
17521 if (cond.Is(al)) {
17522 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17523 rm.Encode(5, 0) | (imm << 8));
17524 return;
17525 }
17526 }
17527 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17528 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17529 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17530 if (cond.Is(al)) {
17531 uint32_t imm4 = imm / dt.GetSize();
17532 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17533 rm.Encode(5, 0) | (imm4 << 8));
17534 return;
17535 }
17536 }
17537 }
17538 }
17539 }
17540 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17541}
17542
17543void Assembler::vext(Condition cond,
17544 DataType dt,
17545 QRegister rd,
17546 QRegister rn,
17547 QRegister rm,
17548 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017549 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017550 CheckIT(cond);
17551 if (operand.IsImmediate()) {
17552 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17553 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017554 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017555 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17556 if (dt.Is(Untyped8) && (imm <= 15)) {
17557 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17558 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17559 rm.Encode(5, 0) | (imm << 8));
17560 AdvanceIT();
17561 return;
17562 }
17563 }
17564 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17565 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17566 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17567 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17568 uint32_t imm4 = imm / dt.GetSize();
17569 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17570 rm.Encode(5, 0) | (imm4 << 8));
17571 AdvanceIT();
17572 return;
17573 }
17574 }
17575 } else {
17576 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17577 if (dt.Is(Untyped8) && (imm <= 15)) {
17578 if (cond.Is(al)) {
17579 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17580 rm.Encode(5, 0) | (imm << 8));
17581 return;
17582 }
17583 }
17584 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17585 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17586 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17587 if (cond.Is(al)) {
17588 uint32_t imm4 = imm / dt.GetSize();
17589 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17590 rm.Encode(5, 0) | (imm4 << 8));
17591 return;
17592 }
17593 }
17594 }
17595 }
17596 }
17597 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17598}
17599
17600void Assembler::vfma(
17601 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017602 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017603 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017604 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017605 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17606 if (dt.Is(F32)) {
17607 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17608 EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17609 rm.Encode(5, 0));
17610 AdvanceIT();
17611 return;
17612 }
17613 }
17614 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17615 if (dt.Is(F64)) {
17616 EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17617 rm.Encode(5, 0));
17618 AdvanceIT();
17619 return;
17620 }
17621 } else {
17622 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17623 if (dt.Is(F32)) {
17624 if (cond.Is(al)) {
17625 EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17626 rm.Encode(5, 0));
17627 return;
17628 }
17629 }
17630 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17631 if (dt.Is(F64) && cond.IsNotNever()) {
17632 EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17633 rn.Encode(7, 16) | rm.Encode(5, 0));
17634 return;
17635 }
17636 }
17637 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17638}
17639
17640void Assembler::vfma(
17641 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017642 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017643 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017644 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017645 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17646 if (dt.Is(F32)) {
17647 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17648 EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17649 rm.Encode(5, 0));
17650 AdvanceIT();
17651 return;
17652 }
17653 }
17654 } else {
17655 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17656 if (dt.Is(F32)) {
17657 if (cond.Is(al)) {
17658 EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17659 rm.Encode(5, 0));
17660 return;
17661 }
17662 }
17663 }
17664 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17665}
17666
17667void Assembler::vfma(
17668 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017669 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017670 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017671 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017672 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17673 if (dt.Is(F32)) {
17674 EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17675 rm.Encode(5, 0));
17676 AdvanceIT();
17677 return;
17678 }
17679 } else {
17680 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17681 if (dt.Is(F32) && cond.IsNotNever()) {
17682 EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17683 rn.Encode(7, 16) | rm.Encode(5, 0));
17684 return;
17685 }
17686 }
17687 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17688}
17689
17690void Assembler::vfms(
17691 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017692 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017693 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017694 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017695 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17696 if (dt.Is(F32)) {
17697 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17698 EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17699 rm.Encode(5, 0));
17700 AdvanceIT();
17701 return;
17702 }
17703 }
17704 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17705 if (dt.Is(F64)) {
17706 EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17707 rm.Encode(5, 0));
17708 AdvanceIT();
17709 return;
17710 }
17711 } else {
17712 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17713 if (dt.Is(F32)) {
17714 if (cond.Is(al)) {
17715 EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17716 rm.Encode(5, 0));
17717 return;
17718 }
17719 }
17720 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17721 if (dt.Is(F64) && cond.IsNotNever()) {
17722 EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17723 rn.Encode(7, 16) | rm.Encode(5, 0));
17724 return;
17725 }
17726 }
17727 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17728}
17729
17730void Assembler::vfms(
17731 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017732 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017733 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017734 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017735 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17736 if (dt.Is(F32)) {
17737 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17738 EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17739 rm.Encode(5, 0));
17740 AdvanceIT();
17741 return;
17742 }
17743 }
17744 } else {
17745 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17746 if (dt.Is(F32)) {
17747 if (cond.Is(al)) {
17748 EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17749 rm.Encode(5, 0));
17750 return;
17751 }
17752 }
17753 }
17754 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17755}
17756
17757void Assembler::vfms(
17758 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017759 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017760 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017761 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017762 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17763 if (dt.Is(F32)) {
17764 EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17765 rm.Encode(5, 0));
17766 AdvanceIT();
17767 return;
17768 }
17769 } else {
17770 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17771 if (dt.Is(F32) && cond.IsNotNever()) {
17772 EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17773 rn.Encode(7, 16) | rm.Encode(5, 0));
17774 return;
17775 }
17776 }
17777 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17778}
17779
17780void Assembler::vfnma(
17781 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017782 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017783 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017784 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017785 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17786 if (dt.Is(F32)) {
17787 EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17788 rm.Encode(5, 0));
17789 AdvanceIT();
17790 return;
17791 }
17792 } else {
17793 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17794 if (dt.Is(F32) && cond.IsNotNever()) {
17795 EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17796 rn.Encode(7, 16) | rm.Encode(5, 0));
17797 return;
17798 }
17799 }
17800 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17801}
17802
17803void Assembler::vfnma(
17804 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017805 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017806 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017807 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017808 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17809 if (dt.Is(F64)) {
17810 EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17811 rm.Encode(5, 0));
17812 AdvanceIT();
17813 return;
17814 }
17815 } else {
17816 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17817 if (dt.Is(F64) && cond.IsNotNever()) {
17818 EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17819 rn.Encode(7, 16) | rm.Encode(5, 0));
17820 return;
17821 }
17822 }
17823 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17824}
17825
17826void Assembler::vfnms(
17827 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017828 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017829 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017831 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17832 if (dt.Is(F32)) {
17833 EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17834 rm.Encode(5, 0));
17835 AdvanceIT();
17836 return;
17837 }
17838 } else {
17839 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17840 if (dt.Is(F32) && cond.IsNotNever()) {
17841 EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17842 rn.Encode(7, 16) | rm.Encode(5, 0));
17843 return;
17844 }
17845 }
17846 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17847}
17848
17849void Assembler::vfnms(
17850 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017851 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017852 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017853 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017854 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17855 if (dt.Is(F64)) {
17856 EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17857 rm.Encode(5, 0));
17858 AdvanceIT();
17859 return;
17860 }
17861 } else {
17862 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17863 if (dt.Is(F64) && cond.IsNotNever()) {
17864 EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17865 rn.Encode(7, 16) | rm.Encode(5, 0));
17866 return;
17867 }
17868 }
17869 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17870}
17871
17872void Assembler::vhadd(
17873 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017874 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017875 CheckIT(cond);
17876 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017877 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017878 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17879 if (encoded_dt.IsValid()) {
17880 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17881 EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17882 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17883 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17884 AdvanceIT();
17885 return;
17886 }
17887 }
17888 } else {
17889 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17890 if (encoded_dt.IsValid()) {
17891 if (cond.Is(al)) {
17892 EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17893 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17894 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17895 return;
17896 }
17897 }
17898 }
17899 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17900}
17901
17902void Assembler::vhadd(
17903 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017904 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017905 CheckIT(cond);
17906 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017907 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017908 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17909 if (encoded_dt.IsValid()) {
17910 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17911 EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17912 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17913 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17914 AdvanceIT();
17915 return;
17916 }
17917 }
17918 } else {
17919 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17920 if (encoded_dt.IsValid()) {
17921 if (cond.Is(al)) {
17922 EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17923 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17924 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17925 return;
17926 }
17927 }
17928 }
17929 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17930}
17931
17932void Assembler::vhsub(
17933 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017934 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017935 CheckIT(cond);
17936 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017937 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017938 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17939 if (encoded_dt.IsValid()) {
17940 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17941 EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17942 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17943 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17944 AdvanceIT();
17945 return;
17946 }
17947 }
17948 } else {
17949 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17950 if (encoded_dt.IsValid()) {
17951 if (cond.Is(al)) {
17952 EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17953 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17954 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17955 return;
17956 }
17957 }
17958 }
17959 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17960}
17961
17962void Assembler::vhsub(
17963 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017964 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017965 CheckIT(cond);
17966 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017968 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17969 if (encoded_dt.IsValid()) {
17970 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17971 EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17972 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17973 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17974 AdvanceIT();
17975 return;
17976 }
17977 }
17978 } else {
17979 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17980 if (encoded_dt.IsValid()) {
17981 if (cond.Is(al)) {
17982 EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17983 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17984 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17985 return;
17986 }
17987 }
17988 }
17989 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17990}
17991
17992void Assembler::vld1(Condition cond,
17993 DataType dt,
17994 const NeonRegisterList& nreglist,
17995 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017996 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017997 CheckIT(cond);
17998 if (operand.IsImmediateZero()) {
17999 Register rn = operand.GetBaseRegister();
18000 Alignment align = operand.GetAlignment();
18001 Dt_size_6 encoded_dt(dt);
18002 Dt_size_7 encoded_dt_2(dt);
18003 Align_align_1 encoded_align_1(align, nreglist);
18004 Align_a_1 encoded_align_2(align, dt);
18005 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018006 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018007 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18008 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18009 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018010 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018011 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018012 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18013 const DRegister& first = nreglist.GetFirstDRegister();
18014 uint32_t len_encoding;
18015 switch (nreglist.GetLength()) {
18016 default:
18017 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18018 case 1:
18019 len_encoding = 0x7;
18020 break;
18021 case 2:
18022 len_encoding = 0xa;
18023 break;
18024 case 3:
18025 len_encoding = 0x6;
18026 break;
18027 case 4:
18028 len_encoding = 0x2;
18029 break;
18030 }
18031 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18032 (encoded_align_1.GetEncodingValue() << 4) |
18033 first.Encode(22, 12) | (len_encoding << 8) |
18034 (rn.GetCode() << 16));
18035 AdvanceIT();
18036 return;
18037 }
18038 }
18039 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18040 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18041 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018042 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018043 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018044 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18045 const DRegister& first = nreglist.GetFirstDRegister();
18046 uint32_t len_encoding;
18047 switch (nreglist.GetLength()) {
18048 default:
18049 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18050 case 1:
18051 len_encoding = 0x7;
18052 break;
18053 case 2:
18054 len_encoding = 0xa;
18055 break;
18056 case 3:
18057 len_encoding = 0x6;
18058 break;
18059 case 4:
18060 len_encoding = 0x2;
18061 break;
18062 }
18063 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18064 (encoded_align_1.GetEncodingValue() << 4) |
18065 first.Encode(22, 12) | (len_encoding << 8) |
18066 (rn.GetCode() << 16));
18067 AdvanceIT();
18068 return;
18069 }
18070 }
18071 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18072 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18073 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018074 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018075 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018076 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18077 const DRegister& first = nreglist.GetFirstDRegister();
18078 uint32_t len_encoding = nreglist.GetLength() - 1;
18079 EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18080 (encoded_align_2.GetEncodingValue() << 4) |
18081 first.Encode(22, 12) | (len_encoding << 5) |
18082 (rn.GetCode() << 16));
18083 AdvanceIT();
18084 return;
18085 }
18086 }
18087 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18088 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18089 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018090 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018091 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018092 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18093 const DRegister& first = nreglist.GetFirstDRegister();
18094 uint32_t len_encoding = nreglist.GetLength() - 1;
18095 EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18096 (encoded_align_2.GetEncodingValue() << 4) |
18097 first.Encode(22, 12) | (len_encoding << 5) |
18098 (rn.GetCode() << 16));
18099 AdvanceIT();
18100 return;
18101 }
18102 }
18103 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18104 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018105 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018106 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018107 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18108 const DRegister& first = nreglist.GetFirstDRegister();
18109 EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18110 (encoded_align_3.GetEncodingValue() << 4) |
18111 first.Encode(22, 12) | (rn.GetCode() << 16));
18112 AdvanceIT();
18113 return;
18114 }
18115 }
18116 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18117 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018118 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018119 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018120 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18121 const DRegister& first = nreglist.GetFirstDRegister();
18122 EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18123 (encoded_align_3.GetEncodingValue() << 4) |
18124 first.Encode(22, 12) | (rn.GetCode() << 16));
18125 AdvanceIT();
18126 return;
18127 }
18128 }
18129 } else {
18130 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18131 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18132 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018133 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018134 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018135 if (cond.Is(al)) {
18136 const DRegister& first = nreglist.GetFirstDRegister();
18137 uint32_t len_encoding;
18138 switch (nreglist.GetLength()) {
18139 default:
18140 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18141 case 1:
18142 len_encoding = 0x7;
18143 break;
18144 case 2:
18145 len_encoding = 0xa;
18146 break;
18147 case 3:
18148 len_encoding = 0x6;
18149 break;
18150 case 4:
18151 len_encoding = 0x2;
18152 break;
18153 }
18154 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18155 (encoded_align_1.GetEncodingValue() << 4) |
18156 first.Encode(22, 12) | (len_encoding << 8) |
18157 (rn.GetCode() << 16));
18158 return;
18159 }
18160 }
18161 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18162 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18163 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018164 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018165 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018166 if (cond.Is(al)) {
18167 const DRegister& first = nreglist.GetFirstDRegister();
18168 uint32_t len_encoding;
18169 switch (nreglist.GetLength()) {
18170 default:
18171 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18172 case 1:
18173 len_encoding = 0x7;
18174 break;
18175 case 2:
18176 len_encoding = 0xa;
18177 break;
18178 case 3:
18179 len_encoding = 0x6;
18180 break;
18181 case 4:
18182 len_encoding = 0x2;
18183 break;
18184 }
18185 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18186 (encoded_align_1.GetEncodingValue() << 4) |
18187 first.Encode(22, 12) | (len_encoding << 8) |
18188 (rn.GetCode() << 16));
18189 return;
18190 }
18191 }
18192 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18193 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18194 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018195 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018196 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018197 if (cond.Is(al)) {
18198 const DRegister& first = nreglist.GetFirstDRegister();
18199 uint32_t len_encoding = nreglist.GetLength() - 1;
18200 EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18201 (encoded_align_2.GetEncodingValue() << 4) |
18202 first.Encode(22, 12) | (len_encoding << 5) |
18203 (rn.GetCode() << 16));
18204 return;
18205 }
18206 }
18207 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18208 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18209 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018210 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018211 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018212 if (cond.Is(al)) {
18213 const DRegister& first = nreglist.GetFirstDRegister();
18214 uint32_t len_encoding = nreglist.GetLength() - 1;
18215 EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18216 (encoded_align_2.GetEncodingValue() << 4) |
18217 first.Encode(22, 12) | (len_encoding << 5) |
18218 (rn.GetCode() << 16));
18219 return;
18220 }
18221 }
18222 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18223 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018224 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018225 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018226 if (cond.Is(al)) {
18227 const DRegister& first = nreglist.GetFirstDRegister();
18228 EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18229 (encoded_align_3.GetEncodingValue() << 4) |
18230 first.Encode(22, 12) | (rn.GetCode() << 16));
18231 return;
18232 }
18233 }
18234 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18235 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018236 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018237 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018238 if (cond.Is(al)) {
18239 const DRegister& first = nreglist.GetFirstDRegister();
18240 EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18241 (encoded_align_3.GetEncodingValue() << 4) |
18242 first.Encode(22, 12) | (rn.GetCode() << 16));
18243 return;
18244 }
18245 }
18246 }
18247 }
18248 if (operand.IsPlainRegister()) {
18249 Register rn = operand.GetBaseRegister();
18250 Alignment align = operand.GetAlignment();
18251 Register rm = operand.GetOffsetRegister();
18252 Dt_size_6 encoded_dt(dt);
18253 Dt_size_7 encoded_dt_2(dt);
18254 Align_align_1 encoded_align_1(align, nreglist);
18255 Align_a_1 encoded_align_2(align, dt);
18256 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018257 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018258 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18259 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18260 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018261 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018262 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18263 const DRegister& first = nreglist.GetFirstDRegister();
18264 uint32_t len_encoding;
18265 switch (nreglist.GetLength()) {
18266 default:
18267 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18268 case 1:
18269 len_encoding = 0x7;
18270 break;
18271 case 2:
18272 len_encoding = 0xa;
18273 break;
18274 case 3:
18275 len_encoding = 0x6;
18276 break;
18277 case 4:
18278 len_encoding = 0x2;
18279 break;
18280 }
18281 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18282 (encoded_align_1.GetEncodingValue() << 4) |
18283 first.Encode(22, 12) | (len_encoding << 8) |
18284 (rn.GetCode() << 16) | rm.GetCode());
18285 AdvanceIT();
18286 return;
18287 }
18288 }
18289 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18290 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18291 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018292 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018293 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18294 const DRegister& first = nreglist.GetFirstDRegister();
18295 uint32_t len_encoding = nreglist.GetLength() - 1;
18296 EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18297 (encoded_align_2.GetEncodingValue() << 4) |
18298 first.Encode(22, 12) | (len_encoding << 5) |
18299 (rn.GetCode() << 16) | rm.GetCode());
18300 AdvanceIT();
18301 return;
18302 }
18303 }
18304 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18305 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018306 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18307 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018308 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18309 const DRegister& first = nreglist.GetFirstDRegister();
18310 EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18311 (encoded_align_3.GetEncodingValue() << 4) |
18312 first.Encode(22, 12) | (rn.GetCode() << 16) |
18313 rm.GetCode());
18314 AdvanceIT();
18315 return;
18316 }
18317 }
18318 } else {
18319 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18320 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18321 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018322 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018323 if (cond.Is(al)) {
18324 const DRegister& first = nreglist.GetFirstDRegister();
18325 uint32_t len_encoding;
18326 switch (nreglist.GetLength()) {
18327 default:
18328 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18329 case 1:
18330 len_encoding = 0x7;
18331 break;
18332 case 2:
18333 len_encoding = 0xa;
18334 break;
18335 case 3:
18336 len_encoding = 0x6;
18337 break;
18338 case 4:
18339 len_encoding = 0x2;
18340 break;
18341 }
18342 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18343 (encoded_align_1.GetEncodingValue() << 4) |
18344 first.Encode(22, 12) | (len_encoding << 8) |
18345 (rn.GetCode() << 16) | rm.GetCode());
18346 return;
18347 }
18348 }
18349 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18350 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18351 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018352 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018353 if (cond.Is(al)) {
18354 const DRegister& first = nreglist.GetFirstDRegister();
18355 uint32_t len_encoding = nreglist.GetLength() - 1;
18356 EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18357 (encoded_align_2.GetEncodingValue() << 4) |
18358 first.Encode(22, 12) | (len_encoding << 5) |
18359 (rn.GetCode() << 16) | rm.GetCode());
18360 return;
18361 }
18362 }
18363 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18364 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018365 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18366 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018367 if (cond.Is(al)) {
18368 const DRegister& first = nreglist.GetFirstDRegister();
18369 EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18370 (encoded_align_3.GetEncodingValue() << 4) |
18371 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18372 return;
18373 }
18374 }
18375 }
18376 }
18377 Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
18378}
18379
18380void Assembler::vld2(Condition cond,
18381 DataType dt,
18382 const NeonRegisterList& nreglist,
18383 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018384 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018385 CheckIT(cond);
18386 if (operand.IsImmediateZero()) {
18387 Register rn = operand.GetBaseRegister();
18388 Alignment align = operand.GetAlignment();
18389 Dt_size_7 encoded_dt(dt);
18390 Align_align_2 encoded_align_1(align, nreglist);
18391 Align_a_2 encoded_align_2(align, dt);
18392 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018393 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018394 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18395 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18396 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18397 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18398 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018399 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018400 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018401 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18402 const DRegister& first = nreglist.GetFirstDRegister();
18403 uint32_t len_encoding;
18404 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18405 len_encoding = 0x8;
18406 }
18407 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18408 len_encoding = 0x9;
18409 }
18410 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18411 len_encoding = 0x3;
18412 }
18413 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18414 (encoded_align_1.GetEncodingValue() << 4) |
18415 first.Encode(22, 12) | (len_encoding << 8) |
18416 (rn.GetCode() << 16));
18417 AdvanceIT();
18418 return;
18419 }
18420 }
18421 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18422 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18423 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18424 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18425 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018426 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018427 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018428 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18429 const DRegister& first = nreglist.GetFirstDRegister();
18430 uint32_t len_encoding;
18431 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18432 len_encoding = 0x8;
18433 }
18434 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18435 len_encoding = 0x9;
18436 }
18437 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18438 len_encoding = 0x3;
18439 }
18440 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18441 (encoded_align_1.GetEncodingValue() << 4) |
18442 first.Encode(22, 12) | (len_encoding << 8) |
18443 (rn.GetCode() << 16));
18444 AdvanceIT();
18445 return;
18446 }
18447 }
18448 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18449 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18450 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18451 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018452 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018453 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018454 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18455 const DRegister& first = nreglist.GetFirstDRegister();
18456 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18457 EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18458 (encoded_align_2.GetEncodingValue() << 4) |
18459 first.Encode(22, 12) | (len_encoding << 5) |
18460 (rn.GetCode() << 16));
18461 AdvanceIT();
18462 return;
18463 }
18464 }
18465 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18466 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18467 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18468 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018469 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018470 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018471 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18472 const DRegister& first = nreglist.GetFirstDRegister();
18473 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18474 EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18475 (encoded_align_2.GetEncodingValue() << 4) |
18476 first.Encode(22, 12) | (len_encoding << 5) |
18477 (rn.GetCode() << 16));
18478 AdvanceIT();
18479 return;
18480 }
18481 }
18482 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18483 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18484 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18485 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018486 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018487 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018488 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18489 const DRegister& first = nreglist.GetFirstDRegister();
18490 EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18491 (encoded_align_3.GetEncodingValue() << 4) |
18492 first.Encode(22, 12) | (rn.GetCode() << 16));
18493 AdvanceIT();
18494 return;
18495 }
18496 }
18497 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18498 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18499 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18500 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018501 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018502 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018503 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18504 const DRegister& first = nreglist.GetFirstDRegister();
18505 EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18506 (encoded_align_3.GetEncodingValue() << 4) |
18507 first.Encode(22, 12) | (rn.GetCode() << 16));
18508 AdvanceIT();
18509 return;
18510 }
18511 }
18512 } else {
18513 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18514 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18515 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18516 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18517 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018518 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018519 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018520 if (cond.Is(al)) {
18521 const DRegister& first = nreglist.GetFirstDRegister();
18522 uint32_t len_encoding;
18523 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18524 len_encoding = 0x8;
18525 }
18526 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18527 len_encoding = 0x9;
18528 }
18529 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18530 len_encoding = 0x3;
18531 }
18532 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18533 (encoded_align_1.GetEncodingValue() << 4) |
18534 first.Encode(22, 12) | (len_encoding << 8) |
18535 (rn.GetCode() << 16));
18536 return;
18537 }
18538 }
18539 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18540 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18541 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18542 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18543 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018544 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018545 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018546 if (cond.Is(al)) {
18547 const DRegister& first = nreglist.GetFirstDRegister();
18548 uint32_t len_encoding;
18549 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18550 len_encoding = 0x8;
18551 }
18552 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18553 len_encoding = 0x9;
18554 }
18555 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18556 len_encoding = 0x3;
18557 }
18558 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18559 (encoded_align_1.GetEncodingValue() << 4) |
18560 first.Encode(22, 12) | (len_encoding << 8) |
18561 (rn.GetCode() << 16));
18562 return;
18563 }
18564 }
18565 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18566 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18567 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18568 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018569 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018570 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018571 if (cond.Is(al)) {
18572 const DRegister& first = nreglist.GetFirstDRegister();
18573 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18574 EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18575 (encoded_align_2.GetEncodingValue() << 4) |
18576 first.Encode(22, 12) | (len_encoding << 5) |
18577 (rn.GetCode() << 16));
18578 return;
18579 }
18580 }
18581 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18582 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18583 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18584 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018585 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018586 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018587 if (cond.Is(al)) {
18588 const DRegister& first = nreglist.GetFirstDRegister();
18589 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18590 EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18591 (encoded_align_2.GetEncodingValue() << 4) |
18592 first.Encode(22, 12) | (len_encoding << 5) |
18593 (rn.GetCode() << 16));
18594 return;
18595 }
18596 }
18597 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18598 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18599 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18600 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018601 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018602 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018603 if (cond.Is(al)) {
18604 const DRegister& first = nreglist.GetFirstDRegister();
18605 EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18606 (encoded_align_3.GetEncodingValue() << 4) |
18607 first.Encode(22, 12) | (rn.GetCode() << 16));
18608 return;
18609 }
18610 }
18611 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18612 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18613 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18614 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018615 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018616 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018617 if (cond.Is(al)) {
18618 const DRegister& first = nreglist.GetFirstDRegister();
18619 EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18620 (encoded_align_3.GetEncodingValue() << 4) |
18621 first.Encode(22, 12) | (rn.GetCode() << 16));
18622 return;
18623 }
18624 }
18625 }
18626 }
18627 if (operand.IsPlainRegister()) {
18628 Register rn = operand.GetBaseRegister();
18629 Alignment align = operand.GetAlignment();
18630 Register rm = operand.GetOffsetRegister();
18631 Dt_size_7 encoded_dt(dt);
18632 Align_align_2 encoded_align_1(align, nreglist);
18633 Align_a_2 encoded_align_2(align, dt);
18634 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018635 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018636 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18637 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18638 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18639 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18640 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018641 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018642 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18643 const DRegister& first = nreglist.GetFirstDRegister();
18644 uint32_t len_encoding;
18645 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18646 len_encoding = 0x8;
18647 }
18648 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18649 len_encoding = 0x9;
18650 }
18651 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18652 len_encoding = 0x3;
18653 }
18654 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18655 (encoded_align_1.GetEncodingValue() << 4) |
18656 first.Encode(22, 12) | (len_encoding << 8) |
18657 (rn.GetCode() << 16) | rm.GetCode());
18658 AdvanceIT();
18659 return;
18660 }
18661 }
18662 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18663 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18664 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18665 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018666 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018667 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18668 const DRegister& first = nreglist.GetFirstDRegister();
18669 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18670 EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18671 (encoded_align_2.GetEncodingValue() << 4) |
18672 first.Encode(22, 12) | (len_encoding << 5) |
18673 (rn.GetCode() << 16) | rm.GetCode());
18674 AdvanceIT();
18675 return;
18676 }
18677 }
18678 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18679 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18680 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18681 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018682 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018683 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18684 const DRegister& first = nreglist.GetFirstDRegister();
18685 EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
18686 (encoded_align_3.GetEncodingValue() << 4) |
18687 first.Encode(22, 12) | (rn.GetCode() << 16) |
18688 rm.GetCode());
18689 AdvanceIT();
18690 return;
18691 }
18692 }
18693 } else {
18694 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18695 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18696 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18697 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18698 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018699 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018700 if (cond.Is(al)) {
18701 const DRegister& first = nreglist.GetFirstDRegister();
18702 uint32_t len_encoding;
18703 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18704 len_encoding = 0x8;
18705 }
18706 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18707 len_encoding = 0x9;
18708 }
18709 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18710 len_encoding = 0x3;
18711 }
18712 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18713 (encoded_align_1.GetEncodingValue() << 4) |
18714 first.Encode(22, 12) | (len_encoding << 8) |
18715 (rn.GetCode() << 16) | rm.GetCode());
18716 return;
18717 }
18718 }
18719 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18720 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18721 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18722 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018723 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018724 if (cond.Is(al)) {
18725 const DRegister& first = nreglist.GetFirstDRegister();
18726 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18727 EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18728 (encoded_align_2.GetEncodingValue() << 4) |
18729 first.Encode(22, 12) | (len_encoding << 5) |
18730 (rn.GetCode() << 16) | rm.GetCode());
18731 return;
18732 }
18733 }
18734 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18735 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18736 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18737 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018738 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018739 if (cond.Is(al)) {
18740 const DRegister& first = nreglist.GetFirstDRegister();
18741 EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
18742 (encoded_align_3.GetEncodingValue() << 4) |
18743 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18744 return;
18745 }
18746 }
18747 }
18748 }
18749 Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
18750}
18751
18752void Assembler::vld3(Condition cond,
18753 DataType dt,
18754 const NeonRegisterList& nreglist,
18755 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018756 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018757 CheckIT(cond);
18758 if (operand.IsImmediateZero()) {
18759 Register rn = operand.GetBaseRegister();
18760 Alignment align = operand.GetAlignment();
18761 Dt_size_7 encoded_dt(dt);
18762 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018763 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018764 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18765 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18766 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18767 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018768 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018769 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018770 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18771 const DRegister& first = nreglist.GetFirstDRegister();
18772 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18773 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18774 (encoded_align_1.GetEncodingValue() << 4) |
18775 first.Encode(22, 12) | (len_encoding << 8) |
18776 (rn.GetCode() << 16));
18777 AdvanceIT();
18778 return;
18779 }
18780 }
18781 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18782 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18783 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18784 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018785 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018786 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018787 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18788 const DRegister& first = nreglist.GetFirstDRegister();
18789 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18790 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18791 (encoded_align_1.GetEncodingValue() << 4) |
18792 first.Encode(22, 12) | (len_encoding << 8) |
18793 (rn.GetCode() << 16));
18794 AdvanceIT();
18795 return;
18796 }
18797 }
18798 } else {
18799 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18800 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18801 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18802 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018803 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018804 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018805 if (cond.Is(al)) {
18806 const DRegister& first = nreglist.GetFirstDRegister();
18807 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18808 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18809 (encoded_align_1.GetEncodingValue() << 4) |
18810 first.Encode(22, 12) | (len_encoding << 8) |
18811 (rn.GetCode() << 16));
18812 return;
18813 }
18814 }
18815 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18816 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18817 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18818 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018819 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018820 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018821 if (cond.Is(al)) {
18822 const DRegister& first = nreglist.GetFirstDRegister();
18823 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18824 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18825 (encoded_align_1.GetEncodingValue() << 4) |
18826 first.Encode(22, 12) | (len_encoding << 8) |
18827 (rn.GetCode() << 16));
18828 return;
18829 }
18830 }
18831 }
18832 }
18833 if (operand.IsPlainRegister()) {
18834 Register rn = operand.GetBaseRegister();
18835 Alignment align = operand.GetAlignment();
18836 Register rm = operand.GetOffsetRegister();
18837 Dt_size_7 encoded_dt(dt);
18838 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018839 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018840 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18841 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18842 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18843 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018844 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018845 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18846 const DRegister& first = nreglist.GetFirstDRegister();
18847 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18848 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18849 (encoded_align_1.GetEncodingValue() << 4) |
18850 first.Encode(22, 12) | (len_encoding << 8) |
18851 (rn.GetCode() << 16) | rm.GetCode());
18852 AdvanceIT();
18853 return;
18854 }
18855 }
18856 } else {
18857 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18858 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18859 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18860 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018861 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018862 if (cond.Is(al)) {
18863 const DRegister& first = nreglist.GetFirstDRegister();
18864 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18865 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18866 (encoded_align_1.GetEncodingValue() << 4) |
18867 first.Encode(22, 12) | (len_encoding << 8) |
18868 (rn.GetCode() << 16) | rm.GetCode());
18869 return;
18870 }
18871 }
18872 }
18873 }
18874 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
18875}
18876
18877void Assembler::vld3(Condition cond,
18878 DataType dt,
18879 const NeonRegisterList& nreglist,
18880 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018881 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018882 CheckIT(cond);
18883 if (operand.IsImmediateZero()) {
18884 Register rn = operand.GetBaseRegister();
18885 Dt_size_7 encoded_dt(dt);
18886 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018887 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018888 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18889 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18890 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18891 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018892 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018893 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18894 const DRegister& first = nreglist.GetFirstDRegister();
18895 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18896 EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18897 first.Encode(22, 12) | (len_encoding << 5) |
18898 (rn.GetCode() << 16));
18899 AdvanceIT();
18900 return;
18901 }
18902 }
18903 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18904 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18905 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18906 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018907 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018908 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18909 const DRegister& first = nreglist.GetFirstDRegister();
18910 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18911 EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18912 first.Encode(22, 12) | (len_encoding << 5) |
18913 (rn.GetCode() << 16));
18914 AdvanceIT();
18915 return;
18916 }
18917 }
18918 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18919 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18920 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18921 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018922 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018923 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18924 const DRegister& first = nreglist.GetFirstDRegister();
18925 EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18926 (encoded_align_1.GetEncodingValue() << 4) |
18927 first.Encode(22, 12) | (rn.GetCode() << 16));
18928 AdvanceIT();
18929 return;
18930 }
18931 }
18932 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18933 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18934 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18935 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018936 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018937 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18938 const DRegister& first = nreglist.GetFirstDRegister();
18939 EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18940 (encoded_align_1.GetEncodingValue() << 4) |
18941 first.Encode(22, 12) | (rn.GetCode() << 16));
18942 AdvanceIT();
18943 return;
18944 }
18945 }
18946 } else {
18947 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18948 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18949 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18950 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018951 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018952 if (cond.Is(al)) {
18953 const DRegister& first = nreglist.GetFirstDRegister();
18954 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18955 EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18956 first.Encode(22, 12) | (len_encoding << 5) |
18957 (rn.GetCode() << 16));
18958 return;
18959 }
18960 }
18961 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18962 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18963 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18964 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018965 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018966 if (cond.Is(al)) {
18967 const DRegister& first = nreglist.GetFirstDRegister();
18968 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18969 EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18970 first.Encode(22, 12) | (len_encoding << 5) |
18971 (rn.GetCode() << 16));
18972 return;
18973 }
18974 }
18975 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18976 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18977 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18978 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018979 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018980 if (cond.Is(al)) {
18981 const DRegister& first = nreglist.GetFirstDRegister();
18982 EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18983 (encoded_align_1.GetEncodingValue() << 4) |
18984 first.Encode(22, 12) | (rn.GetCode() << 16));
18985 return;
18986 }
18987 }
18988 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18989 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18990 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18991 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070018992 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018993 if (cond.Is(al)) {
18994 const DRegister& first = nreglist.GetFirstDRegister();
18995 EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18996 (encoded_align_1.GetEncodingValue() << 4) |
18997 first.Encode(22, 12) | (rn.GetCode() << 16));
18998 return;
18999 }
19000 }
19001 }
19002 }
19003 if (operand.IsPlainRegister()) {
19004 Register rn = operand.GetBaseRegister();
19005 Sign sign = operand.GetSign();
19006 Register rm = operand.GetOffsetRegister();
19007 Dt_size_7 encoded_dt(dt);
19008 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019009 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019010 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
19011 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
19012 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19013 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019014 sign.IsPlus() && operand.IsPostIndex() &&
19015 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019016 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19017 const DRegister& first = nreglist.GetFirstDRegister();
19018 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19019 EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19020 first.Encode(22, 12) | (len_encoding << 5) |
19021 (rn.GetCode() << 16) | rm.GetCode());
19022 AdvanceIT();
19023 return;
19024 }
19025 }
19026 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
19027 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19028 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19029 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019030 sign.IsPlus() && operand.IsPostIndex() &&
19031 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019032 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19033 const DRegister& first = nreglist.GetFirstDRegister();
19034 EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
19035 (encoded_align_1.GetEncodingValue() << 4) |
19036 first.Encode(22, 12) | (rn.GetCode() << 16) |
19037 rm.GetCode());
19038 AdvanceIT();
19039 return;
19040 }
19041 }
19042 } else {
19043 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19044 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
19045 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19046 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019047 sign.IsPlus() && operand.IsPostIndex() &&
19048 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019049 if (cond.Is(al)) {
19050 const DRegister& first = nreglist.GetFirstDRegister();
19051 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19052 EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19053 first.Encode(22, 12) | (len_encoding << 5) |
19054 (rn.GetCode() << 16) | rm.GetCode());
19055 return;
19056 }
19057 }
19058 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19059 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19060 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
19061 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019062 sign.IsPlus() && operand.IsPostIndex() &&
19063 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019064 if (cond.Is(al)) {
19065 const DRegister& first = nreglist.GetFirstDRegister();
19066 EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
19067 (encoded_align_1.GetEncodingValue() << 4) |
19068 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19069 return;
19070 }
19071 }
19072 }
19073 }
19074 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
19075}
19076
19077void Assembler::vld4(Condition cond,
19078 DataType dt,
19079 const NeonRegisterList& nreglist,
19080 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019081 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019082 CheckIT(cond);
19083 if (operand.IsImmediateZero()) {
19084 Register rn = operand.GetBaseRegister();
19085 Alignment align = operand.GetAlignment();
19086 Dt_size_7 encoded_dt(dt);
19087 Dt_size_8 encoded_dt_2(dt, align);
19088 Align_align_4 encoded_align_1(align);
19089 Align_a_3 encoded_align_2(align, dt);
19090 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019091 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019092 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19093 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19094 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19095 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019096 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019097 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019098 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19099 const DRegister& first = nreglist.GetFirstDRegister();
19100 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19101 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
19102 (encoded_align_1.GetEncodingValue() << 4) |
19103 first.Encode(22, 12) | (len_encoding << 8) |
19104 (rn.GetCode() << 16));
19105 AdvanceIT();
19106 return;
19107 }
19108 }
19109 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19110 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19111 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19112 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019113 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019114 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019115 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19116 const DRegister& first = nreglist.GetFirstDRegister();
19117 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19118 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
19119 (encoded_align_1.GetEncodingValue() << 4) |
19120 first.Encode(22, 12) | (len_encoding << 8) |
19121 (rn.GetCode() << 16));
19122 AdvanceIT();
19123 return;
19124 }
19125 }
19126 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19127 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19128 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19129 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019130 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019131 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019132 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19133 const DRegister& first = nreglist.GetFirstDRegister();
19134 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19135 EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19136 (encoded_align_2.GetEncodingValue() << 4) |
19137 first.Encode(22, 12) | (len_encoding << 5) |
19138 (rn.GetCode() << 16));
19139 AdvanceIT();
19140 return;
19141 }
19142 }
19143 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19144 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19145 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19146 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019147 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019148 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019149 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19150 const DRegister& first = nreglist.GetFirstDRegister();
19151 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19152 EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19153 (encoded_align_2.GetEncodingValue() << 4) |
19154 first.Encode(22, 12) | (len_encoding << 5) |
19155 (rn.GetCode() << 16));
19156 AdvanceIT();
19157 return;
19158 }
19159 }
19160 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19161 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19162 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19163 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019164 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019165 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019166 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19167 const DRegister& first = nreglist.GetFirstDRegister();
19168 EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19169 (encoded_align_3.GetEncodingValue() << 4) |
19170 first.Encode(22, 12) | (rn.GetCode() << 16));
19171 AdvanceIT();
19172 return;
19173 }
19174 }
19175 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19176 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19177 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19178 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019179 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019180 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019181 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19182 const DRegister& first = nreglist.GetFirstDRegister();
19183 EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19184 (encoded_align_3.GetEncodingValue() << 4) |
19185 first.Encode(22, 12) | (rn.GetCode() << 16));
19186 AdvanceIT();
19187 return;
19188 }
19189 }
19190 } else {
19191 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19192 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19193 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19194 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019195 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019196 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019197 if (cond.Is(al)) {
19198 const DRegister& first = nreglist.GetFirstDRegister();
19199 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19200 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
19201 (encoded_align_1.GetEncodingValue() << 4) |
19202 first.Encode(22, 12) | (len_encoding << 8) |
19203 (rn.GetCode() << 16));
19204 return;
19205 }
19206 }
19207 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19208 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19209 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19210 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019211 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019212 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019213 if (cond.Is(al)) {
19214 const DRegister& first = nreglist.GetFirstDRegister();
19215 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19216 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
19217 (encoded_align_1.GetEncodingValue() << 4) |
19218 first.Encode(22, 12) | (len_encoding << 8) |
19219 (rn.GetCode() << 16));
19220 return;
19221 }
19222 }
19223 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19224 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19225 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19226 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019227 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019228 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019229 if (cond.Is(al)) {
19230 const DRegister& first = nreglist.GetFirstDRegister();
19231 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19232 EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19233 (encoded_align_2.GetEncodingValue() << 4) |
19234 first.Encode(22, 12) | (len_encoding << 5) |
19235 (rn.GetCode() << 16));
19236 return;
19237 }
19238 }
19239 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19240 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19241 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19242 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019243 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019244 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019245 if (cond.Is(al)) {
19246 const DRegister& first = nreglist.GetFirstDRegister();
19247 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19248 EmitA32(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19249 (encoded_align_2.GetEncodingValue() << 4) |
19250 first.Encode(22, 12) | (len_encoding << 5) |
19251 (rn.GetCode() << 16));
19252 return;
19253 }
19254 }
19255 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19256 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19257 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19258 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019259 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019260 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019261 if (cond.Is(al)) {
19262 const DRegister& first = nreglist.GetFirstDRegister();
19263 EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19264 (encoded_align_3.GetEncodingValue() << 4) |
19265 first.Encode(22, 12) | (rn.GetCode() << 16));
19266 return;
19267 }
19268 }
19269 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19270 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19271 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19272 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019273 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019274 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019275 if (cond.Is(al)) {
19276 const DRegister& first = nreglist.GetFirstDRegister();
19277 EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19278 (encoded_align_3.GetEncodingValue() << 4) |
19279 first.Encode(22, 12) | (rn.GetCode() << 16));
19280 return;
19281 }
19282 }
19283 }
19284 }
19285 if (operand.IsPlainRegister()) {
19286 Register rn = operand.GetBaseRegister();
19287 Alignment align = operand.GetAlignment();
19288 Register rm = operand.GetOffsetRegister();
19289 Dt_size_7 encoded_dt(dt);
19290 Dt_size_8 encoded_dt_2(dt, align);
19291 Align_align_4 encoded_align_1(align);
19292 Align_a_3 encoded_align_2(align, dt);
19293 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019294 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019295 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19296 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19297 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19298 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019299 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019300 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19301 const DRegister& first = nreglist.GetFirstDRegister();
19302 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19303 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
19304 (encoded_align_1.GetEncodingValue() << 4) |
19305 first.Encode(22, 12) | (len_encoding << 8) |
19306 (rn.GetCode() << 16) | rm.GetCode());
19307 AdvanceIT();
19308 return;
19309 }
19310 }
19311 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19312 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19313 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19314 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019315 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019316 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19317 const DRegister& first = nreglist.GetFirstDRegister();
19318 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19319 EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19320 (encoded_align_2.GetEncodingValue() << 4) |
19321 first.Encode(22, 12) | (len_encoding << 5) |
19322 (rn.GetCode() << 16) | rm.GetCode());
19323 AdvanceIT();
19324 return;
19325 }
19326 }
19327 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19328 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19329 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19330 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019331 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019332 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19333 const DRegister& first = nreglist.GetFirstDRegister();
19334 EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
19335 (encoded_align_3.GetEncodingValue() << 4) |
19336 first.Encode(22, 12) | (rn.GetCode() << 16) |
19337 rm.GetCode());
19338 AdvanceIT();
19339 return;
19340 }
19341 }
19342 } else {
19343 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19344 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19345 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19346 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019347 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019348 if (cond.Is(al)) {
19349 const DRegister& first = nreglist.GetFirstDRegister();
19350 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19351 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
19352 (encoded_align_1.GetEncodingValue() << 4) |
19353 first.Encode(22, 12) | (len_encoding << 8) |
19354 (rn.GetCode() << 16) | rm.GetCode());
19355 return;
19356 }
19357 }
19358 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19359 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19360 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19361 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019362 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019363 if (cond.Is(al)) {
19364 const DRegister& first = nreglist.GetFirstDRegister();
19365 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19366 EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19367 (encoded_align_2.GetEncodingValue() << 4) |
19368 first.Encode(22, 12) | (len_encoding << 5) |
19369 (rn.GetCode() << 16) | rm.GetCode());
19370 return;
19371 }
19372 }
19373 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19374 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19375 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19376 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019377 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019378 if (cond.Is(al)) {
19379 const DRegister& first = nreglist.GetFirstDRegister();
19380 EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
19381 (encoded_align_3.GetEncodingValue() << 4) |
19382 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19383 return;
19384 }
19385 }
19386 }
19387 }
19388 Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
19389}
19390
19391void Assembler::vldm(Condition cond,
19392 DataType dt,
19393 Register rn,
19394 WriteBack write_back,
19395 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019396 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019397 CheckIT(cond);
19398 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019399 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019400 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019401 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19402 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019403 const DRegister& dreg = dreglist.GetFirstDRegister();
19404 unsigned len = dreglist.GetLength() * 2;
19405 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19406 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19407 (len & 0xff));
19408 AdvanceIT();
19409 return;
19410 }
19411 } else {
19412 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019413 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19414 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19415 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019416 const DRegister& dreg = dreglist.GetFirstDRegister();
19417 unsigned len = dreglist.GetLength() * 2;
19418 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19419 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19420 (len & 0xff));
19421 return;
19422 }
19423 }
19424 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
19425}
19426
19427void Assembler::vldm(Condition cond,
19428 DataType dt,
19429 Register rn,
19430 WriteBack write_back,
19431 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019432 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019433 CheckIT(cond);
19434 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019435 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019436 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019437 if ((!rn.IsPC() || AllowUnpredictable())) {
19438 const SRegister& sreg = sreglist.GetFirstSRegister();
19439 unsigned len = sreglist.GetLength();
19440 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19441 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19442 (len & 0xff));
19443 AdvanceIT();
19444 return;
19445 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010019446 } else {
19447 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019448 if (cond.IsNotNever() &&
19449 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019450 const SRegister& sreg = sreglist.GetFirstSRegister();
19451 unsigned len = sreglist.GetLength();
19452 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19453 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19454 (len & 0xff));
19455 return;
19456 }
19457 }
19458 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
19459}
19460
19461void Assembler::vldmdb(Condition cond,
19462 DataType dt,
19463 Register rn,
19464 WriteBack write_back,
19465 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019466 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019467 CheckIT(cond);
19468 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019469 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019470 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
19471 if (write_back.DoesWriteBack() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019472 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19473 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019474 const DRegister& dreg = dreglist.GetFirstDRegister();
19475 unsigned len = dreglist.GetLength() * 2;
19476 EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
19477 (len & 0xff));
19478 AdvanceIT();
19479 return;
19480 }
19481 } else {
19482 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
19483 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019484 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19485 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019486 const DRegister& dreg = dreglist.GetFirstDRegister();
19487 unsigned len = dreglist.GetLength() * 2;
19488 EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19489 dreg.Encode(22, 12) | (len & 0xff));
19490 return;
19491 }
19492 }
19493 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
19494}
19495
19496void Assembler::vldmdb(Condition cond,
19497 DataType dt,
19498 Register rn,
19499 WriteBack write_back,
19500 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019501 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019502 CheckIT(cond);
19503 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019504 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019505 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019506 if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019507 const SRegister& sreg = sreglist.GetFirstSRegister();
19508 unsigned len = sreglist.GetLength();
19509 EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
19510 (len & 0xff));
19511 AdvanceIT();
19512 return;
19513 }
19514 } else {
19515 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019516 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
19517 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019518 const SRegister& sreg = sreglist.GetFirstSRegister();
19519 unsigned len = sreglist.GetLength();
19520 EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19521 sreg.Encode(22, 12) | (len & 0xff));
19522 return;
19523 }
19524 }
19525 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
19526}
19527
19528void Assembler::vldmia(Condition cond,
19529 DataType dt,
19530 Register rn,
19531 WriteBack write_back,
19532 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019534 CheckIT(cond);
19535 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019536 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019537 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019538 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
19539 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019540 const DRegister& dreg = dreglist.GetFirstDRegister();
19541 unsigned len = dreglist.GetLength() * 2;
19542 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19543 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19544 (len & 0xff));
19545 AdvanceIT();
19546 return;
19547 }
19548 } else {
19549 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019550 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
19551 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
19552 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019553 const DRegister& dreg = dreglist.GetFirstDRegister();
19554 unsigned len = dreglist.GetLength() * 2;
19555 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19556 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19557 (len & 0xff));
19558 return;
19559 }
19560 }
19561 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
19562}
19563
19564void Assembler::vldmia(Condition cond,
19565 DataType dt,
19566 Register rn,
19567 WriteBack write_back,
19568 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019569 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019570 CheckIT(cond);
19571 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019572 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019573 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019574 if ((!rn.IsPC() || AllowUnpredictable())) {
19575 const SRegister& sreg = sreglist.GetFirstSRegister();
19576 unsigned len = sreglist.GetLength();
19577 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19578 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19579 (len & 0xff));
19580 AdvanceIT();
19581 return;
19582 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010019583 } else {
19584 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070019585 if (cond.IsNotNever() &&
19586 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019587 const SRegister& sreg = sreglist.GetFirstSRegister();
19588 unsigned len = sreglist.GetLength();
19589 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19590 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19591 (len & 0xff));
19592 return;
19593 }
19594 }
19595 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
19596}
19597
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019598void Assembler::vldr(Condition cond,
19599 DataType dt,
19600 DRegister rd,
19601 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019602 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019603 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019604 Location::Offset offset =
19605 location->IsBound()
19606 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +010019607 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19608 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019609 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019610 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19611 if (dt.IsNoneOr(Untyped64) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019612 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019613 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019614 !location->IsBound())) {
19615 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019616 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019617 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019618 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019619 Location::Offset pc,
19620 const Location* location) const VIXL_OVERRIDE {
19621 pc += kT32PcDelta;
19622 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019623 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19624 ((offset & 0x3) == 0));
19625 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019626 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019627 target = abs(target) | (U << 8);
19628 return instr | (target & 0xff) | ((target & 0x100) << 15);
19629 }
19630 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -070019631 EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12),
19632 location,
19633 immop,
19634 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019635 AdvanceIT();
19636 return;
19637 }
19638 } else {
19639 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19640 if (dt.IsNoneOr(Untyped64) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019641 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019642 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019643 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019644 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019645 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019646 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019647 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019648 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019649 Location::Offset pc,
19650 const Location* location) const VIXL_OVERRIDE {
19651 pc += kA32PcDelta;
19652 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019653 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19654 ((offset & 0x3) == 0));
19655 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019656 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019657 target = abs(target) | (U << 8);
19658 return instr | (target & 0xff) | ((target & 0x100) << 15);
19659 }
19660 } immop;
19661 EmitA32(
19662 Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019663 location,
19664 immop,
Vincent Belliardac285442017-05-16 09:26:45 -070019665 &kA32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019666 return;
19667 }
19668 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019669 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019670}
19671
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019672bool Assembler::vldr_info(Condition cond,
19673 DataType dt,
19674 DRegister rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019675 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019676 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019677 VIXL_ASSERT(!location->IsBound());
19678 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019679 USE(rd);
19680 if (IsUsingT32()) {
19681 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19682 if (dt.IsNoneOr(Untyped64)) {
Vincent Belliardac285442017-05-16 09:26:45 -070019683 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019684 return true;
19685 }
19686 } else {
19687 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19688 if (dt.IsNoneOr(Untyped64) && cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -070019689 *info = &kA32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019690 return true;
19691 }
19692 }
19693 return false;
19694}
19695
Alexandre Ramesd3832962016-07-04 15:03:43 +010019696void Assembler::vldr(Condition cond,
19697 DataType dt,
19698 DRegister rd,
19699 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019700 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019701 CheckIT(cond);
19702 if (operand.IsImmediate()) {
19703 Register rn = operand.GetBaseRegister();
19704 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019705 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019706 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
19707 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019708 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019709 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19710 uint32_t offset_ = abs(offset) >> 2;
19711 EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19712 AdvanceIT();
19713 return;
19714 }
19715 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
19716 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019717 ((offset % 4) == 0) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019718 ((rn.GetCode() & 0xf) != 0xf)) {
19719 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19720 uint32_t offset_ = abs(offset) >> 2;
19721 EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19722 offset_ | (sign << 23));
19723 AdvanceIT();
19724 return;
19725 }
19726 } else {
19727 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
19728 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019729 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19730 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019731 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19732 uint32_t offset_ = abs(offset) >> 2;
19733 EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19734 offset_ | (sign << 23));
19735 return;
19736 }
19737 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
19738 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019739 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19740 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019741 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19742 uint32_t offset_ = abs(offset) >> 2;
19743 EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19744 (rn.GetCode() << 16) | offset_ | (sign << 23));
19745 return;
19746 }
19747 }
19748 }
19749 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19750}
19751
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019752void Assembler::vldr(Condition cond,
19753 DataType dt,
19754 SRegister rd,
19755 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019756 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019757 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019758 Location::Offset offset =
19759 location->IsBound()
19760 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +010019761 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19762 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019763 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019764 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19765 if (dt.IsNoneOr(Untyped32) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019766 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019767 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019768 !location->IsBound())) {
19769 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019770 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019771 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019772 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019773 Location::Offset pc,
19774 const Location* location) const VIXL_OVERRIDE {
19775 pc += kT32PcDelta;
19776 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019777 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19778 ((offset & 0x3) == 0));
19779 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019780 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019781 target = abs(target) | (U << 8);
19782 return instr | (target & 0xff) | ((target & 0x100) << 15);
19783 }
19784 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -070019785 EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12),
19786 location,
19787 immop,
19788 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019789 AdvanceIT();
19790 return;
19791 }
19792 } else {
19793 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19794 if (dt.IsNoneOr(Untyped32) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019795 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019796 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019797 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019798 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019799 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019800 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019801 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019802 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019803 Location::Offset pc,
19804 const Location* location) const VIXL_OVERRIDE {
19805 pc += kA32PcDelta;
19806 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019807 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19808 ((offset & 0x3) == 0));
19809 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019810 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019811 target = abs(target) | (U << 8);
19812 return instr | (target & 0xff) | ((target & 0x100) << 15);
19813 }
19814 } immop;
19815 EmitA32(
19816 Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019817 location,
19818 immop,
Vincent Belliardac285442017-05-16 09:26:45 -070019819 &kA32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019820 return;
19821 }
19822 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019823 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019824}
19825
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019826bool Assembler::vldr_info(Condition cond,
19827 DataType dt,
19828 SRegister rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019829 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019830 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019831 VIXL_ASSERT(!location->IsBound());
19832 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019833 USE(rd);
19834 if (IsUsingT32()) {
19835 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19836 if (dt.IsNoneOr(Untyped32)) {
Vincent Belliardac285442017-05-16 09:26:45 -070019837 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019838 return true;
19839 }
19840 } else {
19841 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19842 if (dt.IsNoneOr(Untyped32) && cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -070019843 *info = &kA32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019844 return true;
19845 }
19846 }
19847 return false;
19848}
19849
Alexandre Ramesd3832962016-07-04 15:03:43 +010019850void Assembler::vldr(Condition cond,
19851 DataType dt,
19852 SRegister rd,
19853 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019854 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019855 CheckIT(cond);
19856 if (operand.IsImmediate()) {
19857 Register rn = operand.GetBaseRegister();
19858 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019859 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019860 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
19861 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019862 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019863 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19864 uint32_t offset_ = abs(offset) >> 2;
19865 EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19866 AdvanceIT();
19867 return;
19868 }
19869 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
19870 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019871 ((offset % 4) == 0) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019872 ((rn.GetCode() & 0xf) != 0xf)) {
19873 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19874 uint32_t offset_ = abs(offset) >> 2;
19875 EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19876 offset_ | (sign << 23));
19877 AdvanceIT();
19878 return;
19879 }
19880 } else {
19881 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
19882 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019883 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19884 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019885 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19886 uint32_t offset_ = abs(offset) >> 2;
19887 EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19888 offset_ | (sign << 23));
19889 return;
19890 }
19891 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
19892 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019893 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19894 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019895 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19896 uint32_t offset_ = abs(offset) >> 2;
19897 EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19898 (rn.GetCode() << 16) | offset_ | (sign << 23));
19899 return;
19900 }
19901 }
19902 }
19903 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19904}
19905
19906void Assembler::vmax(
19907 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019908 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019909 CheckIT(cond);
19910 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019911 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019912 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
19913 if (dt.Is(F32)) {
19914 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19915 EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19916 rm.Encode(5, 0));
19917 AdvanceIT();
19918 return;
19919 }
19920 }
19921 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
19922 if (encoded_dt.IsValid()) {
19923 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19924 EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19925 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19926 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19927 AdvanceIT();
19928 return;
19929 }
19930 }
19931 } else {
19932 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
19933 if (dt.Is(F32)) {
19934 if (cond.Is(al)) {
19935 EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19936 rm.Encode(5, 0));
19937 return;
19938 }
19939 }
19940 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
19941 if (encoded_dt.IsValid()) {
19942 if (cond.Is(al)) {
19943 EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19944 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19945 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19946 return;
19947 }
19948 }
19949 }
19950 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19951}
19952
19953void Assembler::vmax(
19954 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019955 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019956 CheckIT(cond);
19957 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019958 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019959 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
19960 if (dt.Is(F32)) {
19961 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19962 EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19963 rm.Encode(5, 0));
19964 AdvanceIT();
19965 return;
19966 }
19967 }
19968 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
19969 if (encoded_dt.IsValid()) {
19970 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19971 EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19972 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19973 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19974 AdvanceIT();
19975 return;
19976 }
19977 }
19978 } else {
19979 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
19980 if (dt.Is(F32)) {
19981 if (cond.Is(al)) {
19982 EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19983 rm.Encode(5, 0));
19984 return;
19985 }
19986 }
19987 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
19988 if (encoded_dt.IsValid()) {
19989 if (cond.Is(al)) {
19990 EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19991 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19992 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19993 return;
19994 }
19995 }
19996 }
19997 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19998}
19999
20000void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020001 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020002 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020003 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020004 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20005 if (OutsideITBlock() && dt.Is(F32)) {
20006 EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20007 rm.Encode(5, 0));
20008 AdvanceIT();
20009 return;
20010 }
20011 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20012 if (OutsideITBlock() && dt.Is(F64)) {
20013 EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20014 rm.Encode(5, 0));
20015 AdvanceIT();
20016 return;
20017 }
20018 } else {
20019 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20020 if (dt.Is(F32)) {
20021 EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20022 rm.Encode(5, 0));
20023 return;
20024 }
20025 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20026 if (dt.Is(F64)) {
20027 EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20028 rm.Encode(5, 0));
20029 return;
20030 }
20031 }
20032 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20033}
20034
20035void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020036 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020037 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020038 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020039 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20040 if (OutsideITBlock() && dt.Is(F32)) {
20041 EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20042 rm.Encode(5, 0));
20043 AdvanceIT();
20044 return;
20045 }
20046 } else {
20047 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20048 if (dt.Is(F32)) {
20049 EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20050 rm.Encode(5, 0));
20051 return;
20052 }
20053 }
20054 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20055}
20056
20057void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020058 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020059 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020060 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020061 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20062 if (OutsideITBlock() && dt.Is(F32)) {
20063 EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20064 rm.Encode(5, 0));
20065 AdvanceIT();
20066 return;
20067 }
20068 } else {
20069 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20070 if (dt.Is(F32)) {
20071 EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20072 rm.Encode(5, 0));
20073 return;
20074 }
20075 }
20076 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20077}
20078
20079void Assembler::vmin(
20080 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020081 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020082 CheckIT(cond);
20083 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020084 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020085 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20086 if (dt.Is(F32)) {
20087 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20088 EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20089 rm.Encode(5, 0));
20090 AdvanceIT();
20091 return;
20092 }
20093 }
20094 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20095 if (encoded_dt.IsValid()) {
20096 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20097 EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20098 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20099 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20100 AdvanceIT();
20101 return;
20102 }
20103 }
20104 } else {
20105 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20106 if (dt.Is(F32)) {
20107 if (cond.Is(al)) {
20108 EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20109 rm.Encode(5, 0));
20110 return;
20111 }
20112 }
20113 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20114 if (encoded_dt.IsValid()) {
20115 if (cond.Is(al)) {
20116 EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20117 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20118 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20119 return;
20120 }
20121 }
20122 }
20123 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20124}
20125
20126void Assembler::vmin(
20127 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020128 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020129 CheckIT(cond);
20130 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020131 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020132 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20133 if (dt.Is(F32)) {
20134 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20135 EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20136 rm.Encode(5, 0));
20137 AdvanceIT();
20138 return;
20139 }
20140 }
20141 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20142 if (encoded_dt.IsValid()) {
20143 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20144 EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20145 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20146 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20147 AdvanceIT();
20148 return;
20149 }
20150 }
20151 } else {
20152 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20153 if (dt.Is(F32)) {
20154 if (cond.Is(al)) {
20155 EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20156 rm.Encode(5, 0));
20157 return;
20158 }
20159 }
20160 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20161 if (encoded_dt.IsValid()) {
20162 if (cond.Is(al)) {
20163 EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20164 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20165 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20166 return;
20167 }
20168 }
20169 }
20170 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20171}
20172
20173void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020174 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020175 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020176 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020177 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20178 if (OutsideITBlock() && dt.Is(F32)) {
20179 EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20180 rm.Encode(5, 0));
20181 AdvanceIT();
20182 return;
20183 }
20184 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20185 if (OutsideITBlock() && dt.Is(F64)) {
20186 EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20187 rm.Encode(5, 0));
20188 AdvanceIT();
20189 return;
20190 }
20191 } else {
20192 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20193 if (dt.Is(F32)) {
20194 EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20195 rm.Encode(5, 0));
20196 return;
20197 }
20198 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20199 if (dt.Is(F64)) {
20200 EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20201 rm.Encode(5, 0));
20202 return;
20203 }
20204 }
20205 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20206}
20207
20208void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020209 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020210 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020211 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020212 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20213 if (OutsideITBlock() && dt.Is(F32)) {
20214 EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20215 rm.Encode(5, 0));
20216 AdvanceIT();
20217 return;
20218 }
20219 } else {
20220 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20221 if (dt.Is(F32)) {
20222 EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20223 rm.Encode(5, 0));
20224 return;
20225 }
20226 }
20227 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20228}
20229
20230void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020231 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020232 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020233 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020234 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20235 if (OutsideITBlock() && dt.Is(F32)) {
20236 EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20237 rm.Encode(5, 0));
20238 AdvanceIT();
20239 return;
20240 }
20241 } else {
20242 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20243 if (dt.Is(F32)) {
20244 EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20245 rm.Encode(5, 0));
20246 return;
20247 }
20248 }
20249 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20250}
20251
20252void Assembler::vmla(
20253 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020254 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020255 CheckIT(cond);
20256 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020257 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020258 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20259 if (encoded_dt.IsValid() &&
20260 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20261 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20262 (rm.GetLane() <= 1)))) {
20263 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20264 EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20265 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20266 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20267 AdvanceIT();
20268 return;
20269 }
20270 }
20271 } else {
20272 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20273 if (encoded_dt.IsValid() &&
20274 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20275 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20276 (rm.GetLane() <= 1)))) {
20277 if (cond.Is(al)) {
20278 EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20279 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20280 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20281 return;
20282 }
20283 }
20284 }
20285 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20286}
20287
20288void Assembler::vmla(
20289 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020290 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020291 CheckIT(cond);
20292 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020293 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020294 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20295 if (encoded_dt.IsValid() &&
20296 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20297 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20298 (rm.GetLane() <= 1)))) {
20299 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20300 EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20301 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20302 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20303 AdvanceIT();
20304 return;
20305 }
20306 }
20307 } else {
20308 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20309 if (encoded_dt.IsValid() &&
20310 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20311 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20312 (rm.GetLane() <= 1)))) {
20313 if (cond.Is(al)) {
20314 EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20315 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20316 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20317 return;
20318 }
20319 }
20320 }
20321 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20322}
20323
20324void Assembler::vmla(
20325 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020326 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020327 CheckIT(cond);
20328 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020329 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020330 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20331 if (dt.Is(F32)) {
20332 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20333 EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20334 rm.Encode(5, 0));
20335 AdvanceIT();
20336 return;
20337 }
20338 }
20339 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20340 if (dt.Is(F64)) {
20341 EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20342 rm.Encode(5, 0));
20343 AdvanceIT();
20344 return;
20345 }
20346 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20347 if (encoded_dt.IsValid()) {
20348 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20349 EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
20350 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20351 AdvanceIT();
20352 return;
20353 }
20354 }
20355 } else {
20356 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20357 if (dt.Is(F32)) {
20358 if (cond.Is(al)) {
20359 EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20360 rm.Encode(5, 0));
20361 return;
20362 }
20363 }
20364 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20365 if (dt.Is(F64) && cond.IsNotNever()) {
20366 EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20367 rn.Encode(7, 16) | rm.Encode(5, 0));
20368 return;
20369 }
20370 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20371 if (encoded_dt.IsValid()) {
20372 if (cond.Is(al)) {
20373 EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
20374 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20375 return;
20376 }
20377 }
20378 }
20379 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20380}
20381
20382void Assembler::vmla(
20383 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020384 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020385 CheckIT(cond);
20386 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020387 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020388 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20389 if (dt.Is(F32)) {
20390 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20391 EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20392 rm.Encode(5, 0));
20393 AdvanceIT();
20394 return;
20395 }
20396 }
20397 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20398 if (encoded_dt.IsValid()) {
20399 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20400 EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
20401 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20402 AdvanceIT();
20403 return;
20404 }
20405 }
20406 } else {
20407 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20408 if (dt.Is(F32)) {
20409 if (cond.Is(al)) {
20410 EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20411 rm.Encode(5, 0));
20412 return;
20413 }
20414 }
20415 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20416 if (encoded_dt.IsValid()) {
20417 if (cond.Is(al)) {
20418 EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
20419 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20420 return;
20421 }
20422 }
20423 }
20424 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20425}
20426
20427void Assembler::vmla(
20428 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020429 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020430 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020431 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020432 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20433 if (dt.Is(F32)) {
20434 EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20435 rm.Encode(5, 0));
20436 AdvanceIT();
20437 return;
20438 }
20439 } else {
20440 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20441 if (dt.Is(F32) && cond.IsNotNever()) {
20442 EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20443 rn.Encode(7, 16) | rm.Encode(5, 0));
20444 return;
20445 }
20446 }
20447 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20448}
20449
20450void Assembler::vmlal(
20451 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020452 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020453 CheckIT(cond);
20454 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020455 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020456 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20457 if (encoded_dt.IsValid() &&
20458 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20459 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20460 (rm.GetLane() <= 1)))) {
20461 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20462 EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
20463 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20464 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20465 AdvanceIT();
20466 return;
20467 }
20468 }
20469 } else {
20470 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20471 if (encoded_dt.IsValid() &&
20472 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20473 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20474 (rm.GetLane() <= 1)))) {
20475 if (cond.Is(al)) {
20476 EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
20477 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20478 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20479 return;
20480 }
20481 }
20482 }
20483 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20484}
20485
20486void Assembler::vmlal(
20487 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020488 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020489 CheckIT(cond);
20490 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020491 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020492 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20493 if (encoded_dt.IsValid()) {
20494 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20495 EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
20496 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20497 rn.Encode(7, 16) | rm.Encode(5, 0));
20498 AdvanceIT();
20499 return;
20500 }
20501 }
20502 } else {
20503 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20504 if (encoded_dt.IsValid()) {
20505 if (cond.Is(al)) {
20506 EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
20507 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20508 rn.Encode(7, 16) | rm.Encode(5, 0));
20509 return;
20510 }
20511 }
20512 }
20513 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20514}
20515
20516void Assembler::vmls(
20517 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020518 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020519 CheckIT(cond);
20520 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020521 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020522 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20523 if (encoded_dt.IsValid() &&
20524 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20525 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20526 (rm.GetLane() <= 1)))) {
20527 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20528 EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20529 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20530 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20531 AdvanceIT();
20532 return;
20533 }
20534 }
20535 } else {
20536 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20537 if (encoded_dt.IsValid() &&
20538 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20539 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20540 (rm.GetLane() <= 1)))) {
20541 if (cond.Is(al)) {
20542 EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20543 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20544 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20545 return;
20546 }
20547 }
20548 }
20549 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20550}
20551
20552void Assembler::vmls(
20553 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020554 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020555 CheckIT(cond);
20556 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020557 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020558 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20559 if (encoded_dt.IsValid() &&
20560 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20561 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20562 (rm.GetLane() <= 1)))) {
20563 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20564 EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20565 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20566 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20567 AdvanceIT();
20568 return;
20569 }
20570 }
20571 } else {
20572 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20573 if (encoded_dt.IsValid() &&
20574 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20575 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20576 (rm.GetLane() <= 1)))) {
20577 if (cond.Is(al)) {
20578 EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20579 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20580 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20581 return;
20582 }
20583 }
20584 }
20585 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20586}
20587
20588void Assembler::vmls(
20589 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020590 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020591 CheckIT(cond);
20592 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020593 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020594 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20595 if (dt.Is(F32)) {
20596 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20597 EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20598 rm.Encode(5, 0));
20599 AdvanceIT();
20600 return;
20601 }
20602 }
20603 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20604 if (dt.Is(F64)) {
20605 EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20606 rm.Encode(5, 0));
20607 AdvanceIT();
20608 return;
20609 }
20610 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20611 if (encoded_dt.IsValid()) {
20612 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20613 EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
20614 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20615 AdvanceIT();
20616 return;
20617 }
20618 }
20619 } else {
20620 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20621 if (dt.Is(F32)) {
20622 if (cond.Is(al)) {
20623 EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20624 rm.Encode(5, 0));
20625 return;
20626 }
20627 }
20628 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20629 if (dt.Is(F64) && cond.IsNotNever()) {
20630 EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20631 rn.Encode(7, 16) | rm.Encode(5, 0));
20632 return;
20633 }
20634 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20635 if (encoded_dt.IsValid()) {
20636 if (cond.Is(al)) {
20637 EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
20638 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20639 return;
20640 }
20641 }
20642 }
20643 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20644}
20645
20646void Assembler::vmls(
20647 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020648 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020649 CheckIT(cond);
20650 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020652 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20653 if (dt.Is(F32)) {
20654 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20655 EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20656 rm.Encode(5, 0));
20657 AdvanceIT();
20658 return;
20659 }
20660 }
20661 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20662 if (encoded_dt.IsValid()) {
20663 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20664 EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
20665 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20666 AdvanceIT();
20667 return;
20668 }
20669 }
20670 } else {
20671 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20672 if (dt.Is(F32)) {
20673 if (cond.Is(al)) {
20674 EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20675 rm.Encode(5, 0));
20676 return;
20677 }
20678 }
20679 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20680 if (encoded_dt.IsValid()) {
20681 if (cond.Is(al)) {
20682 EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
20683 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20684 return;
20685 }
20686 }
20687 }
20688 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20689}
20690
20691void Assembler::vmls(
20692 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020693 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020694 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020695 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020696 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20697 if (dt.Is(F32)) {
20698 EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20699 rm.Encode(5, 0));
20700 AdvanceIT();
20701 return;
20702 }
20703 } else {
20704 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20705 if (dt.Is(F32) && cond.IsNotNever()) {
20706 EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20707 rn.Encode(7, 16) | rm.Encode(5, 0));
20708 return;
20709 }
20710 }
20711 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20712}
20713
20714void Assembler::vmlsl(
20715 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020716 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020717 CheckIT(cond);
20718 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020719 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020720 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20721 if (encoded_dt.IsValid() &&
20722 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20723 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20724 (rm.GetLane() <= 1)))) {
20725 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20726 EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
20727 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20728 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20729 AdvanceIT();
20730 return;
20731 }
20732 }
20733 } else {
20734 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20735 if (encoded_dt.IsValid() &&
20736 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20737 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20738 (rm.GetLane() <= 1)))) {
20739 if (cond.Is(al)) {
20740 EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
20741 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20742 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20743 return;
20744 }
20745 }
20746 }
20747 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20748}
20749
20750void Assembler::vmlsl(
20751 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020752 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020753 CheckIT(cond);
20754 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020756 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20757 if (encoded_dt.IsValid()) {
20758 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20759 EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
20760 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20761 rn.Encode(7, 16) | rm.Encode(5, 0));
20762 AdvanceIT();
20763 return;
20764 }
20765 }
20766 } else {
20767 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20768 if (encoded_dt.IsValid()) {
20769 if (cond.Is(al)) {
20770 EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
20771 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20772 rn.Encode(7, 16) | rm.Encode(5, 0));
20773 return;
20774 }
20775 }
20776 }
20777 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20778}
20779
20780void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
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>, <Sn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020785 if ((!rt.IsPC() || AllowUnpredictable())) {
20786 EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
20787 AdvanceIT();
20788 return;
20789 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020790 } else {
20791 // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020792 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020793 EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20794 rn.Encode(7, 16));
20795 return;
20796 }
20797 }
20798 Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
20799}
20800
20801void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020802 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020803 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020804 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020805 // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020806 if ((!rt.IsPC() || AllowUnpredictable())) {
20807 EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
20808 AdvanceIT();
20809 return;
20810 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020811 } else {
20812 // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020813 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020814 EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
20815 (rt.GetCode() << 12));
20816 return;
20817 }
20818 }
20819 Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
20820}
20821
20822void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020823 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020824 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020825 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020826 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020827 if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20828 EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20829 rm.Encode(5, 0));
20830 AdvanceIT();
20831 return;
20832 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020833 } else {
20834 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020835 if (cond.IsNotNever() &&
20836 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020837 EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20838 (rt2.GetCode() << 16) | rm.Encode(5, 0));
20839 return;
20840 }
20841 }
20842 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
20843}
20844
20845void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020846 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020847 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020848 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020849 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020850 if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20851 EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20852 (rt2.GetCode() << 16));
20853 AdvanceIT();
20854 return;
20855 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020856 } else {
20857 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020858 if (cond.IsNotNever() &&
20859 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020860 EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20861 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20862 return;
20863 }
20864 }
20865 Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
20866}
20867
20868void Assembler::vmov(
20869 Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020870 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020871 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020872 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020873 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020874 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20875 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020876 EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20877 rm.Encode(5, 0));
20878 AdvanceIT();
20879 return;
20880 }
20881 } else {
20882 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
20883 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000020884 cond.IsNotNever() &&
20885 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020886 EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20887 (rt2.GetCode() << 16) | rm.Encode(5, 0));
20888 return;
20889 }
20890 }
20891 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
20892}
20893
20894void Assembler::vmov(
20895 Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020896 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020897 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020898 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020899 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020900 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20901 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020902 EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20903 (rt2.GetCode() << 16));
20904 AdvanceIT();
20905 return;
20906 }
20907 } else {
20908 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
20909 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000020910 cond.IsNotNever() &&
20911 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020912 EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20913 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20914 return;
20915 }
20916 }
20917 Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
20918}
20919
20920void Assembler::vmov(Condition cond,
20921 DataType dt,
20922 DRegisterLane rd,
20923 Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020924 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020925 CheckIT(cond);
20926 Dt_opc1_opc2_1 encoded_dt(dt, rd);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020927 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020928 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020929 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020930 EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20931 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
20932 rd.Encode(7, 16) | (rt.GetCode() << 12));
20933 AdvanceIT();
20934 return;
20935 }
20936 } else {
20937 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020938 if (encoded_dt.IsValid() && cond.IsNotNever() &&
20939 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020940 EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
20941 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20942 ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
20943 (rt.GetCode() << 12));
20944 return;
20945 }
20946 }
20947 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
20948}
20949
20950void Assembler::vmov(Condition cond,
20951 DataType dt,
20952 DRegister rd,
20953 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020954 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020955 CheckIT(cond);
20956 if (operand.IsImmediate()) {
20957 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020958 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020959 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20960 if (encoded_dt.IsValid()) {
20961 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20962 EmitT32_32(
20963 0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20964 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20965 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20966 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20967 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20968 AdvanceIT();
20969 return;
20970 }
20971 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020972 } else {
20973 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20974 if (encoded_dt.IsValid()) {
20975 if (cond.Is(al)) {
20976 EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20977 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20978 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20979 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20980 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20981 return;
20982 }
20983 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070020984 }
20985 }
20986 if (operand.IsImmediate()) {
20987 ImmediateVFP vfp(operand.GetNeonImmediate());
20988 if (IsUsingT32()) {
20989 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
20990 if (dt.Is(F64) && vfp.IsValid()) {
20991 EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
20992 (vfp.GetEncodingValue() & 0xf) |
20993 ((vfp.GetEncodingValue() & 0xf0) << 12));
20994 AdvanceIT();
20995 return;
20996 }
20997 } else {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020998 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
20999 if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
21000 EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21001 (vfp.GetEncodingValue() & 0xf) |
21002 ((vfp.GetEncodingValue() & 0xf0) << 12));
21003 return;
21004 }
21005 }
21006 }
21007 if (operand.IsRegister()) {
21008 DRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021009 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021010 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21011 if (dt.Is(F64)) {
21012 EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21013 AdvanceIT();
21014 return;
21015 }
21016 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21017 if (!dt.Is(F64)) {
21018 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21019 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21020 rm.Encode(5, 0));
21021 AdvanceIT();
21022 return;
21023 }
21024 }
21025 } else {
21026 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21027 if (dt.Is(F64) && cond.IsNotNever()) {
21028 EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21029 rm.Encode(5, 0));
21030 return;
21031 }
21032 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21033 if (!dt.Is(F64)) {
21034 if (cond.Is(al)) {
21035 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21036 rm.Encode(5, 0));
21037 return;
21038 }
21039 }
21040 }
21041 }
21042 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21043}
21044
21045void Assembler::vmov(Condition cond,
21046 DataType dt,
21047 QRegister rd,
21048 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021049 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021050 CheckIT(cond);
21051 if (operand.IsImmediate()) {
21052 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021053 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021054 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21055 if (encoded_dt.IsValid()) {
21056 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21057 EmitT32_32(
21058 0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21059 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21060 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21061 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21062 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21063 AdvanceIT();
21064 return;
21065 }
21066 }
21067 } else {
21068 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21069 if (encoded_dt.IsValid()) {
21070 if (cond.Is(al)) {
21071 EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21072 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21073 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21074 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21075 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21076 return;
21077 }
21078 }
21079 }
21080 }
21081 if (operand.IsRegister()) {
21082 QRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021083 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021084 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21085 if (!dt.Is(F64)) {
21086 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21087 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21088 rm.Encode(5, 0));
21089 AdvanceIT();
21090 return;
21091 }
21092 }
21093 } else {
21094 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21095 if (!dt.Is(F64)) {
21096 if (cond.Is(al)) {
21097 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21098 rm.Encode(5, 0));
21099 return;
21100 }
21101 }
21102 }
21103 }
21104 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21105}
21106
21107void Assembler::vmov(Condition cond,
21108 DataType dt,
21109 SRegister rd,
21110 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021111 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021112 CheckIT(cond);
21113 if (operand.IsImmediate()) {
21114 ImmediateVFP vfp(operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021115 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021116 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
21117 if (dt.Is(F32) && vfp.IsValid()) {
21118 EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
21119 (vfp.GetEncodingValue() & 0xf) |
21120 ((vfp.GetEncodingValue() & 0xf0) << 12));
21121 AdvanceIT();
21122 return;
21123 }
21124 } else {
21125 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
21126 if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
21127 EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21128 (vfp.GetEncodingValue() & 0xf) |
21129 ((vfp.GetEncodingValue() & 0xf0) << 12));
21130 return;
21131 }
21132 }
21133 }
21134 if (operand.IsRegister()) {
21135 SRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021136 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021137 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21138 if (dt.Is(F32)) {
21139 EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21140 AdvanceIT();
21141 return;
21142 }
21143 } else {
21144 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21145 if (dt.Is(F32) && cond.IsNotNever()) {
21146 EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21147 rm.Encode(5, 0));
21148 return;
21149 }
21150 }
21151 }
21152 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21153}
21154
21155void Assembler::vmov(Condition cond,
21156 DataType dt,
21157 Register rt,
21158 DRegisterLane rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021159 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021160 CheckIT(cond);
21161 Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021162 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021163 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021164 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021165 EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21166 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21167 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21168 (rt.GetCode() << 12) | rn.Encode(7, 16));
21169 AdvanceIT();
21170 return;
21171 }
21172 } else {
21173 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021174 if (encoded_dt.IsValid() && cond.IsNotNever() &&
21175 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021176 EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
21177 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21178 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21179 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21180 (rt.GetCode() << 12) | rn.Encode(7, 16));
21181 return;
21182 }
21183 }
21184 Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
21185}
21186
21187void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021188 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021189 CheckIT(cond);
21190 Dt_U_imm3H_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021191 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021192 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
21193 if (encoded_dt.IsValid()) {
21194 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21195 EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21196 ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
21197 rd.Encode(22, 12) | rm.Encode(5, 0));
21198 AdvanceIT();
21199 return;
21200 }
21201 }
21202 } else {
21203 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
21204 if (encoded_dt.IsValid()) {
21205 if (cond.Is(al)) {
21206 EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21207 ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
21208 rd.Encode(22, 12) | rm.Encode(5, 0));
21209 return;
21210 }
21211 }
21212 }
21213 Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
21214}
21215
21216void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021217 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021218 CheckIT(cond);
21219 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021220 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021221 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21222 if (encoded_dt.IsValid()) {
21223 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21224 EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
21225 rd.Encode(22, 12) | rm.Encode(5, 0));
21226 AdvanceIT();
21227 return;
21228 }
21229 }
21230 } else {
21231 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21232 if (encoded_dt.IsValid()) {
21233 if (cond.Is(al)) {
21234 EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
21235 rd.Encode(22, 12) | rm.Encode(5, 0));
21236 return;
21237 }
21238 }
21239 }
21240 Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
21241}
21242
21243void Assembler::vmrs(Condition cond,
21244 RegisterOrAPSR_nzcv rt,
21245 SpecialFPRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021246 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021247 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021248 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021249 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
21250 EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
21251 AdvanceIT();
21252 return;
21253 } else {
21254 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
21255 if (cond.IsNotNever()) {
21256 EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
21257 (spec_reg.GetReg() << 16));
21258 return;
21259 }
21260 }
21261 Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
21262}
21263
21264void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021265 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021266 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021267 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021268 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021269 if ((!rt.IsPC() || AllowUnpredictable())) {
21270 EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) |
21271 (rt.GetCode() << 12));
21272 AdvanceIT();
21273 return;
21274 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010021275 } else {
21276 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021277 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021278 EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
21279 (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
21280 return;
21281 }
21282 }
21283 Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
21284}
21285
21286void Assembler::vmul(Condition cond,
21287 DataType dt,
21288 DRegister rd,
21289 DRegister rn,
21290 DRegister dm,
21291 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021292 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021293 CheckIT(cond);
21294 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021295 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021296 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
21297 if (encoded_dt.IsValid() &&
21298 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021299 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021300 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21301 uint32_t shift = 4;
21302 if (dt.Is(I16)) {
21303 shift = 3;
21304 }
21305 uint32_t mvm = dm.GetCode() | index << shift;
21306 EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21307 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21308 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21309 ((mvm & 0x10) << 1));
21310 AdvanceIT();
21311 return;
21312 }
21313 }
21314 } else {
21315 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
21316 if (encoded_dt.IsValid() &&
21317 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021318 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021319 if (cond.Is(al)) {
21320 uint32_t shift = 4;
21321 if (dt.Is(I16)) {
21322 shift = 3;
21323 }
21324 uint32_t mvm = dm.GetCode() | index << shift;
21325 EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21326 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21327 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21328 ((mvm & 0x10) << 1));
21329 return;
21330 }
21331 }
21332 }
21333 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21334}
21335
21336void Assembler::vmul(Condition cond,
21337 DataType dt,
21338 QRegister rd,
21339 QRegister rn,
21340 DRegister dm,
21341 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021342 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021343 CheckIT(cond);
21344 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021345 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021346 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
21347 if (encoded_dt.IsValid() &&
21348 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021349 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021350 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21351 uint32_t shift = 4;
21352 if (dt.Is(I16)) {
21353 shift = 3;
21354 }
21355 uint32_t mvm = dm.GetCode() | index << shift;
21356 EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21357 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21358 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21359 ((mvm & 0x10) << 1));
21360 AdvanceIT();
21361 return;
21362 }
21363 }
21364 } else {
21365 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
21366 if (encoded_dt.IsValid() &&
21367 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021368 (!dt.Is(I16) && (index <= 1) && (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021369 if (cond.Is(al)) {
21370 uint32_t shift = 4;
21371 if (dt.Is(I16)) {
21372 shift = 3;
21373 }
21374 uint32_t mvm = dm.GetCode() | index << shift;
21375 EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21376 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21377 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21378 ((mvm & 0x10) << 1));
21379 return;
21380 }
21381 }
21382 }
21383 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21384}
21385
21386void Assembler::vmul(
21387 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021388 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021389 CheckIT(cond);
21390 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021391 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021392 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21393 if (dt.Is(F32)) {
21394 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21395 EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21396 rm.Encode(5, 0));
21397 AdvanceIT();
21398 return;
21399 }
21400 }
21401 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
21402 if (dt.Is(F64)) {
21403 EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21404 rm.Encode(5, 0));
21405 AdvanceIT();
21406 return;
21407 }
21408 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21409 if (encoded_dt.IsValid()) {
21410 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21411 EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21412 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21413 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21414 AdvanceIT();
21415 return;
21416 }
21417 }
21418 } else {
21419 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21420 if (dt.Is(F32)) {
21421 if (cond.Is(al)) {
21422 EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21423 rm.Encode(5, 0));
21424 return;
21425 }
21426 }
21427 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
21428 if (dt.Is(F64) && cond.IsNotNever()) {
21429 EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21430 rn.Encode(7, 16) | rm.Encode(5, 0));
21431 return;
21432 }
21433 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21434 if (encoded_dt.IsValid()) {
21435 if (cond.Is(al)) {
21436 EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21437 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21438 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21439 return;
21440 }
21441 }
21442 }
21443 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21444}
21445
21446void Assembler::vmul(
21447 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021448 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021449 CheckIT(cond);
21450 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021451 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021452 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
21453 if (dt.Is(F32)) {
21454 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21455 EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21456 rm.Encode(5, 0));
21457 AdvanceIT();
21458 return;
21459 }
21460 }
21461 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21462 if (encoded_dt.IsValid()) {
21463 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21464 EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21465 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21466 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21467 AdvanceIT();
21468 return;
21469 }
21470 }
21471 } else {
21472 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
21473 if (dt.Is(F32)) {
21474 if (cond.Is(al)) {
21475 EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21476 rm.Encode(5, 0));
21477 return;
21478 }
21479 }
21480 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21481 if (encoded_dt.IsValid()) {
21482 if (cond.Is(al)) {
21483 EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21484 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21485 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21486 return;
21487 }
21488 }
21489 }
21490 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21491}
21492
21493void Assembler::vmul(
21494 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021495 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021496 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021497 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021498 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
21499 if (dt.Is(F32)) {
21500 EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21501 rm.Encode(5, 0));
21502 AdvanceIT();
21503 return;
21504 }
21505 } else {
21506 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
21507 if (dt.Is(F32) && cond.IsNotNever()) {
21508 EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21509 rn.Encode(7, 16) | rm.Encode(5, 0));
21510 return;
21511 }
21512 }
21513 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21514}
21515
21516void Assembler::vmull(Condition cond,
21517 DataType dt,
21518 QRegister rd,
21519 DRegister rn,
21520 DRegister dm,
21521 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021522 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021523 CheckIT(cond);
21524 Dt_U_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021525 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021526 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
21527 if (encoded_dt.IsValid() &&
21528 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021529 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21530 (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021531 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21532 uint32_t shift = 4;
21533 if (dt.Is(S16) || dt.Is(U16)) {
21534 shift = 3;
21535 }
21536 uint32_t mvm = dm.GetCode() | index << shift;
21537 EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21538 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21539 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21540 ((mvm & 0x10) << 1));
21541 AdvanceIT();
21542 return;
21543 }
21544 }
21545 } else {
21546 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
21547 if (encoded_dt.IsValid() &&
21548 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070021549 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1) &&
21550 (dm.GetCode() <= 15)))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021551 if (cond.Is(al)) {
21552 uint32_t shift = 4;
21553 if (dt.Is(S16) || dt.Is(U16)) {
21554 shift = 3;
21555 }
21556 uint32_t mvm = dm.GetCode() | index << shift;
21557 EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21558 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21559 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21560 ((mvm & 0x10) << 1));
21561 return;
21562 }
21563 }
21564 }
21565 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
21566}
21567
21568void Assembler::vmull(
21569 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021570 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021571 CheckIT(cond);
21572 Dt_op_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021573 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021574 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21575 if (encoded_dt.IsValid()) {
21576 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21577 EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21578 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21579 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21580 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21581 AdvanceIT();
21582 return;
21583 }
21584 }
21585 } else {
21586 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21587 if (encoded_dt.IsValid()) {
21588 if (cond.Is(al)) {
21589 EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21590 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21591 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21592 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21593 return;
21594 }
21595 }
21596 }
21597 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
21598}
21599
21600void Assembler::vmvn(Condition cond,
21601 DataType dt,
21602 DRegister rd,
21603 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021604 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021605 CheckIT(cond);
21606 if (operand.IsImmediate()) {
21607 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021608 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021609 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
21610 if (encoded_dt.IsValid()) {
21611 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21612 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
21613 rd.Encode(22, 12) |
21614 (encoded_dt.GetEncodedImmediate() & 0xf) |
21615 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21616 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21617 AdvanceIT();
21618 return;
21619 }
21620 }
21621 } else {
21622 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
21623 if (encoded_dt.IsValid()) {
21624 if (cond.Is(al)) {
21625 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
21626 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21627 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21628 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21629 return;
21630 }
21631 }
21632 }
21633 }
21634 if (operand.IsRegister()) {
21635 DRegister rm = operand.GetRegister();
21636 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021637 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021638 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21639 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21640 EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21641 AdvanceIT();
21642 return;
21643 }
21644 } else {
21645 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21646 if (cond.Is(al)) {
21647 EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21648 return;
21649 }
21650 }
21651 }
21652 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21653}
21654
21655void Assembler::vmvn(Condition cond,
21656 DataType dt,
21657 QRegister rd,
21658 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021659 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021660 CheckIT(cond);
21661 if (operand.IsImmediate()) {
21662 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021663 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021664 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21665 if (encoded_dt.IsValid()) {
21666 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21667 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
21668 rd.Encode(22, 12) |
21669 (encoded_dt.GetEncodedImmediate() & 0xf) |
21670 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21671 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21672 AdvanceIT();
21673 return;
21674 }
21675 }
21676 } else {
21677 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21678 if (encoded_dt.IsValid()) {
21679 if (cond.Is(al)) {
21680 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
21681 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21682 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21683 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21684 return;
21685 }
21686 }
21687 }
21688 }
21689 if (operand.IsRegister()) {
21690 QRegister rm = operand.GetRegister();
21691 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021692 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021693 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21694 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21695 EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21696 AdvanceIT();
21697 return;
21698 }
21699 } else {
21700 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21701 if (cond.Is(al)) {
21702 EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21703 return;
21704 }
21705 }
21706 }
21707 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21708}
21709
21710void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021711 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021712 CheckIT(cond);
21713 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021714 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021715 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21716 if (encoded_dt.IsValid()) {
21717 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21718 EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21719 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21720 rd.Encode(22, 12) | rm.Encode(5, 0));
21721 AdvanceIT();
21722 return;
21723 }
21724 }
21725 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21726 if (dt.Is(F64)) {
21727 EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21728 AdvanceIT();
21729 return;
21730 }
21731 } else {
21732 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21733 if (encoded_dt.IsValid()) {
21734 if (cond.Is(al)) {
21735 EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21736 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21737 rd.Encode(22, 12) | rm.Encode(5, 0));
21738 return;
21739 }
21740 }
21741 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21742 if (dt.Is(F64) && cond.IsNotNever()) {
21743 EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21744 rm.Encode(5, 0));
21745 return;
21746 }
21747 }
21748 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21749}
21750
21751void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021752 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021753 CheckIT(cond);
21754 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021756 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21757 if (encoded_dt.IsValid()) {
21758 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21759 EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21760 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21761 rd.Encode(22, 12) | rm.Encode(5, 0));
21762 AdvanceIT();
21763 return;
21764 }
21765 }
21766 } else {
21767 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21768 if (encoded_dt.IsValid()) {
21769 if (cond.Is(al)) {
21770 EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21771 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21772 rd.Encode(22, 12) | rm.Encode(5, 0));
21773 return;
21774 }
21775 }
21776 }
21777 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21778}
21779
21780void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021781 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021782 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021783 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021784 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21785 if (dt.Is(F32)) {
21786 EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21787 AdvanceIT();
21788 return;
21789 }
21790 } else {
21791 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21792 if (dt.Is(F32) && cond.IsNotNever()) {
21793 EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21794 rm.Encode(5, 0));
21795 return;
21796 }
21797 }
21798 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21799}
21800
21801void Assembler::vnmla(
21802 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021803 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021804 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021806 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21807 if (dt.Is(F32)) {
21808 EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21809 rm.Encode(5, 0));
21810 AdvanceIT();
21811 return;
21812 }
21813 } else {
21814 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21815 if (dt.Is(F32) && cond.IsNotNever()) {
21816 EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21817 rn.Encode(7, 16) | rm.Encode(5, 0));
21818 return;
21819 }
21820 }
21821 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21822}
21823
21824void Assembler::vnmla(
21825 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021826 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021827 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021828 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021829 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21830 if (dt.Is(F64)) {
21831 EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21832 rm.Encode(5, 0));
21833 AdvanceIT();
21834 return;
21835 }
21836 } else {
21837 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21838 if (dt.Is(F64) && cond.IsNotNever()) {
21839 EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21840 rn.Encode(7, 16) | rm.Encode(5, 0));
21841 return;
21842 }
21843 }
21844 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21845}
21846
21847void Assembler::vnmls(
21848 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021849 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021850 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021851 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021852 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21853 if (dt.Is(F32)) {
21854 EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21855 rm.Encode(5, 0));
21856 AdvanceIT();
21857 return;
21858 }
21859 } else {
21860 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21861 if (dt.Is(F32) && cond.IsNotNever()) {
21862 EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21863 rn.Encode(7, 16) | rm.Encode(5, 0));
21864 return;
21865 }
21866 }
21867 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21868}
21869
21870void Assembler::vnmls(
21871 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021872 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021873 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021874 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021875 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21876 if (dt.Is(F64)) {
21877 EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21878 rm.Encode(5, 0));
21879 AdvanceIT();
21880 return;
21881 }
21882 } else {
21883 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21884 if (dt.Is(F64) && cond.IsNotNever()) {
21885 EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21886 rn.Encode(7, 16) | rm.Encode(5, 0));
21887 return;
21888 }
21889 }
21890 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21891}
21892
21893void Assembler::vnmul(
21894 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021895 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021896 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021897 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021898 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
21899 if (dt.Is(F32)) {
21900 EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21901 rm.Encode(5, 0));
21902 AdvanceIT();
21903 return;
21904 }
21905 } else {
21906 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
21907 if (dt.Is(F32) && cond.IsNotNever()) {
21908 EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21909 rn.Encode(7, 16) | rm.Encode(5, 0));
21910 return;
21911 }
21912 }
21913 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21914}
21915
21916void Assembler::vnmul(
21917 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021918 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021919 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021920 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021921 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
21922 if (dt.Is(F64)) {
21923 EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21924 rm.Encode(5, 0));
21925 AdvanceIT();
21926 return;
21927 }
21928 } else {
21929 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
21930 if (dt.Is(F64) && cond.IsNotNever()) {
21931 EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21932 rn.Encode(7, 16) | rm.Encode(5, 0));
21933 return;
21934 }
21935 }
21936 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21937}
21938
21939void Assembler::vorn(Condition cond,
21940 DataType dt,
21941 DRegister rd,
21942 DRegister rn,
21943 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021944 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021945 CheckIT(cond);
21946 if (operand.IsImmediate()) {
21947 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021948 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021949 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
21950 if (encoded_dt.IsValid() && rd.Is(rn)) {
21951 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21952 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
21953 rd.Encode(22, 12) |
21954 (encoded_dt.GetEncodedImmediate() & 0xf) |
21955 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21956 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21957 AdvanceIT();
21958 return;
21959 }
21960 }
21961 } else {
21962 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
21963 if (encoded_dt.IsValid() && rd.Is(rn)) {
21964 if (cond.Is(al)) {
21965 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
21966 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21967 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21968 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21969 return;
21970 }
21971 }
21972 }
21973 }
21974 if (operand.IsRegister()) {
21975 DRegister rm = operand.GetRegister();
21976 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021977 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021978 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
21979 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21980 EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21981 rm.Encode(5, 0));
21982 AdvanceIT();
21983 return;
21984 }
21985 } else {
21986 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
21987 if (cond.Is(al)) {
21988 EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21989 rm.Encode(5, 0));
21990 return;
21991 }
21992 }
21993 }
21994 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
21995}
21996
21997void Assembler::vorn(Condition cond,
21998 DataType dt,
21999 QRegister rd,
22000 QRegister rn,
22001 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022002 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022003 CheckIT(cond);
22004 if (operand.IsImmediate()) {
22005 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022006 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022007 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22008 if (encoded_dt.IsValid() && rd.Is(rn)) {
22009 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22010 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22011 rd.Encode(22, 12) |
22012 (encoded_dt.GetEncodedImmediate() & 0xf) |
22013 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22014 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22015 AdvanceIT();
22016 return;
22017 }
22018 }
22019 } else {
22020 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22021 if (encoded_dt.IsValid() && rd.Is(rn)) {
22022 if (cond.Is(al)) {
22023 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22024 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22025 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22026 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22027 return;
22028 }
22029 }
22030 }
22031 }
22032 if (operand.IsRegister()) {
22033 QRegister rm = operand.GetRegister();
22034 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022035 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022036 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22037 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22038 EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22039 rm.Encode(5, 0));
22040 AdvanceIT();
22041 return;
22042 }
22043 } else {
22044 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22045 if (cond.Is(al)) {
22046 EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22047 rm.Encode(5, 0));
22048 return;
22049 }
22050 }
22051 }
22052 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
22053}
22054
22055void Assembler::vorr(Condition cond,
22056 DataType dt,
22057 DRegister rd,
22058 DRegister rn,
22059 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022060 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022061 CheckIT(cond);
22062 if (operand.IsRegister()) {
22063 DRegister rm = operand.GetRegister();
22064 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022065 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022066 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
22067 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22068 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22069 rm.Encode(5, 0));
22070 AdvanceIT();
22071 return;
22072 }
22073 } else {
22074 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
22075 if (cond.Is(al)) {
22076 EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22077 rm.Encode(5, 0));
22078 return;
22079 }
22080 }
22081 }
22082 if (operand.IsImmediate()) {
22083 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022084 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022085 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
22086 if (encoded_dt.IsValid() && rd.Is(rn)) {
22087 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22088 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
22089 rd.Encode(22, 12) |
22090 (encoded_dt.GetEncodedImmediate() & 0xf) |
22091 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22092 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22093 AdvanceIT();
22094 return;
22095 }
22096 }
22097 } else {
22098 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
22099 if (encoded_dt.IsValid() && rd.Is(rn)) {
22100 if (cond.Is(al)) {
22101 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
22102 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22103 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22104 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22105 return;
22106 }
22107 }
22108 }
22109 }
22110 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22111}
22112
22113void Assembler::vorr(Condition cond,
22114 DataType dt,
22115 QRegister rd,
22116 QRegister rn,
22117 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022118 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022119 CheckIT(cond);
22120 if (operand.IsRegister()) {
22121 QRegister rm = operand.GetRegister();
22122 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022123 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022124 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22125 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22126 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22127 rm.Encode(5, 0));
22128 AdvanceIT();
22129 return;
22130 }
22131 } else {
22132 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22133 if (cond.Is(al)) {
22134 EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22135 rm.Encode(5, 0));
22136 return;
22137 }
22138 }
22139 }
22140 if (operand.IsImmediate()) {
22141 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022142 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022143 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22144 if (encoded_dt.IsValid() && rd.Is(rn)) {
22145 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22146 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22147 rd.Encode(22, 12) |
22148 (encoded_dt.GetEncodedImmediate() & 0xf) |
22149 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22150 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22151 AdvanceIT();
22152 return;
22153 }
22154 }
22155 } else {
22156 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22157 if (encoded_dt.IsValid() && rd.Is(rn)) {
22158 if (cond.Is(al)) {
22159 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22160 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22161 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22162 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22163 return;
22164 }
22165 }
22166 }
22167 }
22168 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22169}
22170
22171void Assembler::vpadal(Condition cond,
22172 DataType dt,
22173 DRegister rd,
22174 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022175 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022176 CheckIT(cond);
22177 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022178 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022179 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22180 if (encoded_dt.IsValid()) {
22181 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22182 EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22183 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22184 rd.Encode(22, 12) | rm.Encode(5, 0));
22185 AdvanceIT();
22186 return;
22187 }
22188 }
22189 } else {
22190 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22191 if (encoded_dt.IsValid()) {
22192 if (cond.Is(al)) {
22193 EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22194 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22195 rd.Encode(22, 12) | rm.Encode(5, 0));
22196 return;
22197 }
22198 }
22199 }
22200 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22201}
22202
22203void Assembler::vpadal(Condition cond,
22204 DataType dt,
22205 QRegister rd,
22206 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022207 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022208 CheckIT(cond);
22209 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022210 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022211 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22212 if (encoded_dt.IsValid()) {
22213 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22214 EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22215 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22216 rd.Encode(22, 12) | rm.Encode(5, 0));
22217 AdvanceIT();
22218 return;
22219 }
22220 }
22221 } else {
22222 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22223 if (encoded_dt.IsValid()) {
22224 if (cond.Is(al)) {
22225 EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22226 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22227 rd.Encode(22, 12) | rm.Encode(5, 0));
22228 return;
22229 }
22230 }
22231 }
22232 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22233}
22234
22235void Assembler::vpadd(
22236 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022237 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022238 CheckIT(cond);
22239 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022240 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022241 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22242 if (dt.Is(F32)) {
22243 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22244 EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22245 rm.Encode(5, 0));
22246 AdvanceIT();
22247 return;
22248 }
22249 }
22250 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22251 if (encoded_dt.IsValid()) {
22252 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22253 EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
22254 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22255 AdvanceIT();
22256 return;
22257 }
22258 }
22259 } else {
22260 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22261 if (dt.Is(F32)) {
22262 if (cond.Is(al)) {
22263 EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22264 rm.Encode(5, 0));
22265 return;
22266 }
22267 }
22268 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22269 if (encoded_dt.IsValid()) {
22270 if (cond.Is(al)) {
22271 EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
22272 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22273 return;
22274 }
22275 }
22276 }
22277 Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
22278}
22279
22280void Assembler::vpaddl(Condition cond,
22281 DataType dt,
22282 DRegister rd,
22283 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022284 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022285 CheckIT(cond);
22286 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022287 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022288 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22289 if (encoded_dt.IsValid()) {
22290 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22291 EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22292 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22293 rd.Encode(22, 12) | rm.Encode(5, 0));
22294 AdvanceIT();
22295 return;
22296 }
22297 }
22298 } else {
22299 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22300 if (encoded_dt.IsValid()) {
22301 if (cond.Is(al)) {
22302 EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22303 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22304 rd.Encode(22, 12) | rm.Encode(5, 0));
22305 return;
22306 }
22307 }
22308 }
22309 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22310}
22311
22312void Assembler::vpaddl(Condition cond,
22313 DataType dt,
22314 QRegister rd,
22315 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022316 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022317 CheckIT(cond);
22318 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022320 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22321 if (encoded_dt.IsValid()) {
22322 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22323 EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22324 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22325 rd.Encode(22, 12) | rm.Encode(5, 0));
22326 AdvanceIT();
22327 return;
22328 }
22329 }
22330 } else {
22331 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22332 if (encoded_dt.IsValid()) {
22333 if (cond.Is(al)) {
22334 EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22335 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22336 rd.Encode(22, 12) | rm.Encode(5, 0));
22337 return;
22338 }
22339 }
22340 }
22341 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22342}
22343
22344void Assembler::vpmax(
22345 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022346 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022347 CheckIT(cond);
22348 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022349 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022350 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22351 if (dt.Is(F32)) {
22352 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22353 EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22354 rm.Encode(5, 0));
22355 AdvanceIT();
22356 return;
22357 }
22358 }
22359 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22360 if (encoded_dt.IsValid()) {
22361 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22362 EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22363 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22364 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22365 AdvanceIT();
22366 return;
22367 }
22368 }
22369 } else {
22370 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22371 if (dt.Is(F32)) {
22372 if (cond.Is(al)) {
22373 EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22374 rm.Encode(5, 0));
22375 return;
22376 }
22377 }
22378 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22379 if (encoded_dt.IsValid()) {
22380 if (cond.Is(al)) {
22381 EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22382 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22383 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22384 return;
22385 }
22386 }
22387 }
22388 Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
22389}
22390
22391void Assembler::vpmin(
22392 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022393 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022394 CheckIT(cond);
22395 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022396 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022397 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22398 if (dt.Is(F32)) {
22399 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22400 EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22401 rm.Encode(5, 0));
22402 AdvanceIT();
22403 return;
22404 }
22405 }
22406 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22407 if (encoded_dt.IsValid()) {
22408 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22409 EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22410 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22411 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22412 AdvanceIT();
22413 return;
22414 }
22415 }
22416 } else {
22417 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22418 if (dt.Is(F32)) {
22419 if (cond.Is(al)) {
22420 EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22421 rm.Encode(5, 0));
22422 return;
22423 }
22424 }
22425 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22426 if (encoded_dt.IsValid()) {
22427 if (cond.Is(al)) {
22428 EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22429 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22430 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22431 return;
22432 }
22433 }
22434 }
22435 Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
22436}
22437
22438void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022439 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022440 CheckIT(cond);
22441 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022442 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022443 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080022444 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022445 const DRegister& dreg = dreglist.GetFirstDRegister();
22446 unsigned len = dreglist.GetLength() * 2;
22447 EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
22448 AdvanceIT();
22449 return;
22450 }
22451 } else {
22452 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
22453 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080022454 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022455 const DRegister& dreg = dreglist.GetFirstDRegister();
22456 unsigned len = dreglist.GetLength() * 2;
22457 EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22458 (len & 0xff));
22459 return;
22460 }
22461 }
22462 Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
22463}
22464
22465void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022466 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022467 CheckIT(cond);
22468 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022469 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022470 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
22471 const SRegister& sreg = sreglist.GetFirstSRegister();
22472 unsigned len = sreglist.GetLength();
22473 EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
22474 AdvanceIT();
22475 return;
22476 } else {
22477 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
22478 if (cond.IsNotNever()) {
22479 const SRegister& sreg = sreglist.GetFirstSRegister();
22480 unsigned len = sreglist.GetLength();
22481 EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22482 (len & 0xff));
22483 return;
22484 }
22485 }
22486 Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
22487}
22488
22489void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022490 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022491 CheckIT(cond);
22492 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022493 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022494 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080022495 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022496 const DRegister& dreg = dreglist.GetFirstDRegister();
22497 unsigned len = dreglist.GetLength() * 2;
22498 EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
22499 AdvanceIT();
22500 return;
22501 }
22502 } else {
22503 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
22504 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080022505 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022506 const DRegister& dreg = dreglist.GetFirstDRegister();
22507 unsigned len = dreglist.GetLength() * 2;
22508 EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22509 (len & 0xff));
22510 return;
22511 }
22512 }
22513 Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
22514}
22515
22516void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022517 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022518 CheckIT(cond);
22519 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022520 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022521 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
22522 const SRegister& sreg = sreglist.GetFirstSRegister();
22523 unsigned len = sreglist.GetLength();
22524 EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
22525 AdvanceIT();
22526 return;
22527 } else {
22528 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
22529 if (cond.IsNotNever()) {
22530 const SRegister& sreg = sreglist.GetFirstSRegister();
22531 unsigned len = sreglist.GetLength();
22532 EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22533 (len & 0xff));
22534 return;
22535 }
22536 }
22537 Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
22538}
22539
22540void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022541 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022542 CheckIT(cond);
22543 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022544 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022545 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22546 if (encoded_dt.IsValid()) {
22547 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22548 EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
22549 rd.Encode(22, 12) | rm.Encode(5, 0));
22550 AdvanceIT();
22551 return;
22552 }
22553 }
22554 } else {
22555 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22556 if (encoded_dt.IsValid()) {
22557 if (cond.Is(al)) {
22558 EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
22559 rd.Encode(22, 12) | rm.Encode(5, 0));
22560 return;
22561 }
22562 }
22563 }
22564 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22565}
22566
22567void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022568 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022569 CheckIT(cond);
22570 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022571 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022572 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22573 if (encoded_dt.IsValid()) {
22574 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22575 EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
22576 rd.Encode(22, 12) | rm.Encode(5, 0));
22577 AdvanceIT();
22578 return;
22579 }
22580 }
22581 } else {
22582 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22583 if (encoded_dt.IsValid()) {
22584 if (cond.Is(al)) {
22585 EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
22586 rd.Encode(22, 12) | rm.Encode(5, 0));
22587 return;
22588 }
22589 }
22590 }
22591 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22592}
22593
22594void Assembler::vqadd(
22595 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022596 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022597 CheckIT(cond);
22598 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022599 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022600 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22601 if (encoded_dt.IsValid()) {
22602 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22603 EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22604 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22605 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22606 AdvanceIT();
22607 return;
22608 }
22609 }
22610 } else {
22611 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22612 if (encoded_dt.IsValid()) {
22613 if (cond.Is(al)) {
22614 EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22615 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22616 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22617 return;
22618 }
22619 }
22620 }
22621 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22622}
22623
22624void Assembler::vqadd(
22625 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022626 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022627 CheckIT(cond);
22628 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022629 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022630 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22631 if (encoded_dt.IsValid()) {
22632 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22633 EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22634 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22635 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22636 AdvanceIT();
22637 return;
22638 }
22639 }
22640 } else {
22641 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22642 if (encoded_dt.IsValid()) {
22643 if (cond.Is(al)) {
22644 EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22645 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22646 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22647 return;
22648 }
22649 }
22650 }
22651 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22652}
22653
22654void Assembler::vqdmlal(
22655 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022656 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022657 CheckIT(cond);
22658 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022659 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022660 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22661 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22662 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22663 EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
22664 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22665 AdvanceIT();
22666 return;
22667 }
22668 }
22669 } else {
22670 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22671 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22672 if (cond.Is(al)) {
22673 EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
22674 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22675 return;
22676 }
22677 }
22678 }
22679 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
22680}
22681
22682void Assembler::vqdmlal(Condition cond,
22683 DataType dt,
22684 QRegister rd,
22685 DRegister rn,
22686 DRegister dm,
22687 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022688 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022689 CheckIT(cond);
22690 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022691 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022692 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22693 if (encoded_dt.IsValid() &&
22694 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022695 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022696 (dt.Is(S16) || dt.Is(S32))) {
22697 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22698 uint32_t shift = 4;
22699 if (dt.Is(S16)) {
22700 shift = 3;
22701 }
22702 uint32_t mvm = dm.GetCode() | index << shift;
22703 EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
22704 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22705 ((mvm & 0x10) << 1));
22706 AdvanceIT();
22707 return;
22708 }
22709 }
22710 } else {
22711 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22712 if (encoded_dt.IsValid() &&
22713 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022714 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022715 (dt.Is(S16) || dt.Is(S32))) {
22716 if (cond.Is(al)) {
22717 uint32_t shift = 4;
22718 if (dt.Is(S16)) {
22719 shift = 3;
22720 }
22721 uint32_t mvm = dm.GetCode() | index << shift;
22722 EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
22723 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22724 ((mvm & 0x10) << 1));
22725 return;
22726 }
22727 }
22728 }
22729 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
22730}
22731
22732void Assembler::vqdmlsl(
22733 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022734 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022735 CheckIT(cond);
22736 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022737 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022738 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22739 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22740 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22741 EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
22742 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22743 AdvanceIT();
22744 return;
22745 }
22746 }
22747 } else {
22748 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22749 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22750 if (cond.Is(al)) {
22751 EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
22752 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22753 return;
22754 }
22755 }
22756 }
22757 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
22758}
22759
22760void Assembler::vqdmlsl(Condition cond,
22761 DataType dt,
22762 QRegister rd,
22763 DRegister rn,
22764 DRegister dm,
22765 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022766 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022767 CheckIT(cond);
22768 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022769 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022770 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22771 if (encoded_dt.IsValid() &&
22772 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022773 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022774 (dt.Is(S16) || dt.Is(S32))) {
22775 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22776 uint32_t shift = 4;
22777 if (dt.Is(S16)) {
22778 shift = 3;
22779 }
22780 uint32_t mvm = dm.GetCode() | index << shift;
22781 EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
22782 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22783 ((mvm & 0x10) << 1));
22784 AdvanceIT();
22785 return;
22786 }
22787 }
22788 } else {
22789 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22790 if (encoded_dt.IsValid() &&
22791 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
Vincent Belliard71fb5912017-08-16 08:37:08 -070022792 (!dt.Is(S16) && (index <= 1) && (dm.GetCode() <= 15))) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010022793 (dt.Is(S16) || dt.Is(S32))) {
22794 if (cond.Is(al)) {
22795 uint32_t shift = 4;
22796 if (dt.Is(S16)) {
22797 shift = 3;
22798 }
22799 uint32_t mvm = dm.GetCode() | index << shift;
22800 EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
22801 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22802 ((mvm & 0x10) << 1));
22803 return;
22804 }
22805 }
22806 }
22807 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
22808}
22809
22810void Assembler::vqdmulh(
22811 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022812 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022813 CheckIT(cond);
22814 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022815 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022816 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22817 if (encoded_dt.IsValid()) {
22818 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22819 EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
22820 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22821 AdvanceIT();
22822 return;
22823 }
22824 }
22825 } else {
22826 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22827 if (encoded_dt.IsValid()) {
22828 if (cond.Is(al)) {
22829 EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
22830 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22831 return;
22832 }
22833 }
22834 }
22835 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22836}
22837
22838void Assembler::vqdmulh(
22839 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022840 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022841 CheckIT(cond);
22842 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022844 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22845 if (encoded_dt.IsValid()) {
22846 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22847 EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
22848 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22849 AdvanceIT();
22850 return;
22851 }
22852 }
22853 } else {
22854 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22855 if (encoded_dt.IsValid()) {
22856 if (cond.Is(al)) {
22857 EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
22858 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22859 return;
22860 }
22861 }
22862 }
22863 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22864}
22865
22866void Assembler::vqdmulh(
22867 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022868 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022869 CheckIT(cond);
22870 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022871 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022872 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
22873 if (encoded_dt.IsValid() &&
22874 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22875 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22876 (rm.GetLane() <= 1))) &&
22877 (dt.Is(S16) || dt.Is(S32))) {
22878 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22879 EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
22880 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22881 AdvanceIT();
22882 return;
22883 }
22884 }
22885 } else {
22886 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
22887 if (encoded_dt.IsValid() &&
22888 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22889 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22890 (rm.GetLane() <= 1))) &&
22891 (dt.Is(S16) || dt.Is(S32))) {
22892 if (cond.Is(al)) {
22893 EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
22894 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22895 return;
22896 }
22897 }
22898 }
22899 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22900}
22901
22902void Assembler::vqdmulh(
22903 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022904 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022905 CheckIT(cond);
22906 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022907 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022908 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
22909 if (encoded_dt.IsValid() &&
22910 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22911 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22912 (rm.GetLane() <= 1))) &&
22913 (dt.Is(S16) || dt.Is(S32))) {
22914 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22915 EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
22916 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22917 AdvanceIT();
22918 return;
22919 }
22920 }
22921 } else {
22922 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
22923 if (encoded_dt.IsValid() &&
22924 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22925 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22926 (rm.GetLane() <= 1))) &&
22927 (dt.Is(S16) || dt.Is(S32))) {
22928 if (cond.Is(al)) {
22929 EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
22930 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22931 return;
22932 }
22933 }
22934 }
22935 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22936}
22937
22938void Assembler::vqdmull(
22939 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022940 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022941 CheckIT(cond);
22942 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022944 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22945 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22946 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22947 EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
22948 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22949 AdvanceIT();
22950 return;
22951 }
22952 }
22953 } else {
22954 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22955 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22956 if (cond.Is(al)) {
22957 EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
22958 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22959 return;
22960 }
22961 }
22962 }
22963 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22964}
22965
22966void Assembler::vqdmull(
22967 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022968 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022969 CheckIT(cond);
22970 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022971 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022972 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
22973 if (encoded_dt.IsValid() &&
22974 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22975 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22976 (rm.GetLane() <= 1))) &&
22977 (dt.Is(S16) || dt.Is(S32))) {
22978 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22979 EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
22980 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22981 AdvanceIT();
22982 return;
22983 }
22984 }
22985 } else {
22986 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
22987 if (encoded_dt.IsValid() &&
22988 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22989 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22990 (rm.GetLane() <= 1))) &&
22991 (dt.Is(S16) || dt.Is(S32))) {
22992 if (cond.Is(al)) {
22993 EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
22994 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22995 return;
22996 }
22997 }
22998 }
22999 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
23000}
23001
23002void Assembler::vqmovn(Condition cond,
23003 DataType dt,
23004 DRegister rd,
23005 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023006 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023007 CheckIT(cond);
23008 Dt_op_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023009 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023010 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
23011 if (encoded_dt.IsValid()) {
23012 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23013 EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23014 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23015 rd.Encode(22, 12) | rm.Encode(5, 0));
23016 AdvanceIT();
23017 return;
23018 }
23019 }
23020 } else {
23021 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
23022 if (encoded_dt.IsValid()) {
23023 if (cond.Is(al)) {
23024 EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23025 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23026 rd.Encode(22, 12) | rm.Encode(5, 0));
23027 return;
23028 }
23029 }
23030 }
23031 Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
23032}
23033
23034void Assembler::vqmovun(Condition cond,
23035 DataType dt,
23036 DRegister rd,
23037 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023038 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023039 CheckIT(cond);
23040 Dt_size_14 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023041 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023042 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
23043 if (encoded_dt.IsValid()) {
23044 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23045 EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
23046 rd.Encode(22, 12) | rm.Encode(5, 0));
23047 AdvanceIT();
23048 return;
23049 }
23050 }
23051 } else {
23052 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
23053 if (encoded_dt.IsValid()) {
23054 if (cond.Is(al)) {
23055 EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
23056 rd.Encode(22, 12) | rm.Encode(5, 0));
23057 return;
23058 }
23059 }
23060 }
23061 Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
23062}
23063
23064void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023065 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023066 CheckIT(cond);
23067 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023068 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023069 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23070 if (encoded_dt.IsValid()) {
23071 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23072 EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
23073 rd.Encode(22, 12) | rm.Encode(5, 0));
23074 AdvanceIT();
23075 return;
23076 }
23077 }
23078 } else {
23079 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23080 if (encoded_dt.IsValid()) {
23081 if (cond.Is(al)) {
23082 EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
23083 rd.Encode(22, 12) | rm.Encode(5, 0));
23084 return;
23085 }
23086 }
23087 }
23088 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23089}
23090
23091void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023092 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023093 CheckIT(cond);
23094 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023095 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023096 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23097 if (encoded_dt.IsValid()) {
23098 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23099 EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
23100 rd.Encode(22, 12) | rm.Encode(5, 0));
23101 AdvanceIT();
23102 return;
23103 }
23104 }
23105 } else {
23106 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23107 if (encoded_dt.IsValid()) {
23108 if (cond.Is(al)) {
23109 EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
23110 rd.Encode(22, 12) | rm.Encode(5, 0));
23111 return;
23112 }
23113 }
23114 }
23115 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23116}
23117
23118void Assembler::vqrdmulh(
23119 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023120 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023121 CheckIT(cond);
23122 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023123 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023124 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23125 if (encoded_dt.IsValid()) {
23126 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23127 EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
23128 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23129 AdvanceIT();
23130 return;
23131 }
23132 }
23133 } else {
23134 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23135 if (encoded_dt.IsValid()) {
23136 if (cond.Is(al)) {
23137 EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
23138 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23139 return;
23140 }
23141 }
23142 }
23143 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23144}
23145
23146void Assembler::vqrdmulh(
23147 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023148 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023149 CheckIT(cond);
23150 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023151 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023152 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23153 if (encoded_dt.IsValid()) {
23154 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23155 EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
23156 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23157 AdvanceIT();
23158 return;
23159 }
23160 }
23161 } else {
23162 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23163 if (encoded_dt.IsValid()) {
23164 if (cond.Is(al)) {
23165 EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
23166 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23167 return;
23168 }
23169 }
23170 }
23171 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23172}
23173
23174void Assembler::vqrdmulh(
23175 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023176 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023177 CheckIT(cond);
23178 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023179 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023180 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
23181 if (encoded_dt.IsValid() &&
23182 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23183 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23184 (rm.GetLane() <= 1))) &&
23185 (dt.Is(S16) || dt.Is(S32))) {
23186 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23187 EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
23188 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23189 AdvanceIT();
23190 return;
23191 }
23192 }
23193 } else {
23194 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
23195 if (encoded_dt.IsValid() &&
23196 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23197 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23198 (rm.GetLane() <= 1))) &&
23199 (dt.Is(S16) || dt.Is(S32))) {
23200 if (cond.Is(al)) {
23201 EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
23202 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23203 return;
23204 }
23205 }
23206 }
23207 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23208}
23209
23210void Assembler::vqrdmulh(
23211 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023212 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023213 CheckIT(cond);
23214 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023215 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023216 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
23217 if (encoded_dt.IsValid() &&
23218 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23219 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23220 (rm.GetLane() <= 1))) &&
23221 (dt.Is(S16) || dt.Is(S32))) {
23222 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23223 EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
23224 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23225 AdvanceIT();
23226 return;
23227 }
23228 }
23229 } else {
23230 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
23231 if (encoded_dt.IsValid() &&
23232 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23233 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23234 (rm.GetLane() <= 1))) &&
23235 (dt.Is(S16) || dt.Is(S32))) {
23236 if (cond.Is(al)) {
23237 EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
23238 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23239 return;
23240 }
23241 }
23242 }
23243 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23244}
23245
23246void Assembler::vqrshl(
23247 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023248 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023249 CheckIT(cond);
23250 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023251 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023252 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23253 if (encoded_dt.IsValid()) {
23254 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23255 EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23256 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23257 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23258 AdvanceIT();
23259 return;
23260 }
23261 }
23262 } else {
23263 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23264 if (encoded_dt.IsValid()) {
23265 if (cond.Is(al)) {
23266 EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23267 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23268 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23269 return;
23270 }
23271 }
23272 }
23273 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23274}
23275
23276void Assembler::vqrshl(
23277 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023278 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023279 CheckIT(cond);
23280 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023281 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023282 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23283 if (encoded_dt.IsValid()) {
23284 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23285 EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23286 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23287 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23288 AdvanceIT();
23289 return;
23290 }
23291 }
23292 } else {
23293 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23294 if (encoded_dt.IsValid()) {
23295 if (cond.Is(al)) {
23296 EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23297 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23298 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23299 return;
23300 }
23301 }
23302 }
23303 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23304}
23305
23306void Assembler::vqrshrn(Condition cond,
23307 DataType dt,
23308 DRegister rd,
23309 QRegister rm,
23310 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023311 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023312 CheckIT(cond);
23313 if (operand.IsImmediate()) {
23314 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23315 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23316 Dt_op_size_3 encoded_dt(dt);
23317 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023318 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023319 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23320 if (encoded_dt.IsValid() && (imm == 0)) {
23321 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23322 EmitT32_32(0xffb20280U |
23323 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23324 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23325 rd.Encode(22, 12) | rm.Encode(5, 0));
23326 AdvanceIT();
23327 return;
23328 }
23329 }
23330 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23331 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23332 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23333 uint32_t imm6 = dt.GetSize() / 2 - imm;
23334 EmitT32_32(0xef800950U |
23335 (encoded_dt_2.GetTypeEncodingValue() << 28) |
23336 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23337 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23338 AdvanceIT();
23339 return;
23340 }
23341 }
23342 } else {
23343 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23344 if (encoded_dt.IsValid() && (imm == 0)) {
23345 if (cond.Is(al)) {
23346 EmitA32(0xf3b20280U |
23347 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23348 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23349 rd.Encode(22, 12) | rm.Encode(5, 0));
23350 return;
23351 }
23352 }
23353 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23354 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23355 if (cond.Is(al)) {
23356 uint32_t imm6 = dt.GetSize() / 2 - imm;
23357 EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23358 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23359 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23360 return;
23361 }
23362 }
23363 }
23364 }
23365 }
23366 Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
23367}
23368
23369void Assembler::vqrshrun(Condition cond,
23370 DataType dt,
23371 DRegister rd,
23372 QRegister rm,
23373 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023374 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023375 CheckIT(cond);
23376 if (operand.IsImmediate()) {
23377 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23378 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23379 Dt_imm6_2 encoded_dt(dt);
23380 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023381 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023382 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23383 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23384 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23385 uint32_t imm6 = dt.GetSize() / 2 - imm;
23386 EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
23387 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23388 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23389 AdvanceIT();
23390 return;
23391 }
23392 }
23393 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23394 if (encoded_dt_2.IsValid() && (imm == 0)) {
23395 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23396 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23397 rd.Encode(22, 12) | rm.Encode(5, 0));
23398 AdvanceIT();
23399 return;
23400 }
23401 }
23402 } else {
23403 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23404 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23405 if (cond.Is(al)) {
23406 uint32_t imm6 = dt.GetSize() / 2 - imm;
23407 EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
23408 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23409 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23410 return;
23411 }
23412 }
23413 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23414 if (encoded_dt_2.IsValid() && (imm == 0)) {
23415 if (cond.Is(al)) {
23416 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23417 rd.Encode(22, 12) | rm.Encode(5, 0));
23418 return;
23419 }
23420 }
23421 }
23422 }
23423 }
23424 Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
23425}
23426
23427void Assembler::vqshl(Condition cond,
23428 DataType dt,
23429 DRegister rd,
23430 DRegister rm,
23431 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023432 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023433 CheckIT(cond);
23434 if (operand.IsRegister()) {
23435 DRegister rn = operand.GetRegister();
23436 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023437 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023438 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23439 if (encoded_dt.IsValid()) {
23440 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23441 EmitT32_32(0xef000410U |
23442 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23443 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23444 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23445 AdvanceIT();
23446 return;
23447 }
23448 }
23449 } else {
23450 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23451 if (encoded_dt.IsValid()) {
23452 if (cond.Is(al)) {
23453 EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23454 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23455 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23456 return;
23457 }
23458 }
23459 }
23460 }
23461 if (operand.IsImmediate()) {
23462 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23463 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23464 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023465 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023466 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23467 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23468 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23469 uint32_t imm6 = imm;
23470 EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
23471 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23472 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23473 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23474 AdvanceIT();
23475 return;
23476 }
23477 }
23478 } else {
23479 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23480 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23481 if (cond.Is(al)) {
23482 uint32_t imm6 = imm;
23483 EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
23484 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23485 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23486 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23487 return;
23488 }
23489 }
23490 }
23491 }
23492 }
23493 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23494}
23495
23496void Assembler::vqshl(Condition cond,
23497 DataType dt,
23498 QRegister rd,
23499 QRegister rm,
23500 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023501 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023502 CheckIT(cond);
23503 if (operand.IsRegister()) {
23504 QRegister rn = operand.GetRegister();
23505 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023506 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023507 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23508 if (encoded_dt.IsValid()) {
23509 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23510 EmitT32_32(0xef000450U |
23511 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23512 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23513 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23514 AdvanceIT();
23515 return;
23516 }
23517 }
23518 } else {
23519 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23520 if (encoded_dt.IsValid()) {
23521 if (cond.Is(al)) {
23522 EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23523 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23524 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23525 return;
23526 }
23527 }
23528 }
23529 }
23530 if (operand.IsImmediate()) {
23531 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23532 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23533 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023534 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023535 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<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(0xef800750U | (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 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23549 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23550 if (cond.Is(al)) {
23551 uint32_t imm6 = imm;
23552 EmitA32(0xf2800750U | (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(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23563}
23564
23565void Assembler::vqshlu(Condition cond,
23566 DataType dt,
23567 DRegister rd,
23568 DRegister rm,
23569 const DOperand& 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> {<Dd>}, <Dm>, #<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(0xef800610U | (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> {<Dd>}, <Dm>, #<imm> ; A1
23591 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23592 if (cond.Is(al)) {
23593 uint32_t imm6 = imm;
23594 EmitA32(0xf2800610U | (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::vqshlu(Condition cond,
23608 DataType dt,
23609 QRegister 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_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023618 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023619 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23620 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23621 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23622 uint32_t imm6 = imm;
23623 EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
23624 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23625 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23626 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23627 AdvanceIT();
23628 return;
23629 }
23630 }
23631 } else {
23632 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23633 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23634 if (cond.Is(al)) {
23635 uint32_t imm6 = imm;
23636 EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
23637 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23638 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23639 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23640 return;
23641 }
23642 }
23643 }
23644 }
23645 }
23646 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23647}
23648
23649void Assembler::vqshrn(Condition cond,
23650 DataType dt,
23651 DRegister rd,
23652 QRegister rm,
23653 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023654 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023655 CheckIT(cond);
23656 if (operand.IsImmediate()) {
23657 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23658 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23659 Dt_op_size_3 encoded_dt(dt);
23660 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023661 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023662 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23663 if (encoded_dt.IsValid() && (imm == 0)) {
23664 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23665 EmitT32_32(0xffb20280U |
23666 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23667 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23668 rd.Encode(22, 12) | rm.Encode(5, 0));
23669 AdvanceIT();
23670 return;
23671 }
23672 }
23673 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23674 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23675 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23676 uint32_t imm6 = dt.GetSize() / 2 - imm;
23677 EmitT32_32(0xef800910U |
23678 (encoded_dt_2.GetTypeEncodingValue() << 28) |
23679 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23680 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23681 AdvanceIT();
23682 return;
23683 }
23684 }
23685 } else {
23686 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23687 if (encoded_dt.IsValid() && (imm == 0)) {
23688 if (cond.Is(al)) {
23689 EmitA32(0xf3b20280U |
23690 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23691 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23692 rd.Encode(22, 12) | rm.Encode(5, 0));
23693 return;
23694 }
23695 }
23696 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23697 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23698 if (cond.Is(al)) {
23699 uint32_t imm6 = dt.GetSize() / 2 - imm;
23700 EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23701 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23702 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23703 return;
23704 }
23705 }
23706 }
23707 }
23708 }
23709 Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
23710}
23711
23712void Assembler::vqshrun(Condition cond,
23713 DataType dt,
23714 DRegister rd,
23715 QRegister rm,
23716 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023717 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023718 CheckIT(cond);
23719 if (operand.IsImmediate()) {
23720 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23721 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23722 Dt_imm6_2 encoded_dt(dt);
23723 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023724 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023725 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23726 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23727 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23728 uint32_t imm6 = dt.GetSize() / 2 - imm;
23729 EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
23730 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23731 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23732 AdvanceIT();
23733 return;
23734 }
23735 }
23736 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23737 if (encoded_dt_2.IsValid() && (imm == 0)) {
23738 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23739 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23740 rd.Encode(22, 12) | rm.Encode(5, 0));
23741 AdvanceIT();
23742 return;
23743 }
23744 }
23745 } else {
23746 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23747 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23748 if (cond.Is(al)) {
23749 uint32_t imm6 = dt.GetSize() / 2 - imm;
23750 EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
23751 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23752 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23753 return;
23754 }
23755 }
23756 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23757 if (encoded_dt_2.IsValid() && (imm == 0)) {
23758 if (cond.Is(al)) {
23759 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23760 rd.Encode(22, 12) | rm.Encode(5, 0));
23761 return;
23762 }
23763 }
23764 }
23765 }
23766 }
23767 Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
23768}
23769
23770void Assembler::vqsub(
23771 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023772 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023773 CheckIT(cond);
23774 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023775 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023776 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23777 if (encoded_dt.IsValid()) {
23778 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23779 EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23780 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23781 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23782 AdvanceIT();
23783 return;
23784 }
23785 }
23786 } else {
23787 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23788 if (encoded_dt.IsValid()) {
23789 if (cond.Is(al)) {
23790 EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23791 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23792 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23793 return;
23794 }
23795 }
23796 }
23797 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23798}
23799
23800void Assembler::vqsub(
23801 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023802 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023803 CheckIT(cond);
23804 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023806 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23807 if (encoded_dt.IsValid()) {
23808 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23809 EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23810 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23811 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23812 AdvanceIT();
23813 return;
23814 }
23815 }
23816 } else {
23817 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23818 if (encoded_dt.IsValid()) {
23819 if (cond.Is(al)) {
23820 EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23821 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23822 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23823 return;
23824 }
23825 }
23826 }
23827 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23828}
23829
23830void Assembler::vraddhn(
23831 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023832 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023833 CheckIT(cond);
23834 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023835 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023836 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23837 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23838 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23839 EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
23840 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23841 AdvanceIT();
23842 return;
23843 }
23844 }
23845 } else {
23846 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23847 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23848 if (cond.Is(al)) {
23849 EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
23850 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23851 return;
23852 }
23853 }
23854 }
23855 Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
23856}
23857
23858void Assembler::vrecpe(Condition cond,
23859 DataType dt,
23860 DRegister rd,
23861 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023863 CheckIT(cond);
23864 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023865 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023866 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23867 if (encoded_dt.IsValid()) {
23868 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23869 EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23870 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23871 rd.Encode(22, 12) | rm.Encode(5, 0));
23872 AdvanceIT();
23873 return;
23874 }
23875 }
23876 } else {
23877 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23878 if (encoded_dt.IsValid()) {
23879 if (cond.Is(al)) {
23880 EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23881 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23882 rd.Encode(22, 12) | rm.Encode(5, 0));
23883 return;
23884 }
23885 }
23886 }
23887 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23888}
23889
23890void Assembler::vrecpe(Condition cond,
23891 DataType dt,
23892 QRegister rd,
23893 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023894 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023895 CheckIT(cond);
23896 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023897 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023898 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23899 if (encoded_dt.IsValid()) {
23900 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23901 EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23902 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23903 rd.Encode(22, 12) | rm.Encode(5, 0));
23904 AdvanceIT();
23905 return;
23906 }
23907 }
23908 } else {
23909 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23910 if (encoded_dt.IsValid()) {
23911 if (cond.Is(al)) {
23912 EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23913 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23914 rd.Encode(22, 12) | rm.Encode(5, 0));
23915 return;
23916 }
23917 }
23918 }
23919 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23920}
23921
23922void Assembler::vrecps(
23923 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023924 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023925 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023926 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023927 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23928 if (dt.Is(F32)) {
23929 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23930 EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23931 rm.Encode(5, 0));
23932 AdvanceIT();
23933 return;
23934 }
23935 }
23936 } else {
23937 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23938 if (dt.Is(F32)) {
23939 if (cond.Is(al)) {
23940 EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23941 rm.Encode(5, 0));
23942 return;
23943 }
23944 }
23945 }
23946 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23947}
23948
23949void Assembler::vrecps(
23950 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023951 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023952 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023953 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023954 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23955 if (dt.Is(F32)) {
23956 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23957 EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23958 rm.Encode(5, 0));
23959 AdvanceIT();
23960 return;
23961 }
23962 }
23963 } else {
23964 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23965 if (dt.Is(F32)) {
23966 if (cond.Is(al)) {
23967 EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23968 rm.Encode(5, 0));
23969 return;
23970 }
23971 }
23972 }
23973 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23974}
23975
23976void Assembler::vrev16(Condition cond,
23977 DataType dt,
23978 DRegister rd,
23979 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023980 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023981 CheckIT(cond);
23982 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023983 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023984 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23985 if (encoded_dt.IsValid()) {
23986 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23987 EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
23988 rd.Encode(22, 12) | rm.Encode(5, 0));
23989 AdvanceIT();
23990 return;
23991 }
23992 }
23993 } else {
23994 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23995 if (encoded_dt.IsValid()) {
23996 if (cond.Is(al)) {
23997 EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
23998 rd.Encode(22, 12) | rm.Encode(5, 0));
23999 return;
24000 }
24001 }
24002 }
24003 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
24004}
24005
24006void Assembler::vrev16(Condition cond,
24007 DataType dt,
24008 QRegister rd,
24009 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024010 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024011 CheckIT(cond);
24012 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024013 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024014 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24015 if (encoded_dt.IsValid()) {
24016 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24017 EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
24018 rd.Encode(22, 12) | rm.Encode(5, 0));
24019 AdvanceIT();
24020 return;
24021 }
24022 }
24023 } else {
24024 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24025 if (encoded_dt.IsValid()) {
24026 if (cond.Is(al)) {
24027 EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
24028 rd.Encode(22, 12) | rm.Encode(5, 0));
24029 return;
24030 }
24031 }
24032 }
24033 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
24034}
24035
24036void Assembler::vrev32(Condition cond,
24037 DataType dt,
24038 DRegister rd,
24039 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024040 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024041 CheckIT(cond);
24042 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024043 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024044 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24045 if (encoded_dt.IsValid()) {
24046 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24047 EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
24048 rd.Encode(22, 12) | rm.Encode(5, 0));
24049 AdvanceIT();
24050 return;
24051 }
24052 }
24053 } else {
24054 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24055 if (encoded_dt.IsValid()) {
24056 if (cond.Is(al)) {
24057 EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
24058 rd.Encode(22, 12) | rm.Encode(5, 0));
24059 return;
24060 }
24061 }
24062 }
24063 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24064}
24065
24066void Assembler::vrev32(Condition cond,
24067 DataType dt,
24068 QRegister rd,
24069 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024070 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024071 CheckIT(cond);
24072 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024074 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24075 if (encoded_dt.IsValid()) {
24076 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24077 EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
24078 rd.Encode(22, 12) | rm.Encode(5, 0));
24079 AdvanceIT();
24080 return;
24081 }
24082 }
24083 } else {
24084 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24085 if (encoded_dt.IsValid()) {
24086 if (cond.Is(al)) {
24087 EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
24088 rd.Encode(22, 12) | rm.Encode(5, 0));
24089 return;
24090 }
24091 }
24092 }
24093 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24094}
24095
24096void Assembler::vrev64(Condition cond,
24097 DataType dt,
24098 DRegister rd,
24099 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024100 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024101 CheckIT(cond);
24102 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024103 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024104 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24105 if (encoded_dt.IsValid()) {
24106 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24107 EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
24108 rd.Encode(22, 12) | rm.Encode(5, 0));
24109 AdvanceIT();
24110 return;
24111 }
24112 }
24113 } else {
24114 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24115 if (encoded_dt.IsValid()) {
24116 if (cond.Is(al)) {
24117 EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
24118 rd.Encode(22, 12) | rm.Encode(5, 0));
24119 return;
24120 }
24121 }
24122 }
24123 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24124}
24125
24126void Assembler::vrev64(Condition cond,
24127 DataType dt,
24128 QRegister rd,
24129 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024130 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024131 CheckIT(cond);
24132 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024133 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024134 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24135 if (encoded_dt.IsValid()) {
24136 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24137 EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
24138 rd.Encode(22, 12) | rm.Encode(5, 0));
24139 AdvanceIT();
24140 return;
24141 }
24142 }
24143 } else {
24144 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24145 if (encoded_dt.IsValid()) {
24146 if (cond.Is(al)) {
24147 EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
24148 rd.Encode(22, 12) | rm.Encode(5, 0));
24149 return;
24150 }
24151 }
24152 }
24153 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24154}
24155
24156void Assembler::vrhadd(
24157 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024158 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024159 CheckIT(cond);
24160 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024161 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024162 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
24163 if (encoded_dt.IsValid()) {
24164 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24165 EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24166 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24167 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24168 AdvanceIT();
24169 return;
24170 }
24171 }
24172 } else {
24173 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
24174 if (encoded_dt.IsValid()) {
24175 if (cond.Is(al)) {
24176 EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24177 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24178 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24179 return;
24180 }
24181 }
24182 }
24183 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24184}
24185
24186void Assembler::vrhadd(
24187 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024188 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024189 CheckIT(cond);
24190 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024191 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024192 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
24193 if (encoded_dt.IsValid()) {
24194 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24195 EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24196 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24197 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24198 AdvanceIT();
24199 return;
24200 }
24201 }
24202 } else {
24203 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
24204 if (encoded_dt.IsValid()) {
24205 if (cond.Is(al)) {
24206 EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24207 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24208 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24209 return;
24210 }
24211 }
24212 }
24213 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24214}
24215
Vincent Belliard564c10c2018-02-06 08:21:16 -080024216void Assembler::vrinta(DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024217 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024218 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024219 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024220 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024221 // VRINTA{<q>}.<dt> <Dd>, <Dm> ; T1
24222 if (encoded_dt.IsValid()) {
24223 EmitT32_32(0xffb20500U | (encoded_dt.GetEncodingValue() << 18) |
24224 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024225 AdvanceIT();
24226 return;
24227 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024228 // VRINTA{<q>}.F64 <Dd>, <Dm> ; T1
24229 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024230 EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24231 AdvanceIT();
24232 return;
24233 }
24234 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024235 // VRINTA{<q>}.<dt> <Dd>, <Dm> ; A1
24236 if (encoded_dt.IsValid()) {
24237 EmitA32(0xf3b20500U | (encoded_dt.GetEncodingValue() << 18) |
24238 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024239 return;
24240 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024241 // VRINTA{<q>}.F64 <Dd>, <Dm> ; A1
24242 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024243 EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24244 return;
24245 }
24246 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024247 Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024248}
24249
Vincent Belliard564c10c2018-02-06 08:21:16 -080024250void Assembler::vrinta(DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024251 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024252 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024253 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024254 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024255 // VRINTA{<q>}.<dt> <Qd>, <Qm> ; T1
24256 if (encoded_dt.IsValid()) {
24257 EmitT32_32(0xffb20540U | (encoded_dt.GetEncodingValue() << 18) |
24258 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024259 AdvanceIT();
24260 return;
24261 }
24262 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024263 // VRINTA{<q>}.<dt> <Qd>, <Qm> ; A1
24264 if (encoded_dt.IsValid()) {
24265 EmitA32(0xf3b20540U | (encoded_dt.GetEncodingValue() << 18) |
24266 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024267 return;
24268 }
24269 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024270 Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024271}
24272
Vincent Belliard564c10c2018-02-06 08:21:16 -080024273void Assembler::vrinta(DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024274 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024275 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024276 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024277 // VRINTA{<q>}.F32 <Sd>, <Sm> ; T1
24278 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024279 EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24280 AdvanceIT();
24281 return;
24282 }
24283 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024284 // VRINTA{<q>}.F32 <Sd>, <Sm> ; A1
24285 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024286 EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24287 return;
24288 }
24289 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024290 Delegate(kVrinta, &Assembler::vrinta, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024291}
24292
Vincent Belliard564c10c2018-02-06 08:21:16 -080024293void Assembler::vrintm(DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024294 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024295 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024296 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024297 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024298 // VRINTM{<q>}.<dt> <Dd>, <Dm> ; T1
24299 if (encoded_dt.IsValid()) {
24300 EmitT32_32(0xffb20680U | (encoded_dt.GetEncodingValue() << 18) |
24301 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024302 AdvanceIT();
24303 return;
24304 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024305 // VRINTM{<q>}.F64 <Dd>, <Dm> ; T1
24306 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024307 EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24308 AdvanceIT();
24309 return;
24310 }
24311 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024312 // VRINTM{<q>}.<dt> <Dd>, <Dm> ; A1
24313 if (encoded_dt.IsValid()) {
24314 EmitA32(0xf3b20680U | (encoded_dt.GetEncodingValue() << 18) |
24315 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024316 return;
24317 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024318 // VRINTM{<q>}.F64 <Dd>, <Dm> ; A1
24319 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024320 EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24321 return;
24322 }
24323 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024324 Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024325}
24326
Vincent Belliard564c10c2018-02-06 08:21:16 -080024327void Assembler::vrintm(DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024328 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024329 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024330 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024331 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024332 // VRINTM{<q>}.<dt> <Qd>, <Qm> ; T1
24333 if (encoded_dt.IsValid()) {
24334 EmitT32_32(0xffb206c0U | (encoded_dt.GetEncodingValue() << 18) |
24335 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024336 AdvanceIT();
24337 return;
24338 }
24339 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024340 // VRINTM{<q>}.<dt> <Qd>, <Qm> ; A1
24341 if (encoded_dt.IsValid()) {
24342 EmitA32(0xf3b206c0U | (encoded_dt.GetEncodingValue() << 18) |
24343 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024344 return;
24345 }
24346 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024347 Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024348}
24349
Vincent Belliard564c10c2018-02-06 08:21:16 -080024350void Assembler::vrintm(DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024351 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024352 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024353 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024354 // VRINTM{<q>}.F32 <Sd>, <Sm> ; T1
24355 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024356 EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24357 AdvanceIT();
24358 return;
24359 }
24360 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024361 // VRINTM{<q>}.F32 <Sd>, <Sm> ; A1
24362 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024363 EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24364 return;
24365 }
24366 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024367 Delegate(kVrintm, &Assembler::vrintm, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024368}
24369
Vincent Belliard564c10c2018-02-06 08:21:16 -080024370void Assembler::vrintn(DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024371 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024372 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024373 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024374 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024375 // VRINTN{<q>}.<dt> <Dd>, <Dm> ; T1
24376 if (encoded_dt.IsValid()) {
24377 EmitT32_32(0xffb20400U | (encoded_dt.GetEncodingValue() << 18) |
24378 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024379 AdvanceIT();
24380 return;
24381 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024382 // VRINTN{<q>}.F64 <Dd>, <Dm> ; T1
24383 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024384 EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24385 AdvanceIT();
24386 return;
24387 }
24388 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024389 // VRINTN{<q>}.<dt> <Dd>, <Dm> ; A1
24390 if (encoded_dt.IsValid()) {
24391 EmitA32(0xf3b20400U | (encoded_dt.GetEncodingValue() << 18) |
24392 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024393 return;
24394 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024395 // VRINTN{<q>}.F64 <Dd>, <Dm> ; A1
24396 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024397 EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24398 return;
24399 }
24400 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024401 Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024402}
24403
Vincent Belliard564c10c2018-02-06 08:21:16 -080024404void Assembler::vrintn(DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024405 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024406 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024407 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024408 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024409 // VRINTN{<q>}.<dt> <Qd>, <Qm> ; T1
24410 if (encoded_dt.IsValid()) {
24411 EmitT32_32(0xffb20440U | (encoded_dt.GetEncodingValue() << 18) |
24412 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024413 AdvanceIT();
24414 return;
24415 }
24416 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024417 // VRINTN{<q>}.<dt> <Qd>, <Qm> ; A1
24418 if (encoded_dt.IsValid()) {
24419 EmitA32(0xf3b20440U | (encoded_dt.GetEncodingValue() << 18) |
24420 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024421 return;
24422 }
24423 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024424 Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024425}
24426
Vincent Belliard564c10c2018-02-06 08:21:16 -080024427void Assembler::vrintn(DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024428 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024429 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024430 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024431 // VRINTN{<q>}.F32 <Sd>, <Sm> ; T1
24432 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024433 EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24434 AdvanceIT();
24435 return;
24436 }
24437 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024438 // VRINTN{<q>}.F32 <Sd>, <Sm> ; A1
24439 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024440 EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24441 return;
24442 }
24443 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024444 Delegate(kVrintn, &Assembler::vrintn, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024445}
24446
Vincent Belliard564c10c2018-02-06 08:21:16 -080024447void Assembler::vrintp(DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024448 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024449 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024450 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024451 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024452 // VRINTP{<q>}.<dt> <Dd>, <Dm> ; T1
24453 if (encoded_dt.IsValid()) {
24454 EmitT32_32(0xffb20780U | (encoded_dt.GetEncodingValue() << 18) |
24455 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024456 AdvanceIT();
24457 return;
24458 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024459 // VRINTP{<q>}.F64 <Dd>, <Dm> ; T1
24460 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024461 EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24462 AdvanceIT();
24463 return;
24464 }
24465 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024466 // VRINTP{<q>}.<dt> <Dd>, <Dm> ; A1
24467 if (encoded_dt.IsValid()) {
24468 EmitA32(0xf3b20780U | (encoded_dt.GetEncodingValue() << 18) |
24469 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024470 return;
24471 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024472 // VRINTP{<q>}.F64 <Dd>, <Dm> ; A1
24473 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024474 EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24475 return;
24476 }
24477 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024478 Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024479}
24480
Vincent Belliard564c10c2018-02-06 08:21:16 -080024481void Assembler::vrintp(DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024482 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024483 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024484 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024485 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024486 // VRINTP{<q>}.<dt> <Qd>, <Qm> ; T1
24487 if (encoded_dt.IsValid()) {
24488 EmitT32_32(0xffb207c0U | (encoded_dt.GetEncodingValue() << 18) |
24489 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024490 AdvanceIT();
24491 return;
24492 }
24493 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024494 // VRINTP{<q>}.<dt> <Qd>, <Qm> ; A1
24495 if (encoded_dt.IsValid()) {
24496 EmitA32(0xf3b207c0U | (encoded_dt.GetEncodingValue() << 18) |
24497 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024498 return;
24499 }
24500 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024501 Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024502}
24503
Vincent Belliard564c10c2018-02-06 08:21:16 -080024504void Assembler::vrintp(DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024505 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024506 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024507 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024508 // VRINTP{<q>}.F32 <Sd>, <Sm> ; T1
24509 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024510 EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24511 AdvanceIT();
24512 return;
24513 }
24514 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024515 // VRINTP{<q>}.F32 <Sd>, <Sm> ; A1
24516 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024517 EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24518 return;
24519 }
24520 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024521 Delegate(kVrintp, &Assembler::vrintp, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024522}
24523
Vincent Belliard564c10c2018-02-06 08:21:16 -080024524void Assembler::vrintr(Condition cond,
24525 DataType dt,
24526 SRegister rd,
24527 SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024528 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024529 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024530 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024531 // VRINTR{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24532 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024533 EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24534 AdvanceIT();
24535 return;
24536 }
24537 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024538 // VRINTR{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24539 if (dt.Is(F32) && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024540 EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24541 rm.Encode(5, 0));
24542 return;
24543 }
24544 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024545 Delegate(kVrintr, &Assembler::vrintr, cond, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024546}
24547
Vincent Belliard564c10c2018-02-06 08:21:16 -080024548void Assembler::vrintr(Condition cond,
24549 DataType dt,
24550 DRegister rd,
24551 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024552 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024553 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024554 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024555 // VRINTR{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24556 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024557 EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24558 AdvanceIT();
24559 return;
24560 }
24561 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024562 // VRINTR{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24563 if (dt.Is(F64) && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024564 EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24565 rm.Encode(5, 0));
24566 return;
24567 }
24568 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024569 Delegate(kVrintr, &Assembler::vrintr, cond, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024570}
24571
Vincent Belliard564c10c2018-02-06 08:21:16 -080024572void Assembler::vrintx(Condition cond,
24573 DataType dt,
24574 DRegister rd,
24575 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024576 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024577 CheckIT(cond);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024578 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024579 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024580 // VRINTX{<q>}.<dt> <Dd>, <Dm> ; T1
24581 if (encoded_dt.IsValid()) {
24582 EmitT32_32(0xffb20480U | (encoded_dt.GetEncodingValue() << 18) |
24583 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024584 AdvanceIT();
24585 return;
24586 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024587 // VRINTX{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24588 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024589 EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24590 AdvanceIT();
24591 return;
24592 }
24593 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024594 // VRINTX{<q>}.<dt> <Dd>, <Dm> ; A1
24595 if (encoded_dt.IsValid()) {
24596 EmitA32(0xf3b20480U | (encoded_dt.GetEncodingValue() << 18) |
24597 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024598 return;
24599 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024600 // VRINTX{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24601 if (dt.Is(F64) && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024602 EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24603 rm.Encode(5, 0));
24604 return;
24605 }
24606 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024607 Delegate(kVrintx, &Assembler::vrintx, cond, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024608}
24609
Vincent Belliard564c10c2018-02-06 08:21:16 -080024610void Assembler::vrintx(DataType dt, 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);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024613 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024614 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024615 // VRINTX{<q>}.<dt> <Qd>, <Qm> ; T1
24616 if (encoded_dt.IsValid()) {
24617 EmitT32_32(0xffb204c0U | (encoded_dt.GetEncodingValue() << 18) |
24618 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024619 AdvanceIT();
24620 return;
24621 }
24622 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024623 // VRINTX{<q>}.<dt> <Qd>, <Qm> ; A1
24624 if (encoded_dt.IsValid()) {
24625 EmitA32(0xf3b204c0U | (encoded_dt.GetEncodingValue() << 18) |
24626 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024627 return;
24628 }
24629 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024630 Delegate(kVrintx, &Assembler::vrintx, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024631}
24632
Vincent Belliard564c10c2018-02-06 08:21:16 -080024633void Assembler::vrintx(Condition cond,
24634 DataType dt,
24635 SRegister rd,
24636 SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024637 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024638 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024639 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024640 // VRINTX{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24641 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024642 EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24643 AdvanceIT();
24644 return;
24645 }
24646 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024647 // VRINTX{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24648 if (dt.Is(F32) && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024649 EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24650 rm.Encode(5, 0));
24651 return;
24652 }
24653 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024654 Delegate(kVrintx, &Assembler::vrintx, cond, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024655}
24656
Vincent Belliard564c10c2018-02-06 08:21:16 -080024657void Assembler::vrintz(Condition cond,
24658 DataType dt,
24659 DRegister rd,
24660 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024661 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024662 CheckIT(cond);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024663 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024664 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024665 // VRINTZ{<q>}.<dt> <Dd>, <Dm> ; T1
24666 if (encoded_dt.IsValid()) {
24667 EmitT32_32(0xffb20580U | (encoded_dt.GetEncodingValue() << 18) |
24668 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024669 AdvanceIT();
24670 return;
24671 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024672 // VRINTZ{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
24673 if (dt.Is(F64)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024674 EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24675 AdvanceIT();
24676 return;
24677 }
24678 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024679 // VRINTZ{<q>}.<dt> <Dd>, <Dm> ; A1
24680 if (encoded_dt.IsValid()) {
24681 EmitA32(0xf3b20580U | (encoded_dt.GetEncodingValue() << 18) |
24682 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024683 return;
24684 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024685 // VRINTZ{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
24686 if (dt.Is(F64) && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024687 EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24688 rm.Encode(5, 0));
24689 return;
24690 }
24691 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024692 Delegate(kVrintz, &Assembler::vrintz, cond, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024693}
24694
Vincent Belliard564c10c2018-02-06 08:21:16 -080024695void Assembler::vrintz(DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024696 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024697 CheckIT(al);
Vincent Belliard564c10c2018-02-06 08:21:16 -080024698 Dt_size_16 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024699 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024700 // VRINTZ{<q>}.<dt> <Qd>, <Qm> ; T1
24701 if (encoded_dt.IsValid()) {
24702 EmitT32_32(0xffb205c0U | (encoded_dt.GetEncodingValue() << 18) |
24703 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024704 AdvanceIT();
24705 return;
24706 }
24707 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024708 // VRINTZ{<q>}.<dt> <Qd>, <Qm> ; A1
24709 if (encoded_dt.IsValid()) {
24710 EmitA32(0xf3b205c0U | (encoded_dt.GetEncodingValue() << 18) |
24711 rd.Encode(22, 12) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010024712 return;
24713 }
24714 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024715 Delegate(kVrintz, &Assembler::vrintz, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024716}
24717
Vincent Belliard564c10c2018-02-06 08:21:16 -080024718void Assembler::vrintz(Condition cond,
24719 DataType dt,
24720 SRegister rd,
24721 SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024722 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024723 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024724 if (IsUsingT32()) {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024725 // VRINTZ{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
24726 if (dt.Is(F32)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024727 EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24728 AdvanceIT();
24729 return;
24730 }
24731 } else {
Vincent Belliard564c10c2018-02-06 08:21:16 -080024732 // VRINTZ{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
24733 if (dt.Is(F32) && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024734 EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24735 rm.Encode(5, 0));
24736 return;
24737 }
24738 }
Vincent Belliard564c10c2018-02-06 08:21:16 -080024739 Delegate(kVrintz, &Assembler::vrintz, cond, dt, rd, rm);
Alexandre Ramesd3832962016-07-04 15:03:43 +010024740}
24741
24742void Assembler::vrshl(
24743 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024744 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024745 CheckIT(cond);
24746 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024747 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024748 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24749 if (encoded_dt.IsValid()) {
24750 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24751 EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24752 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24753 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24754 AdvanceIT();
24755 return;
24756 }
24757 }
24758 } else {
24759 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24760 if (encoded_dt.IsValid()) {
24761 if (cond.Is(al)) {
24762 EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24763 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24764 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24765 return;
24766 }
24767 }
24768 }
24769 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24770}
24771
24772void Assembler::vrshl(
24773 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024774 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024775 CheckIT(cond);
24776 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024777 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024778 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24779 if (encoded_dt.IsValid()) {
24780 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24781 EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24782 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24783 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24784 AdvanceIT();
24785 return;
24786 }
24787 }
24788 } else {
24789 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24790 if (encoded_dt.IsValid()) {
24791 if (cond.Is(al)) {
24792 EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24793 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24794 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24795 return;
24796 }
24797 }
24798 }
24799 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24800}
24801
24802void Assembler::vrshr(Condition cond,
24803 DataType dt,
24804 DRegister rd,
24805 DRegister rm,
24806 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024807 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024808 CheckIT(cond);
24809 if (operand.IsImmediate()) {
24810 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24811 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24812 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024813 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024814 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24815 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24816 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24817 uint32_t imm6 = dt.GetSize() - imm;
24818 EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
24819 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24820 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24821 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24822 AdvanceIT();
24823 return;
24824 }
24825 }
24826 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24827 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24828 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24829 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24830 rm.Encode(5, 0));
24831 AdvanceIT();
24832 return;
24833 }
24834 }
24835 } else {
24836 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24837 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24838 if (cond.Is(al)) {
24839 uint32_t imm6 = dt.GetSize() - imm;
24840 EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
24841 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24842 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24843 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24844 return;
24845 }
24846 }
24847 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24848 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24849 if (cond.Is(al)) {
24850 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24851 rm.Encode(5, 0));
24852 return;
24853 }
24854 }
24855 }
24856 }
24857 }
24858 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24859}
24860
24861void Assembler::vrshr(Condition cond,
24862 DataType dt,
24863 QRegister rd,
24864 QRegister rm,
24865 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024866 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024867 CheckIT(cond);
24868 if (operand.IsImmediate()) {
24869 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24870 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24871 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024872 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024873 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24874 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24875 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24876 uint32_t imm6 = dt.GetSize() - imm;
24877 EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
24878 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24879 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24880 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24881 AdvanceIT();
24882 return;
24883 }
24884 }
24885 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24886 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24887 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24888 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24889 rm.Encode(5, 0));
24890 AdvanceIT();
24891 return;
24892 }
24893 }
24894 } else {
24895 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24896 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24897 if (cond.Is(al)) {
24898 uint32_t imm6 = dt.GetSize() - imm;
24899 EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
24900 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24901 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24902 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24903 return;
24904 }
24905 }
24906 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24907 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24908 if (cond.Is(al)) {
24909 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24910 rm.Encode(5, 0));
24911 return;
24912 }
24913 }
24914 }
24915 }
24916 }
24917 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24918}
24919
24920void Assembler::vrshrn(Condition cond,
24921 DataType dt,
24922 DRegister rd,
24923 QRegister rm,
24924 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024925 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024926 CheckIT(cond);
24927 if (operand.IsImmediate()) {
24928 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24929 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24930 Dt_imm6_3 encoded_dt(dt);
24931 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024932 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024933 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24934 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24935 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24936 uint32_t imm6 = dt.GetSize() / 2 - imm;
24937 EmitT32_32(0xef800850U |
24938 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24939 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24940 AdvanceIT();
24941 return;
24942 }
24943 }
24944 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24945 if (encoded_dt_2.IsValid() && (imm == 0)) {
24946 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24947 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24948 rd.Encode(22, 12) | rm.Encode(5, 0));
24949 AdvanceIT();
24950 return;
24951 }
24952 }
24953 } else {
24954 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24955 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24956 if (cond.Is(al)) {
24957 uint32_t imm6 = dt.GetSize() / 2 - imm;
24958 EmitA32(0xf2800850U |
24959 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24960 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24961 return;
24962 }
24963 }
24964 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24965 if (encoded_dt_2.IsValid() && (imm == 0)) {
24966 if (cond.Is(al)) {
24967 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24968 rd.Encode(22, 12) | rm.Encode(5, 0));
24969 return;
24970 }
24971 }
24972 }
24973 }
24974 }
24975 Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
24976}
24977
24978void Assembler::vrsqrte(Condition cond,
24979 DataType dt,
24980 DRegister rd,
24981 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024982 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024983 CheckIT(cond);
24984 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024985 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024986 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24987 if (encoded_dt.IsValid()) {
24988 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24989 EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24990 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24991 rd.Encode(22, 12) | rm.Encode(5, 0));
24992 AdvanceIT();
24993 return;
24994 }
24995 }
24996 } else {
24997 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24998 if (encoded_dt.IsValid()) {
24999 if (cond.Is(al)) {
25000 EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
25001 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25002 rd.Encode(22, 12) | rm.Encode(5, 0));
25003 return;
25004 }
25005 }
25006 }
25007 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
25008}
25009
25010void Assembler::vrsqrte(Condition cond,
25011 DataType dt,
25012 QRegister rd,
25013 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025014 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025015 CheckIT(cond);
25016 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025017 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025018 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
25019 if (encoded_dt.IsValid()) {
25020 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25021 EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
25022 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25023 rd.Encode(22, 12) | rm.Encode(5, 0));
25024 AdvanceIT();
25025 return;
25026 }
25027 }
25028 } else {
25029 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
25030 if (encoded_dt.IsValid()) {
25031 if (cond.Is(al)) {
25032 EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
25033 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
25034 rd.Encode(22, 12) | rm.Encode(5, 0));
25035 return;
25036 }
25037 }
25038 }
25039 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
25040}
25041
25042void Assembler::vrsqrts(
25043 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025044 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025045 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025046 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025047 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
25048 if (dt.Is(F32)) {
25049 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25050 EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25051 rm.Encode(5, 0));
25052 AdvanceIT();
25053 return;
25054 }
25055 }
25056 } else {
25057 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
25058 if (dt.Is(F32)) {
25059 if (cond.Is(al)) {
25060 EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25061 rm.Encode(5, 0));
25062 return;
25063 }
25064 }
25065 }
25066 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
25067}
25068
25069void Assembler::vrsqrts(
25070 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025071 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025072 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025074 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
25075 if (dt.Is(F32)) {
25076 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25077 EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25078 rm.Encode(5, 0));
25079 AdvanceIT();
25080 return;
25081 }
25082 }
25083 } else {
25084 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
25085 if (dt.Is(F32)) {
25086 if (cond.Is(al)) {
25087 EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25088 rm.Encode(5, 0));
25089 return;
25090 }
25091 }
25092 }
25093 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
25094}
25095
25096void Assembler::vrsra(Condition cond,
25097 DataType dt,
25098 DRegister rd,
25099 DRegister rm,
25100 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025101 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025102 CheckIT(cond);
25103 if (operand.IsImmediate()) {
25104 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25105 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25106 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025107 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025108 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25109 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25110 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25111 uint32_t imm6 = dt.GetSize() - imm;
25112 EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
25113 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25114 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25115 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25116 AdvanceIT();
25117 return;
25118 }
25119 }
25120 } else {
25121 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25122 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25123 if (cond.Is(al)) {
25124 uint32_t imm6 = dt.GetSize() - imm;
25125 EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
25126 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25127 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25128 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25129 return;
25130 }
25131 }
25132 }
25133 }
25134 }
25135 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25136}
25137
25138void Assembler::vrsra(Condition cond,
25139 DataType dt,
25140 QRegister rd,
25141 QRegister rm,
25142 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025143 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025144 CheckIT(cond);
25145 if (operand.IsImmediate()) {
25146 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25147 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25148 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025149 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025150 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25151 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25152 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25153 uint32_t imm6 = dt.GetSize() - imm;
25154 EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
25155 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25156 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25157 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25158 AdvanceIT();
25159 return;
25160 }
25161 }
25162 } else {
25163 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25164 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25165 if (cond.Is(al)) {
25166 uint32_t imm6 = dt.GetSize() - imm;
25167 EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
25168 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25169 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25170 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25171 return;
25172 }
25173 }
25174 }
25175 }
25176 }
25177 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25178}
25179
25180void Assembler::vrsubhn(
25181 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025182 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025183 CheckIT(cond);
25184 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025185 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025186 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
25187 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25188 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25189 EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
25190 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25191 AdvanceIT();
25192 return;
25193 }
25194 }
25195 } else {
25196 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
25197 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25198 if (cond.Is(al)) {
25199 EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
25200 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25201 return;
25202 }
25203 }
25204 }
25205 Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
25206}
25207
25208void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025209 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025210 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025211 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025212 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
25213 if (OutsideITBlock() && dt.Is(F64)) {
25214 EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25215 rm.Encode(5, 0));
25216 AdvanceIT();
25217 return;
25218 }
25219 } else {
25220 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
25221 if (dt.Is(F64)) {
25222 EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25223 rm.Encode(5, 0));
25224 return;
25225 }
25226 }
25227 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25228}
25229
25230void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025231 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025232 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025233 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025234 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
25235 if (OutsideITBlock() && dt.Is(F32)) {
25236 EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25237 rm.Encode(5, 0));
25238 AdvanceIT();
25239 return;
25240 }
25241 } else {
25242 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
25243 if (dt.Is(F32)) {
25244 EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25245 rm.Encode(5, 0));
25246 return;
25247 }
25248 }
25249 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25250}
25251
25252void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025253 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025254 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025255 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025256 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
25257 if (OutsideITBlock() && dt.Is(F64)) {
25258 EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25259 rm.Encode(5, 0));
25260 AdvanceIT();
25261 return;
25262 }
25263 } else {
25264 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
25265 if (dt.Is(F64)) {
25266 EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25267 rm.Encode(5, 0));
25268 return;
25269 }
25270 }
25271 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25272}
25273
25274void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025275 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025276 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025277 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025278 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
25279 if (OutsideITBlock() && dt.Is(F32)) {
25280 EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25281 rm.Encode(5, 0));
25282 AdvanceIT();
25283 return;
25284 }
25285 } else {
25286 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
25287 if (dt.Is(F32)) {
25288 EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25289 rm.Encode(5, 0));
25290 return;
25291 }
25292 }
25293 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25294}
25295
25296void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025297 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025298 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025299 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025300 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
25301 if (OutsideITBlock() && dt.Is(F64)) {
25302 EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25303 rm.Encode(5, 0));
25304 AdvanceIT();
25305 return;
25306 }
25307 } else {
25308 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
25309 if (dt.Is(F64)) {
25310 EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25311 rm.Encode(5, 0));
25312 return;
25313 }
25314 }
25315 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25316}
25317
25318void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025319 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025320 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025321 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025322 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
25323 if (OutsideITBlock() && dt.Is(F32)) {
25324 EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25325 rm.Encode(5, 0));
25326 AdvanceIT();
25327 return;
25328 }
25329 } else {
25330 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
25331 if (dt.Is(F32)) {
25332 EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25333 rm.Encode(5, 0));
25334 return;
25335 }
25336 }
25337 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25338}
25339
25340void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025341 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025342 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025343 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025344 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
25345 if (OutsideITBlock() && dt.Is(F64)) {
25346 EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25347 rm.Encode(5, 0));
25348 AdvanceIT();
25349 return;
25350 }
25351 } else {
25352 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
25353 if (dt.Is(F64)) {
25354 EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25355 rm.Encode(5, 0));
25356 return;
25357 }
25358 }
25359 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25360}
25361
25362void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025363 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025364 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025365 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025366 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
25367 if (OutsideITBlock() && dt.Is(F32)) {
25368 EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25369 rm.Encode(5, 0));
25370 AdvanceIT();
25371 return;
25372 }
25373 } else {
25374 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
25375 if (dt.Is(F32)) {
25376 EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25377 rm.Encode(5, 0));
25378 return;
25379 }
25380 }
25381 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25382}
25383
25384void Assembler::vshl(Condition cond,
25385 DataType dt,
25386 DRegister rd,
25387 DRegister rm,
25388 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025389 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025390 CheckIT(cond);
25391 if (operand.IsImmediate()) {
25392 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25393 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25394 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025396 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
25397 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25398 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25399 uint32_t imm6 = imm;
25400 EmitT32_32(0xef800510U |
25401 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25402 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25403 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25404 AdvanceIT();
25405 return;
25406 }
25407 }
25408 } else {
25409 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
25410 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25411 if (cond.Is(al)) {
25412 uint32_t imm6 = imm;
25413 EmitA32(0xf2800510U |
25414 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25415 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25416 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25417 return;
25418 }
25419 }
25420 }
25421 }
25422 }
25423 if (operand.IsRegister()) {
25424 DRegister rn = operand.GetRegister();
25425 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025426 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025427 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
25428 if (encoded_dt.IsValid()) {
25429 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25430 EmitT32_32(0xef000400U |
25431 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25432 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25433 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25434 AdvanceIT();
25435 return;
25436 }
25437 }
25438 } else {
25439 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
25440 if (encoded_dt.IsValid()) {
25441 if (cond.Is(al)) {
25442 EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25443 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25444 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25445 return;
25446 }
25447 }
25448 }
25449 }
25450 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25451}
25452
25453void Assembler::vshl(Condition cond,
25454 DataType dt,
25455 QRegister rd,
25456 QRegister rm,
25457 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025458 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025459 CheckIT(cond);
25460 if (operand.IsImmediate()) {
25461 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25462 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25463 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025465 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
25466 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25467 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25468 uint32_t imm6 = imm;
25469 EmitT32_32(0xef800550U |
25470 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25471 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25472 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25473 AdvanceIT();
25474 return;
25475 }
25476 }
25477 } else {
25478 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
25479 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25480 if (cond.Is(al)) {
25481 uint32_t imm6 = imm;
25482 EmitA32(0xf2800550U |
25483 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25484 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25485 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25486 return;
25487 }
25488 }
25489 }
25490 }
25491 }
25492 if (operand.IsRegister()) {
25493 QRegister rn = operand.GetRegister();
25494 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025495 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025496 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
25497 if (encoded_dt.IsValid()) {
25498 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25499 EmitT32_32(0xef000440U |
25500 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25501 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25502 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25503 AdvanceIT();
25504 return;
25505 }
25506 }
25507 } else {
25508 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
25509 if (encoded_dt.IsValid()) {
25510 if (cond.Is(al)) {
25511 EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25512 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25513 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25514 return;
25515 }
25516 }
25517 }
25518 }
25519 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25520}
25521
25522void Assembler::vshll(Condition cond,
25523 DataType dt,
25524 QRegister rd,
25525 DRegister rm,
25526 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025527 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025528 CheckIT(cond);
25529 if (operand.IsImmediate()) {
25530 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25531 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25532 Dt_imm6_4 encoded_dt(dt);
Vincent Belliard564c10c2018-02-06 08:21:16 -080025533 Dt_size_17 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025534 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025535 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
25536 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25537 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25538 uint32_t imm6 = dt.GetSize() + imm;
25539 EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
25540 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25541 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25542 AdvanceIT();
25543 return;
25544 }
25545 }
25546 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
25547 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25548 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25549 EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25550 rd.Encode(22, 12) | rm.Encode(5, 0));
25551 AdvanceIT();
25552 return;
25553 }
25554 }
25555 } else {
25556 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
25557 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25558 if (cond.Is(al)) {
25559 uint32_t imm6 = dt.GetSize() + imm;
25560 EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
25561 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25562 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25563 return;
25564 }
25565 }
25566 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
25567 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25568 if (cond.Is(al)) {
25569 EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25570 rd.Encode(22, 12) | rm.Encode(5, 0));
25571 return;
25572 }
25573 }
25574 }
25575 }
25576 }
25577 Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
25578}
25579
25580void Assembler::vshr(Condition cond,
25581 DataType dt,
25582 DRegister rd,
25583 DRegister rm,
25584 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025585 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025586 CheckIT(cond);
25587 if (operand.IsImmediate()) {
25588 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25589 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25590 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025591 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025592 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25593 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25594 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25595 uint32_t imm6 = dt.GetSize() - imm;
25596 EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
25597 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25598 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25599 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25600 AdvanceIT();
25601 return;
25602 }
25603 }
25604 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
25605 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25606 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25607 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25608 rm.Encode(5, 0));
25609 AdvanceIT();
25610 return;
25611 }
25612 }
25613 } else {
25614 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25615 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25616 if (cond.Is(al)) {
25617 uint32_t imm6 = dt.GetSize() - imm;
25618 EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
25619 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25620 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25621 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25622 return;
25623 }
25624 }
25625 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
25626 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25627 if (cond.Is(al)) {
25628 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25629 rm.Encode(5, 0));
25630 return;
25631 }
25632 }
25633 }
25634 }
25635 }
25636 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25637}
25638
25639void Assembler::vshr(Condition cond,
25640 DataType dt,
25641 QRegister rd,
25642 QRegister rm,
25643 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025644 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025645 CheckIT(cond);
25646 if (operand.IsImmediate()) {
25647 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25648 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25649 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025650 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025651 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25652 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25653 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25654 uint32_t imm6 = dt.GetSize() - imm;
25655 EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
25656 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25657 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25658 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25659 AdvanceIT();
25660 return;
25661 }
25662 }
25663 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
25664 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25665 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25666 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25667 rm.Encode(5, 0));
25668 AdvanceIT();
25669 return;
25670 }
25671 }
25672 } else {
25673 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25674 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25675 if (cond.Is(al)) {
25676 uint32_t imm6 = dt.GetSize() - imm;
25677 EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
25678 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25679 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25680 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25681 return;
25682 }
25683 }
25684 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
25685 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25686 if (cond.Is(al)) {
25687 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25688 rm.Encode(5, 0));
25689 return;
25690 }
25691 }
25692 }
25693 }
25694 }
25695 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25696}
25697
25698void Assembler::vshrn(Condition cond,
25699 DataType dt,
25700 DRegister rd,
25701 QRegister rm,
25702 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025703 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025704 CheckIT(cond);
25705 if (operand.IsImmediate()) {
25706 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25707 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25708 Dt_imm6_3 encoded_dt(dt);
25709 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025710 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025711 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
25712 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25713 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25714 uint32_t imm6 = dt.GetSize() / 2 - imm;
25715 EmitT32_32(0xef800810U |
25716 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25717 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25718 AdvanceIT();
25719 return;
25720 }
25721 }
25722 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
25723 if (encoded_dt_2.IsValid() && (imm == 0)) {
25724 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25725 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25726 rd.Encode(22, 12) | rm.Encode(5, 0));
25727 AdvanceIT();
25728 return;
25729 }
25730 }
25731 } else {
25732 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
25733 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25734 if (cond.Is(al)) {
25735 uint32_t imm6 = dt.GetSize() / 2 - imm;
25736 EmitA32(0xf2800810U |
25737 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25738 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25739 return;
25740 }
25741 }
25742 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
25743 if (encoded_dt_2.IsValid() && (imm == 0)) {
25744 if (cond.Is(al)) {
25745 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25746 rd.Encode(22, 12) | rm.Encode(5, 0));
25747 return;
25748 }
25749 }
25750 }
25751 }
25752 }
25753 Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
25754}
25755
25756void Assembler::vsli(Condition cond,
25757 DataType dt,
25758 DRegister rd,
25759 DRegister rm,
25760 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025761 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025762 CheckIT(cond);
25763 if (operand.IsImmediate()) {
25764 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25765 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25766 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025767 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025768 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25769 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25770 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25771 uint32_t imm6 = imm;
25772 EmitT32_32(0xff800510U |
25773 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25774 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25775 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25776 AdvanceIT();
25777 return;
25778 }
25779 }
25780 } else {
25781 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25782 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25783 if (cond.Is(al)) {
25784 uint32_t imm6 = imm;
25785 EmitA32(0xf3800510U |
25786 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25787 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25788 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25789 return;
25790 }
25791 }
25792 }
25793 }
25794 }
25795 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25796}
25797
25798void Assembler::vsli(Condition cond,
25799 DataType dt,
25800 QRegister rd,
25801 QRegister rm,
25802 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025803 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025804 CheckIT(cond);
25805 if (operand.IsImmediate()) {
25806 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25807 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25808 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025809 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025810 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25811 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25812 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25813 uint32_t imm6 = imm;
25814 EmitT32_32(0xff800550U |
25815 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25816 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25817 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25818 AdvanceIT();
25819 return;
25820 }
25821 }
25822 } else {
25823 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25824 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25825 if (cond.Is(al)) {
25826 uint32_t imm6 = imm;
25827 EmitA32(0xf3800550U |
25828 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25829 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25830 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25831 return;
25832 }
25833 }
25834 }
25835 }
25836 }
25837 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25838}
25839
25840void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025841 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025842 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025843 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025844 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
25845 if (dt.Is(F32)) {
25846 EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25847 AdvanceIT();
25848 return;
25849 }
25850 } else {
25851 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
25852 if (dt.Is(F32) && cond.IsNotNever()) {
25853 EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25854 rm.Encode(5, 0));
25855 return;
25856 }
25857 }
25858 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25859}
25860
25861void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025862 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025863 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025864 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025865 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
25866 if (dt.Is(F64)) {
25867 EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25868 AdvanceIT();
25869 return;
25870 }
25871 } else {
25872 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
25873 if (dt.Is(F64) && cond.IsNotNever()) {
25874 EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25875 rm.Encode(5, 0));
25876 return;
25877 }
25878 }
25879 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25880}
25881
25882void Assembler::vsra(Condition cond,
25883 DataType dt,
25884 DRegister rd,
25885 DRegister rm,
25886 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025887 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025888 CheckIT(cond);
25889 if (operand.IsImmediate()) {
25890 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25891 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25892 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025893 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025894 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25895 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25896 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25897 uint32_t imm6 = dt.GetSize() - imm;
25898 EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
25899 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25900 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25901 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25902 AdvanceIT();
25903 return;
25904 }
25905 }
25906 } else {
25907 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25908 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25909 if (cond.Is(al)) {
25910 uint32_t imm6 = dt.GetSize() - imm;
25911 EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
25912 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25913 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25914 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25915 return;
25916 }
25917 }
25918 }
25919 }
25920 }
25921 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25922}
25923
25924void Assembler::vsra(Condition cond,
25925 DataType dt,
25926 QRegister rd,
25927 QRegister rm,
25928 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025929 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025930 CheckIT(cond);
25931 if (operand.IsImmediate()) {
25932 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25933 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25934 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025936 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25937 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25938 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25939 uint32_t imm6 = dt.GetSize() - imm;
25940 EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
25941 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25942 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25943 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25944 AdvanceIT();
25945 return;
25946 }
25947 }
25948 } else {
25949 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25950 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25951 if (cond.Is(al)) {
25952 uint32_t imm6 = dt.GetSize() - imm;
25953 EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
25954 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25955 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25956 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25957 return;
25958 }
25959 }
25960 }
25961 }
25962 }
25963 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25964}
25965
25966void Assembler::vsri(Condition cond,
25967 DataType dt,
25968 DRegister rd,
25969 DRegister rm,
25970 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025971 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025972 CheckIT(cond);
25973 if (operand.IsImmediate()) {
25974 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25975 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25976 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025977 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025978 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25979 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25980 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25981 uint32_t imm6 = dt.GetSize() - imm;
25982 EmitT32_32(0xff800410U |
25983 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25984 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25985 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25986 AdvanceIT();
25987 return;
25988 }
25989 }
25990 } else {
25991 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25992 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25993 if (cond.Is(al)) {
25994 uint32_t imm6 = dt.GetSize() - imm;
25995 EmitA32(0xf3800410U |
25996 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25997 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25998 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25999 return;
26000 }
26001 }
26002 }
26003 }
26004 }
26005 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
26006}
26007
26008void Assembler::vsri(Condition cond,
26009 DataType dt,
26010 QRegister rd,
26011 QRegister rm,
26012 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026013 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026014 CheckIT(cond);
26015 if (operand.IsImmediate()) {
26016 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
26017 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
26018 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026019 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026020 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
26021 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
26022 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26023 uint32_t imm6 = dt.GetSize() - imm;
26024 EmitT32_32(0xff800450U |
26025 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
26026 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
26027 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
26028 AdvanceIT();
26029 return;
26030 }
26031 }
26032 } else {
26033 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
26034 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
26035 if (cond.Is(al)) {
26036 uint32_t imm6 = dt.GetSize() - imm;
26037 EmitA32(0xf3800450U |
26038 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
26039 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
26040 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
26041 return;
26042 }
26043 }
26044 }
26045 }
26046 }
26047 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
26048}
26049
26050void Assembler::vst1(Condition cond,
26051 DataType dt,
26052 const NeonRegisterList& nreglist,
26053 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026054 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026055 CheckIT(cond);
26056 if (operand.IsImmediateZero()) {
26057 Register rn = operand.GetBaseRegister();
26058 Alignment align = operand.GetAlignment();
26059 Dt_size_6 encoded_dt(dt);
26060 Dt_size_7 encoded_dt_2(dt);
26061 Align_align_5 encoded_align_1(align, nreglist);
26062 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026063 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026064 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26065 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26066 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026067 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026068 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026069 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26070 const DRegister& first = nreglist.GetFirstDRegister();
26071 uint32_t len_encoding;
26072 switch (nreglist.GetLength()) {
26073 default:
26074 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26075 case 1:
26076 len_encoding = 0x7;
26077 break;
26078 case 2:
26079 len_encoding = 0xa;
26080 break;
26081 case 3:
26082 len_encoding = 0x6;
26083 break;
26084 case 4:
26085 len_encoding = 0x2;
26086 break;
26087 }
26088 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26089 (encoded_align_1.GetEncodingValue() << 4) |
26090 first.Encode(22, 12) | (len_encoding << 8) |
26091 (rn.GetCode() << 16));
26092 AdvanceIT();
26093 return;
26094 }
26095 }
26096 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
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) || AllowStronglyDiscouraged()) {
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 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26121 (encoded_align_1.GetEncodingValue() << 4) |
26122 first.Encode(22, 12) | (len_encoding << 8) |
26123 (rn.GetCode() << 16));
26124 AdvanceIT();
26125 return;
26126 }
26127 }
26128 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26129 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026130 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026131 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026132 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26133 const DRegister& first = nreglist.GetFirstDRegister();
26134 EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26135 (encoded_align_2.GetEncodingValue() << 4) |
26136 first.Encode(22, 12) | (rn.GetCode() << 16));
26137 AdvanceIT();
26138 return;
26139 }
26140 }
26141 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26142 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026143 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026144 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026145 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26146 const DRegister& first = nreglist.GetFirstDRegister();
26147 EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26148 (encoded_align_2.GetEncodingValue() << 4) |
26149 first.Encode(22, 12) | (rn.GetCode() << 16));
26150 AdvanceIT();
26151 return;
26152 }
26153 }
26154 } else {
26155 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26156 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26157 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026158 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026159 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026160 if (cond.Is(al)) {
26161 const DRegister& first = nreglist.GetFirstDRegister();
26162 uint32_t len_encoding;
26163 switch (nreglist.GetLength()) {
26164 default:
26165 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26166 case 1:
26167 len_encoding = 0x7;
26168 break;
26169 case 2:
26170 len_encoding = 0xa;
26171 break;
26172 case 3:
26173 len_encoding = 0x6;
26174 break;
26175 case 4:
26176 len_encoding = 0x2;
26177 break;
26178 }
26179 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26180 (encoded_align_1.GetEncodingValue() << 4) |
26181 first.Encode(22, 12) | (len_encoding << 8) |
26182 (rn.GetCode() << 16));
26183 return;
26184 }
26185 }
26186 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26187 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26188 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026189 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026190 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026191 if (cond.Is(al)) {
26192 const DRegister& first = nreglist.GetFirstDRegister();
26193 uint32_t len_encoding;
26194 switch (nreglist.GetLength()) {
26195 default:
26196 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26197 case 1:
26198 len_encoding = 0x7;
26199 break;
26200 case 2:
26201 len_encoding = 0xa;
26202 break;
26203 case 3:
26204 len_encoding = 0x6;
26205 break;
26206 case 4:
26207 len_encoding = 0x2;
26208 break;
26209 }
26210 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26211 (encoded_align_1.GetEncodingValue() << 4) |
26212 first.Encode(22, 12) | (len_encoding << 8) |
26213 (rn.GetCode() << 16));
26214 return;
26215 }
26216 }
26217 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26218 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026219 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026220 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026221 if (cond.Is(al)) {
26222 const DRegister& first = nreglist.GetFirstDRegister();
26223 EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26224 (encoded_align_2.GetEncodingValue() << 4) |
26225 first.Encode(22, 12) | (rn.GetCode() << 16));
26226 return;
26227 }
26228 }
26229 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26230 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026231 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026232 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026233 if (cond.Is(al)) {
26234 const DRegister& first = nreglist.GetFirstDRegister();
26235 EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26236 (encoded_align_2.GetEncodingValue() << 4) |
26237 first.Encode(22, 12) | (rn.GetCode() << 16));
26238 return;
26239 }
26240 }
26241 }
26242 }
26243 if (operand.IsPlainRegister()) {
26244 Register rn = operand.GetBaseRegister();
26245 Alignment align = operand.GetAlignment();
26246 Register rm = operand.GetOffsetRegister();
26247 Dt_size_6 encoded_dt(dt);
26248 Dt_size_7 encoded_dt_2(dt);
26249 Align_align_5 encoded_align_1(align, nreglist);
26250 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026251 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026252 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26253 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26254 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026255 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026256 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26257 const DRegister& first = nreglist.GetFirstDRegister();
26258 uint32_t len_encoding;
26259 switch (nreglist.GetLength()) {
26260 default:
26261 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26262 case 1:
26263 len_encoding = 0x7;
26264 break;
26265 case 2:
26266 len_encoding = 0xa;
26267 break;
26268 case 3:
26269 len_encoding = 0x6;
26270 break;
26271 case 4:
26272 len_encoding = 0x2;
26273 break;
26274 }
26275 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26276 (encoded_align_1.GetEncodingValue() << 4) |
26277 first.Encode(22, 12) | (len_encoding << 8) |
26278 (rn.GetCode() << 16) | rm.GetCode());
26279 AdvanceIT();
26280 return;
26281 }
26282 }
26283 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26284 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026285 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26286 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026287 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26288 const DRegister& first = nreglist.GetFirstDRegister();
26289 EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26290 (encoded_align_2.GetEncodingValue() << 4) |
26291 first.Encode(22, 12) | (rn.GetCode() << 16) |
26292 rm.GetCode());
26293 AdvanceIT();
26294 return;
26295 }
26296 }
26297 } else {
26298 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26299 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26300 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026301 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026302 if (cond.Is(al)) {
26303 const DRegister& first = nreglist.GetFirstDRegister();
26304 uint32_t len_encoding;
26305 switch (nreglist.GetLength()) {
26306 default:
26307 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26308 case 1:
26309 len_encoding = 0x7;
26310 break;
26311 case 2:
26312 len_encoding = 0xa;
26313 break;
26314 case 3:
26315 len_encoding = 0x6;
26316 break;
26317 case 4:
26318 len_encoding = 0x2;
26319 break;
26320 }
26321 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26322 (encoded_align_1.GetEncodingValue() << 4) |
26323 first.Encode(22, 12) | (len_encoding << 8) |
26324 (rn.GetCode() << 16) | rm.GetCode());
26325 return;
26326 }
26327 }
26328 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26329 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026330 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26331 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026332 if (cond.Is(al)) {
26333 const DRegister& first = nreglist.GetFirstDRegister();
26334 EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26335 (encoded_align_2.GetEncodingValue() << 4) |
26336 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26337 return;
26338 }
26339 }
26340 }
26341 }
26342 Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
26343}
26344
26345void Assembler::vst2(Condition cond,
26346 DataType dt,
26347 const NeonRegisterList& nreglist,
26348 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026349 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026350 CheckIT(cond);
26351 if (operand.IsImmediateZero()) {
26352 Register rn = operand.GetBaseRegister();
26353 Alignment align = operand.GetAlignment();
26354 Dt_size_7 encoded_dt(dt);
26355 Align_align_2 encoded_align_1(align, nreglist);
26356 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026357 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026358 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26359 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26360 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26361 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26362 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026363 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026364 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026365 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26366 const DRegister& first = nreglist.GetFirstDRegister();
26367 uint32_t len_encoding;
26368 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26369 len_encoding = 0x8;
26370 }
26371 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26372 len_encoding = 0x9;
26373 }
26374 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26375 len_encoding = 0x3;
26376 }
26377 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26378 (encoded_align_1.GetEncodingValue() << 4) |
26379 first.Encode(22, 12) | (len_encoding << 8) |
26380 (rn.GetCode() << 16));
26381 AdvanceIT();
26382 return;
26383 }
26384 }
26385 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26386 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26387 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26388 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26389 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026390 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026391 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026392 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26393 const DRegister& first = nreglist.GetFirstDRegister();
26394 uint32_t len_encoding;
26395 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26396 len_encoding = 0x8;
26397 }
26398 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26399 len_encoding = 0x9;
26400 }
26401 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26402 len_encoding = 0x3;
26403 }
26404 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26405 (encoded_align_1.GetEncodingValue() << 4) |
26406 first.Encode(22, 12) | (len_encoding << 8) |
26407 (rn.GetCode() << 16));
26408 AdvanceIT();
26409 return;
26410 }
26411 }
26412 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26413 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26414 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26415 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026416 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026417 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026418 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26419 const DRegister& first = nreglist.GetFirstDRegister();
26420 EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
26421 (encoded_align_2.GetEncodingValue() << 4) |
26422 first.Encode(22, 12) | (rn.GetCode() << 16));
26423 AdvanceIT();
26424 return;
26425 }
26426 }
26427 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26428 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26429 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26430 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026431 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026432 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026433 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26434 const DRegister& first = nreglist.GetFirstDRegister();
26435 EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
26436 (encoded_align_2.GetEncodingValue() << 4) |
26437 first.Encode(22, 12) | (rn.GetCode() << 16));
26438 AdvanceIT();
26439 return;
26440 }
26441 }
26442 } else {
26443 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
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))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026448 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026449 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026450 if (cond.Is(al)) {
26451 const DRegister& first = nreglist.GetFirstDRegister();
26452 uint32_t len_encoding;
26453 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26454 len_encoding = 0x8;
26455 }
26456 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26457 len_encoding = 0x9;
26458 }
26459 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26460 len_encoding = 0x3;
26461 }
26462 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26463 (encoded_align_1.GetEncodingValue() << 4) |
26464 first.Encode(22, 12) | (len_encoding << 8) |
26465 (rn.GetCode() << 16));
26466 return;
26467 }
26468 }
26469 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26470 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26471 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26472 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26473 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026474 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026475 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026476 if (cond.Is(al)) {
26477 const DRegister& first = nreglist.GetFirstDRegister();
26478 uint32_t len_encoding;
26479 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26480 len_encoding = 0x8;
26481 }
26482 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26483 len_encoding = 0x9;
26484 }
26485 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26486 len_encoding = 0x3;
26487 }
26488 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26489 (encoded_align_1.GetEncodingValue() << 4) |
26490 first.Encode(22, 12) | (len_encoding << 8) |
26491 (rn.GetCode() << 16));
26492 return;
26493 }
26494 }
26495 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26496 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26497 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26498 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026499 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026500 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026501 if (cond.Is(al)) {
26502 const DRegister& first = nreglist.GetFirstDRegister();
26503 EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
26504 (encoded_align_2.GetEncodingValue() << 4) |
26505 first.Encode(22, 12) | (rn.GetCode() << 16));
26506 return;
26507 }
26508 }
26509 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26510 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26511 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26512 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026513 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026514 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026515 if (cond.Is(al)) {
26516 const DRegister& first = nreglist.GetFirstDRegister();
26517 EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
26518 (encoded_align_2.GetEncodingValue() << 4) |
26519 first.Encode(22, 12) | (rn.GetCode() << 16));
26520 return;
26521 }
26522 }
26523 }
26524 }
26525 if (operand.IsPlainRegister()) {
26526 Register rn = operand.GetBaseRegister();
26527 Alignment align = operand.GetAlignment();
26528 Register rm = operand.GetOffsetRegister();
26529 Dt_size_7 encoded_dt(dt);
26530 Align_align_2 encoded_align_1(align, nreglist);
26531 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026532 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026533 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26534 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26535 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26536 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26537 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026538 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026539 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26540 const DRegister& first = nreglist.GetFirstDRegister();
26541 uint32_t len_encoding;
26542 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26543 len_encoding = 0x8;
26544 }
26545 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26546 len_encoding = 0x9;
26547 }
26548 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26549 len_encoding = 0x3;
26550 }
26551 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26552 (encoded_align_1.GetEncodingValue() << 4) |
26553 first.Encode(22, 12) | (len_encoding << 8) |
26554 (rn.GetCode() << 16) | rm.GetCode());
26555 AdvanceIT();
26556 return;
26557 }
26558 }
26559 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26560 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26561 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26562 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026563 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026564 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26565 const DRegister& first = nreglist.GetFirstDRegister();
26566 EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
26567 (encoded_align_2.GetEncodingValue() << 4) |
26568 first.Encode(22, 12) | (rn.GetCode() << 16) |
26569 rm.GetCode());
26570 AdvanceIT();
26571 return;
26572 }
26573 }
26574 } else {
26575 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26576 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26577 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26578 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26579 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026580 !rm.IsPC() && !rm.IsSP() && (!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;
26584 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26585 len_encoding = 0x8;
26586 }
26587 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26588 len_encoding = 0x9;
26589 }
26590 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26591 len_encoding = 0x3;
26592 }
26593 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26594 (encoded_align_1.GetEncodingValue() << 4) |
26595 first.Encode(22, 12) | (len_encoding << 8) |
26596 (rn.GetCode() << 16) | rm.GetCode());
26597 return;
26598 }
26599 }
26600 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26601 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26602 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26603 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026604 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026605 if (cond.Is(al)) {
26606 const DRegister& first = nreglist.GetFirstDRegister();
26607 EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
26608 (encoded_align_2.GetEncodingValue() << 4) |
26609 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26610 return;
26611 }
26612 }
26613 }
26614 }
26615 Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
26616}
26617
26618void Assembler::vst3(Condition cond,
26619 DataType dt,
26620 const NeonRegisterList& nreglist,
26621 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026622 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026623 CheckIT(cond);
26624 if (operand.IsImmediateZero()) {
26625 Register rn = operand.GetBaseRegister();
26626 Alignment align = operand.GetAlignment();
26627 Dt_size_7 encoded_dt(dt);
26628 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026629 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026630 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26631 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26632 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26633 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026634 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026635 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026636 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26637 const DRegister& first = nreglist.GetFirstDRegister();
26638 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26639 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26640 (encoded_align_1.GetEncodingValue() << 4) |
26641 first.Encode(22, 12) | (len_encoding << 8) |
26642 (rn.GetCode() << 16));
26643 AdvanceIT();
26644 return;
26645 }
26646 }
26647 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26648 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26649 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26650 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026651 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026652 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026653 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26654 const DRegister& first = nreglist.GetFirstDRegister();
26655 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26656 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26657 (encoded_align_1.GetEncodingValue() << 4) |
26658 first.Encode(22, 12) | (len_encoding << 8) |
26659 (rn.GetCode() << 16));
26660 AdvanceIT();
26661 return;
26662 }
26663 }
26664 } else {
26665 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26666 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26667 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26668 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026669 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026670 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026671 if (cond.Is(al)) {
26672 const DRegister& first = nreglist.GetFirstDRegister();
26673 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26674 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26675 (encoded_align_1.GetEncodingValue() << 4) |
26676 first.Encode(22, 12) | (len_encoding << 8) |
26677 (rn.GetCode() << 16));
26678 return;
26679 }
26680 }
26681 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26682 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26683 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26684 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026685 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026686 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026687 if (cond.Is(al)) {
26688 const DRegister& first = nreglist.GetFirstDRegister();
26689 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26690 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26691 (encoded_align_1.GetEncodingValue() << 4) |
26692 first.Encode(22, 12) | (len_encoding << 8) |
26693 (rn.GetCode() << 16));
26694 return;
26695 }
26696 }
26697 }
26698 }
26699 if (operand.IsPlainRegister()) {
26700 Register rn = operand.GetBaseRegister();
26701 Alignment align = operand.GetAlignment();
26702 Register rm = operand.GetOffsetRegister();
26703 Dt_size_7 encoded_dt(dt);
26704 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026705 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026706 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26707 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26708 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26709 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026710 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026711 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26712 const DRegister& first = nreglist.GetFirstDRegister();
26713 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26714 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26715 (encoded_align_1.GetEncodingValue() << 4) |
26716 first.Encode(22, 12) | (len_encoding << 8) |
26717 (rn.GetCode() << 16) | rm.GetCode());
26718 AdvanceIT();
26719 return;
26720 }
26721 }
26722 } else {
26723 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26724 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26725 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26726 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026727 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026728 if (cond.Is(al)) {
26729 const DRegister& first = nreglist.GetFirstDRegister();
26730 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26731 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26732 (encoded_align_1.GetEncodingValue() << 4) |
26733 first.Encode(22, 12) | (len_encoding << 8) |
26734 (rn.GetCode() << 16) | rm.GetCode());
26735 return;
26736 }
26737 }
26738 }
26739 }
26740 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26741}
26742
26743void Assembler::vst3(Condition cond,
26744 DataType dt,
26745 const NeonRegisterList& nreglist,
26746 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026747 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026748 CheckIT(cond);
26749 if (operand.IsImmediateZero()) {
26750 Register rn = operand.GetBaseRegister();
26751 Dt_size_7 encoded_dt(dt);
26752 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026754 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
26755 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26756 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26757 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026758 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026759 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26760 const DRegister& first = nreglist.GetFirstDRegister();
26761 EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
26762 (encoded_align_1.GetEncodingValue() << 4) |
26763 first.Encode(22, 12) | (rn.GetCode() << 16));
26764 AdvanceIT();
26765 return;
26766 }
26767 }
26768 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
26769 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26770 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26771 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070026772 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026773 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26774 const DRegister& first = nreglist.GetFirstDRegister();
26775 EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
26776 (encoded_align_1.GetEncodingValue() << 4) |
26777 first.Encode(22, 12) | (rn.GetCode() << 16));
26778 AdvanceIT();
26779 return;
26780 }
26781 }
26782 } else {
26783 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
26784 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26785 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26786 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026787 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026788 if (cond.Is(al)) {
26789 const DRegister& first = nreglist.GetFirstDRegister();
26790 EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
26791 (encoded_align_1.GetEncodingValue() << 4) |
26792 first.Encode(22, 12) | (rn.GetCode() << 16));
26793 return;
26794 }
26795 }
26796 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
26797 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26798 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26799 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard36fb1ce2017-10-06 07:38:27 -070026800 operand.IsPostIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026801 if (cond.Is(al)) {
26802 const DRegister& first = nreglist.GetFirstDRegister();
26803 EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
26804 (encoded_align_1.GetEncodingValue() << 4) |
26805 first.Encode(22, 12) | (rn.GetCode() << 16));
26806 return;
26807 }
26808 }
26809 }
26810 }
26811 if (operand.IsPlainRegister()) {
26812 Register rn = operand.GetBaseRegister();
26813 Sign sign = operand.GetSign();
26814 Register rm = operand.GetOffsetRegister();
26815 Dt_size_7 encoded_dt(dt);
26816 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026817 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026818 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
26819 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26820 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26821 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026822 sign.IsPlus() && operand.IsPostIndex() &&
26823 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026824 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26825 const DRegister& first = nreglist.GetFirstDRegister();
26826 EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
26827 (encoded_align_1.GetEncodingValue() << 4) |
26828 first.Encode(22, 12) | (rn.GetCode() << 16) |
26829 rm.GetCode());
26830 AdvanceIT();
26831 return;
26832 }
26833 }
26834 } else {
26835 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
26836 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26837 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26838 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026839 sign.IsPlus() && operand.IsPostIndex() &&
26840 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026841 if (cond.Is(al)) {
26842 const DRegister& first = nreglist.GetFirstDRegister();
26843 EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
26844 (encoded_align_1.GetEncodingValue() << 4) |
26845 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26846 return;
26847 }
26848 }
26849 }
26850 }
26851 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26852}
26853
26854void Assembler::vst4(Condition cond,
26855 DataType dt,
26856 const NeonRegisterList& nreglist,
26857 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026858 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026859 CheckIT(cond);
26860 if (operand.IsImmediateZero()) {
26861 Register rn = operand.GetBaseRegister();
26862 Alignment align = operand.GetAlignment();
26863 Dt_size_7 encoded_dt(dt);
26864 Align_align_4 encoded_align_1(align);
26865 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026866 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026867 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26868 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26869 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26870 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026871 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026872 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026873 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26874 const DRegister& first = nreglist.GetFirstDRegister();
26875 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26876 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26877 (encoded_align_1.GetEncodingValue() << 4) |
26878 first.Encode(22, 12) | (len_encoding << 8) |
26879 (rn.GetCode() << 16));
26880 AdvanceIT();
26881 return;
26882 }
26883 }
26884 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26885 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26886 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26887 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026888 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026889 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026890 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26891 const DRegister& first = nreglist.GetFirstDRegister();
26892 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26893 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26894 (encoded_align_1.GetEncodingValue() << 4) |
26895 first.Encode(22, 12) | (len_encoding << 8) |
26896 (rn.GetCode() << 16));
26897 AdvanceIT();
26898 return;
26899 }
26900 }
26901 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26902 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26903 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26904 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026905 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026906 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026907 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26908 const DRegister& first = nreglist.GetFirstDRegister();
26909 EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
26910 (encoded_align_2.GetEncodingValue() << 4) |
26911 first.Encode(22, 12) | (rn.GetCode() << 16));
26912 AdvanceIT();
26913 return;
26914 }
26915 }
26916 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26917 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26918 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26919 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026920 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026921 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026922 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26923 const DRegister& first = nreglist.GetFirstDRegister();
26924 EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
26925 (encoded_align_2.GetEncodingValue() << 4) |
26926 first.Encode(22, 12) | (rn.GetCode() << 16));
26927 AdvanceIT();
26928 return;
26929 }
26930 }
26931 } else {
26932 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26933 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26934 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26935 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026936 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026937 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026938 if (cond.Is(al)) {
26939 const DRegister& first = nreglist.GetFirstDRegister();
26940 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26941 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26942 (encoded_align_1.GetEncodingValue() << 4) |
26943 first.Encode(22, 12) | (len_encoding << 8) |
26944 (rn.GetCode() << 16));
26945 return;
26946 }
26947 }
26948 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26949 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26950 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26951 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026952 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026953 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026954 if (cond.Is(al)) {
26955 const DRegister& first = nreglist.GetFirstDRegister();
26956 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26957 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26958 (encoded_align_1.GetEncodingValue() << 4) |
26959 first.Encode(22, 12) | (len_encoding << 8) |
26960 (rn.GetCode() << 16));
26961 return;
26962 }
26963 }
26964 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26965 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26966 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26967 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026968 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026969 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026970 if (cond.Is(al)) {
26971 const DRegister& first = nreglist.GetFirstDRegister();
26972 EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
26973 (encoded_align_2.GetEncodingValue() << 4) |
26974 first.Encode(22, 12) | (rn.GetCode() << 16));
26975 return;
26976 }
26977 }
26978 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26979 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26980 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26981 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026982 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026983 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026984 if (cond.Is(al)) {
26985 const DRegister& first = nreglist.GetFirstDRegister();
26986 EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
26987 (encoded_align_2.GetEncodingValue() << 4) |
26988 first.Encode(22, 12) | (rn.GetCode() << 16));
26989 return;
26990 }
26991 }
26992 }
26993 }
26994 if (operand.IsPlainRegister()) {
26995 Register rn = operand.GetBaseRegister();
26996 Alignment align = operand.GetAlignment();
26997 Register rm = operand.GetOffsetRegister();
26998 Dt_size_7 encoded_dt(dt);
26999 Align_align_4 encoded_align_1(align);
27000 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027001 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027002 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
27003 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
27004 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27005 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000027006 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027007 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27008 const DRegister& first = nreglist.GetFirstDRegister();
27009 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
27010 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
27011 (encoded_align_1.GetEncodingValue() << 4) |
27012 first.Encode(22, 12) | (len_encoding << 8) |
27013 (rn.GetCode() << 16) | rm.GetCode());
27014 AdvanceIT();
27015 return;
27016 }
27017 }
27018 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
27019 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
27020 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27021 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000027022 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027023 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27024 const DRegister& first = nreglist.GetFirstDRegister();
27025 EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
27026 (encoded_align_2.GetEncodingValue() << 4) |
27027 first.Encode(22, 12) | (rn.GetCode() << 16) |
27028 rm.GetCode());
27029 AdvanceIT();
27030 return;
27031 }
27032 }
27033 } else {
27034 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
27035 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
27036 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27037 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000027038 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027039 if (cond.Is(al)) {
27040 const DRegister& first = nreglist.GetFirstDRegister();
27041 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
27042 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
27043 (encoded_align_1.GetEncodingValue() << 4) |
27044 first.Encode(22, 12) | (len_encoding << 8) |
27045 (rn.GetCode() << 16) | rm.GetCode());
27046 return;
27047 }
27048 }
27049 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
27050 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
27051 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
27052 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000027053 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027054 if (cond.Is(al)) {
27055 const DRegister& first = nreglist.GetFirstDRegister();
27056 EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
27057 (encoded_align_2.GetEncodingValue() << 4) |
27058 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
27059 return;
27060 }
27061 }
27062 }
27063 }
27064 Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
27065}
27066
27067void Assembler::vstm(Condition cond,
27068 DataType dt,
27069 Register rn,
27070 WriteBack write_back,
27071 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027072 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027073 CheckIT(cond);
27074 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027075 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027076 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027077 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27078 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027079 const DRegister& dreg = dreglist.GetFirstDRegister();
27080 unsigned len = dreglist.GetLength() * 2;
27081 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27082 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27083 (len & 0xff));
27084 AdvanceIT();
27085 return;
27086 }
27087 } else {
27088 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027089 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27090 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27091 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027092 const DRegister& dreg = dreglist.GetFirstDRegister();
27093 unsigned len = dreglist.GetLength() * 2;
27094 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27095 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27096 (len & 0xff));
27097 return;
27098 }
27099 }
27100 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
27101}
27102
27103void Assembler::vstm(Condition cond,
27104 DataType dt,
27105 Register rn,
27106 WriteBack write_back,
27107 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027108 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027109 CheckIT(cond);
27110 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027111 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027112 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027113 if ((!rn.IsPC() || AllowUnpredictable())) {
27114 const SRegister& sreg = sreglist.GetFirstSRegister();
27115 unsigned len = sreglist.GetLength();
27116 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27117 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27118 (len & 0xff));
27119 AdvanceIT();
27120 return;
27121 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010027122 } else {
27123 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027124 if (cond.IsNotNever() &&
27125 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027126 const SRegister& sreg = sreglist.GetFirstSRegister();
27127 unsigned len = sreglist.GetLength();
27128 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27129 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27130 (len & 0xff));
27131 return;
27132 }
27133 }
27134 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
27135}
27136
27137void Assembler::vstmdb(Condition cond,
27138 DataType dt,
27139 Register rn,
27140 WriteBack write_back,
27141 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027142 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027143 CheckIT(cond);
27144 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027145 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027146 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
27147 if (write_back.DoesWriteBack() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027148 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27149 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027150 const DRegister& dreg = dreglist.GetFirstDRegister();
27151 unsigned len = dreglist.GetLength() * 2;
27152 EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
27153 (len & 0xff));
27154 AdvanceIT();
27155 return;
27156 }
27157 } else {
27158 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
27159 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027160 (((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27161 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027162 const DRegister& dreg = dreglist.GetFirstDRegister();
27163 unsigned len = dreglist.GetLength() * 2;
27164 EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27165 dreg.Encode(22, 12) | (len & 0xff));
27166 return;
27167 }
27168 }
27169 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
27170}
27171
27172void Assembler::vstmdb(Condition cond,
27173 DataType dt,
27174 Register rn,
27175 WriteBack write_back,
27176 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027177 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027178 CheckIT(cond);
27179 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027180 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027181 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027182 if (write_back.DoesWriteBack() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027183 const SRegister& sreg = sreglist.GetFirstSRegister();
27184 unsigned len = sreglist.GetLength();
27185 EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
27186 (len & 0xff));
27187 AdvanceIT();
27188 return;
27189 }
27190 } else {
27191 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027192 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
27193 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027194 const SRegister& sreg = sreglist.GetFirstSRegister();
27195 unsigned len = sreglist.GetLength();
27196 EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27197 sreg.Encode(22, 12) | (len & 0xff));
27198 return;
27199 }
27200 }
27201 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
27202}
27203
27204void Assembler::vstmia(Condition cond,
27205 DataType dt,
27206 Register rn,
27207 WriteBack write_back,
27208 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027209 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027210 CheckIT(cond);
27211 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027212 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027213 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027214 if ((((dreglist.GetLength() <= 16) && !rn.IsPC()) ||
27215 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027216 const DRegister& dreg = dreglist.GetFirstDRegister();
27217 unsigned len = dreglist.GetLength() * 2;
27218 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27219 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27220 (len & 0xff));
27221 AdvanceIT();
27222 return;
27223 }
27224 } else {
27225 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027226 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
27227 (!rn.IsPC() || !write_back.DoesWriteBack())) ||
27228 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027229 const DRegister& dreg = dreglist.GetFirstDRegister();
27230 unsigned len = dreglist.GetLength() * 2;
27231 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27232 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27233 (len & 0xff));
27234 return;
27235 }
27236 }
27237 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
27238}
27239
27240void Assembler::vstmia(Condition cond,
27241 DataType dt,
27242 Register rn,
27243 WriteBack write_back,
27244 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027245 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027246 CheckIT(cond);
27247 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027248 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027249 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027250 if ((!rn.IsPC() || AllowUnpredictable())) {
27251 const SRegister& sreg = sreglist.GetFirstSRegister();
27252 unsigned len = sreglist.GetLength();
27253 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27254 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27255 (len & 0xff));
27256 AdvanceIT();
27257 return;
27258 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010027259 } else {
27260 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
Vincent Belliardf9a3bc12017-09-12 08:02:15 -070027261 if (cond.IsNotNever() &&
27262 ((!rn.IsPC() || !write_back.DoesWriteBack()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027263 const SRegister& sreg = sreglist.GetFirstSRegister();
27264 unsigned len = sreglist.GetLength();
27265 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27266 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27267 (len & 0xff));
27268 return;
27269 }
27270 }
27271 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
27272}
27273
27274void Assembler::vstr(Condition cond,
27275 DataType dt,
27276 DRegister rd,
27277 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027278 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027279 CheckIT(cond);
27280 if (operand.IsImmediate()) {
27281 Register rn = operand.GetBaseRegister();
27282 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027283 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027284 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
27285 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliard8ecc7892017-09-08 09:49:29 -070027286 ((offset % 4) == 0) && operand.IsOffset() &&
27287 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027288 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27289 uint32_t offset_ = abs(offset) >> 2;
27290 EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27291 offset_ | (sign << 23));
27292 AdvanceIT();
27293 return;
27294 }
27295 } else {
27296 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
27297 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027298 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027299 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27300 uint32_t offset_ = abs(offset) >> 2;
27301 EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27302 (rn.GetCode() << 16) | offset_ | (sign << 23));
27303 return;
27304 }
27305 }
27306 }
27307 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27308}
27309
27310void Assembler::vstr(Condition cond,
27311 DataType dt,
27312 SRegister rd,
27313 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027314 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027315 CheckIT(cond);
27316 if (operand.IsImmediate()) {
27317 Register rn = operand.GetBaseRegister();
27318 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027320 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
27321 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliard8ecc7892017-09-08 09:49:29 -070027322 ((offset % 4) == 0) && operand.IsOffset() &&
27323 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027324 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27325 uint32_t offset_ = abs(offset) >> 2;
27326 EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27327 offset_ | (sign << 23));
27328 AdvanceIT();
27329 return;
27330 }
27331 } else {
27332 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
27333 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027334 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027335 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27336 uint32_t offset_ = abs(offset) >> 2;
27337 EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27338 (rn.GetCode() << 16) | offset_ | (sign << 23));
27339 return;
27340 }
27341 }
27342 }
27343 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27344}
27345
27346void Assembler::vsub(
27347 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027349 CheckIT(cond);
27350 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027352 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
27353 if (dt.Is(F32)) {
27354 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27355 EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27356 rm.Encode(5, 0));
27357 AdvanceIT();
27358 return;
27359 }
27360 }
27361 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
27362 if (dt.Is(F64)) {
27363 EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27364 rm.Encode(5, 0));
27365 AdvanceIT();
27366 return;
27367 }
27368 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27369 if (encoded_dt.IsValid()) {
27370 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27371 EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
27372 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27373 AdvanceIT();
27374 return;
27375 }
27376 }
27377 } else {
27378 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
27379 if (dt.Is(F32)) {
27380 if (cond.Is(al)) {
27381 EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27382 rm.Encode(5, 0));
27383 return;
27384 }
27385 }
27386 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
27387 if (dt.Is(F64) && cond.IsNotNever()) {
27388 EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27389 rn.Encode(7, 16) | rm.Encode(5, 0));
27390 return;
27391 }
27392 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27393 if (encoded_dt.IsValid()) {
27394 if (cond.Is(al)) {
27395 EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
27396 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27397 return;
27398 }
27399 }
27400 }
27401 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27402}
27403
27404void Assembler::vsub(
27405 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027406 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027407 CheckIT(cond);
27408 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027409 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027410 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
27411 if (dt.Is(F32)) {
27412 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27413 EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27414 rm.Encode(5, 0));
27415 AdvanceIT();
27416 return;
27417 }
27418 }
27419 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27420 if (encoded_dt.IsValid()) {
27421 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27422 EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
27423 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27424 AdvanceIT();
27425 return;
27426 }
27427 }
27428 } else {
27429 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
27430 if (dt.Is(F32)) {
27431 if (cond.Is(al)) {
27432 EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27433 rm.Encode(5, 0));
27434 return;
27435 }
27436 }
27437 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27438 if (encoded_dt.IsValid()) {
27439 if (cond.Is(al)) {
27440 EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
27441 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27442 return;
27443 }
27444 }
27445 }
27446 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27447}
27448
27449void Assembler::vsub(
27450 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027451 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027452 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027453 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027454 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
27455 if (dt.Is(F32)) {
27456 EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27457 rm.Encode(5, 0));
27458 AdvanceIT();
27459 return;
27460 }
27461 } else {
27462 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
27463 if (dt.Is(F32) && cond.IsNotNever()) {
27464 EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27465 rn.Encode(7, 16) | rm.Encode(5, 0));
27466 return;
27467 }
27468 }
27469 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27470}
27471
27472void Assembler::vsubhn(
27473 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027474 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027475 CheckIT(cond);
27476 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027477 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027478 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
27479 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27480 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27481 EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
27482 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27483 AdvanceIT();
27484 return;
27485 }
27486 }
27487 } else {
27488 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
27489 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27490 if (cond.Is(al)) {
27491 EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
27492 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27493 return;
27494 }
27495 }
27496 }
27497 Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
27498}
27499
27500void Assembler::vsubl(
27501 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027502 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027503 CheckIT(cond);
27504 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027505 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027506 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
27507 if (encoded_dt.IsValid()) {
27508 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27509 EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27510 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27511 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27512 AdvanceIT();
27513 return;
27514 }
27515 }
27516 } else {
27517 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
27518 if (encoded_dt.IsValid()) {
27519 if (cond.Is(al)) {
27520 EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27521 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27522 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27523 return;
27524 }
27525 }
27526 }
27527 Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
27528}
27529
27530void Assembler::vsubw(
27531 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027532 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027533 CheckIT(cond);
27534 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027536 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
27537 if (encoded_dt.IsValid()) {
27538 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27539 EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27540 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27541 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27542 AdvanceIT();
27543 return;
27544 }
27545 }
27546 } else {
27547 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
27548 if (encoded_dt.IsValid()) {
27549 if (cond.Is(al)) {
27550 EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27551 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27552 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27553 return;
27554 }
27555 }
27556 }
27557 Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
27558}
27559
27560void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027561 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027562 CheckIT(cond);
27563 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027564 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027565 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
27566 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27567 EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27568 AdvanceIT();
27569 return;
27570 }
27571 } else {
27572 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
27573 if (cond.Is(al)) {
27574 EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27575 return;
27576 }
27577 }
27578 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27579}
27580
27581void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027582 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027583 CheckIT(cond);
27584 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027585 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027586 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
27587 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27588 EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27589 AdvanceIT();
27590 return;
27591 }
27592 } else {
27593 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
27594 if (cond.Is(al)) {
27595 EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27596 return;
27597 }
27598 }
27599 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27600}
27601
27602void Assembler::vtbl(Condition cond,
27603 DataType dt,
27604 DRegister rd,
27605 const NeonRegisterList& nreglist,
27606 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027607 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027608 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027609 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027610 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27611 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27612 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27613 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27614 const DRegister& first = nreglist.GetFirstDRegister();
27615 uint32_t len_encoding = nreglist.GetLength() - 1;
27616 EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27617 (len_encoding << 8) | rm.Encode(5, 0));
27618 AdvanceIT();
27619 return;
27620 }
27621 }
27622 } else {
27623 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27624 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27625 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27626 if (cond.Is(al)) {
27627 const DRegister& first = nreglist.GetFirstDRegister();
27628 uint32_t len_encoding = nreglist.GetLength() - 1;
27629 EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27630 (len_encoding << 8) | rm.Encode(5, 0));
27631 return;
27632 }
27633 }
27634 }
27635 Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
27636}
27637
27638void Assembler::vtbx(Condition cond,
27639 DataType dt,
27640 DRegister rd,
27641 const NeonRegisterList& nreglist,
27642 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027643 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027644 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027645 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027646 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27647 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27648 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27649 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27650 const DRegister& first = nreglist.GetFirstDRegister();
27651 uint32_t len_encoding = nreglist.GetLength() - 1;
27652 EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27653 (len_encoding << 8) | rm.Encode(5, 0));
27654 AdvanceIT();
27655 return;
27656 }
27657 }
27658 } else {
27659 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27660 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27661 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27662 if (cond.Is(al)) {
27663 const DRegister& first = nreglist.GetFirstDRegister();
27664 uint32_t len_encoding = nreglist.GetLength() - 1;
27665 EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27666 (len_encoding << 8) | rm.Encode(5, 0));
27667 return;
27668 }
27669 }
27670 }
27671 Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
27672}
27673
27674void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027675 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027676 CheckIT(cond);
27677 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027678 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027679 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27680 if (encoded_dt.IsValid()) {
27681 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27682 EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
27683 rd.Encode(22, 12) | rm.Encode(5, 0));
27684 AdvanceIT();
27685 return;
27686 }
27687 }
27688 } else {
27689 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27690 if (encoded_dt.IsValid()) {
27691 if (cond.Is(al)) {
27692 EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
27693 rd.Encode(22, 12) | rm.Encode(5, 0));
27694 return;
27695 }
27696 }
27697 }
27698 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27699}
27700
27701void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027702 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027703 CheckIT(cond);
27704 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027705 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027706 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27707 if (encoded_dt.IsValid()) {
27708 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27709 EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
27710 rd.Encode(22, 12) | rm.Encode(5, 0));
27711 AdvanceIT();
27712 return;
27713 }
27714 }
27715 } else {
27716 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27717 if (encoded_dt.IsValid()) {
27718 if (cond.Is(al)) {
27719 EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
27720 rd.Encode(22, 12) | rm.Encode(5, 0));
27721 return;
27722 }
27723 }
27724 }
27725 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27726}
27727
27728void Assembler::vtst(
27729 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027730 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027731 CheckIT(cond);
27732 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027733 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027734 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27735 if (encoded_dt.IsValid()) {
27736 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27737 EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
27738 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27739 AdvanceIT();
27740 return;
27741 }
27742 }
27743 } else {
27744 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27745 if (encoded_dt.IsValid()) {
27746 if (cond.Is(al)) {
27747 EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
27748 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27749 return;
27750 }
27751 }
27752 }
27753 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27754}
27755
27756void Assembler::vtst(
27757 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027758 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027759 CheckIT(cond);
27760 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027761 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027762 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27763 if (encoded_dt.IsValid()) {
27764 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27765 EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
27766 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27767 AdvanceIT();
27768 return;
27769 }
27770 }
27771 } else {
27772 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27773 if (encoded_dt.IsValid()) {
27774 if (cond.Is(al)) {
27775 EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
27776 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27777 return;
27778 }
27779 }
27780 }
27781 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27782}
27783
27784void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027785 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027786 CheckIT(cond);
27787 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027788 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027789 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27790 if (encoded_dt.IsValid()) {
27791 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27792 EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
27793 rd.Encode(22, 12) | rm.Encode(5, 0));
27794 AdvanceIT();
27795 return;
27796 }
27797 }
27798 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27799 if (dt.Is(Untyped32)) {
27800 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27801 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27802 AdvanceIT();
27803 return;
27804 }
27805 }
27806 } else {
27807 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27808 if (encoded_dt.IsValid()) {
27809 if (cond.Is(al)) {
27810 EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
27811 rd.Encode(22, 12) | rm.Encode(5, 0));
27812 return;
27813 }
27814 }
27815 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27816 if (dt.Is(Untyped32)) {
27817 if (cond.Is(al)) {
27818 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27819 return;
27820 }
27821 }
27822 }
27823 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27824}
27825
27826void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027827 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027828 CheckIT(cond);
27829 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027830 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027831 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27832 if (encoded_dt.IsValid()) {
27833 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27834 EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
27835 rd.Encode(22, 12) | rm.Encode(5, 0));
27836 AdvanceIT();
27837 return;
27838 }
27839 }
27840 } else {
27841 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27842 if (encoded_dt.IsValid()) {
27843 if (cond.Is(al)) {
27844 EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
27845 rd.Encode(22, 12) | rm.Encode(5, 0));
27846 return;
27847 }
27848 }
27849 }
27850 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27851}
27852
27853void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027854 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027855 CheckIT(cond);
27856 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027857 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027858 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27859 if (encoded_dt.IsValid()) {
27860 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27861 EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
27862 rd.Encode(22, 12) | rm.Encode(5, 0));
27863 AdvanceIT();
27864 return;
27865 }
27866 }
27867 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27868 if (dt.Is(Untyped32)) {
27869 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27870 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27871 AdvanceIT();
27872 return;
27873 }
27874 }
27875 } else {
27876 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27877 if (encoded_dt.IsValid()) {
27878 if (cond.Is(al)) {
27879 EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
27880 rd.Encode(22, 12) | rm.Encode(5, 0));
27881 return;
27882 }
27883 }
27884 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27885 if (dt.Is(Untyped32)) {
27886 if (cond.Is(al)) {
27887 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27888 return;
27889 }
27890 }
27891 }
27892 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27893}
27894
27895void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027896 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027897 CheckIT(cond);
27898 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027899 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027900 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27901 if (encoded_dt.IsValid()) {
27902 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27903 EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
27904 rd.Encode(22, 12) | rm.Encode(5, 0));
27905 AdvanceIT();
27906 return;
27907 }
27908 }
27909 } else {
27910 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27911 if (encoded_dt.IsValid()) {
27912 if (cond.Is(al)) {
27913 EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
27914 rd.Encode(22, 12) | rm.Encode(5, 0));
27915 return;
27916 }
27917 }
27918 }
27919 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27920}
27921
27922void Assembler::yield(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027923 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027924 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027925 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027926 // YIELD{<c>}{<q>} ; T1
27927 if (!size.IsWide()) {
27928 EmitT32_16(0xbf10);
27929 AdvanceIT();
27930 return;
27931 }
27932 // YIELD{<c>}.W ; T2
27933 if (!size.IsNarrow()) {
27934 EmitT32_32(0xf3af8001U);
27935 AdvanceIT();
27936 return;
27937 }
27938 } else {
27939 // YIELD{<c>}{<q>} ; A1
27940 if (cond.IsNotNever()) {
27941 EmitA32(0x0320f001U | (cond.GetCondition() << 28));
27942 return;
27943 }
27944 }
27945 Delegate(kYield, &Assembler::yield, cond, size);
27946}
27947// End of generated code.
27948
27949} // namespace aarch32
27950} // namespace vixl