blob: 8a858f727beb6ff9f429ef785f4f2152742801a8 [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"
38#include "aarch32/constants-aarch32.h"
39#include "aarch32/instructions-aarch32.h"
Pierre Langlois989663e2016-11-24 13:11:08 +000040#include "aarch32/operands-aarch32.h"
Alexandre Ramesd3832962016-07-04 15:03:43 +010041#include "aarch32/assembler-aarch32.h"
42
43namespace vixl {
44namespace aarch32 {
45
46void Assembler::EmitT32_16(uint16_t instr) {
47 VIXL_ASSERT(buffer_.Is16bitAligned());
48 buffer_.Emit16(instr);
49}
50
51
52void Assembler::EmitT32_32(uint32_t instr) {
53 VIXL_ASSERT(buffer_.Is16bitAligned());
54 buffer_.Emit16(static_cast<uint16_t>(instr >> 16));
55 buffer_.Emit16(static_cast<uint16_t>(instr & 0xffff));
56}
57
58
59void Assembler::EmitA32(uint32_t instr) {
60 VIXL_ASSERT(buffer_.Is32bitAligned());
61 buffer_.Emit32(instr);
62}
63
64
65#ifdef VIXL_DEBUG
66void Assembler::PerformCheckIT(Condition condition) {
67 if (it_mask_ == 0) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010068 VIXL_ASSERT(IsUsingA32() || condition.Is(al));
Alexandre Ramesd3832962016-07-04 15:03:43 +010069 } else {
70 VIXL_ASSERT(condition.Is(first_condition_));
71 first_condition_ =
72 Condition((first_condition_.GetCondition() & 0xe) | (it_mask_ >> 3));
73 // For A32, AdavanceIT() is not called by the assembler. We must call it
74 // in order to check that IT instructions are used consistently with
75 // the following conditional instructions.
Jacob Bramley10dae1a2016-07-27 09:45:13 +010076 if (IsUsingA32()) AdvanceIT();
Alexandre Ramesd3832962016-07-04 15:03:43 +010077 }
78}
79#endif
80
81
Vincent Belliarde42218c2016-10-19 13:24:28 -070082void Assembler::BindHelper(Label* label) {
Georgia Kouveli8b57c862017-03-02 15:18:58 +000083 VIXL_ASSERT(!label->IsBound());
84 label->SetLocation(this, GetCursorOffset());
85 label->MarkBound();
Vincent Belliarde42218c2016-10-19 13:24:28 -070086}
87
Georgia Kouveli275c9d42017-05-12 18:07:45 +010088uint32_t Assembler::Link(uint32_t instr,
89 Location* location,
90 const Location::EmitOperator& op,
Georgia Kouveli8b57c862017-03-02 15:18:58 +000091 const ReferenceInfo* info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010092 location->SetReferenced();
93 if (location->IsBound()) {
94 return op.Encode(instr, GetCursorOffset(), location);
95 }
Georgia Kouveli8b57c862017-03-02 15:18:58 +000096 location->AddForwardRef(GetCursorOffset(), op, info);
Alexandre Ramesd3832962016-07-04 15:03:43 +010097 return instr;
98}
99
100
Alexandre Ramesd3832962016-07-04 15:03:43 +0100101// Start of generated code.
102class Dt_L_imm6_1 : public EncodingValue {
103 uint32_t type_;
104
105 public:
106 explicit Dt_L_imm6_1(DataType dt);
107 uint32_t GetTypeEncodingValue() const { return type_; }
108};
109
110Dt_L_imm6_1::Dt_L_imm6_1(DataType dt) {
111 switch (dt.GetValue()) {
112 case S8:
113 type_ = 0x0;
114 SetEncodingValue(0x1);
115 break;
116 case U8:
117 type_ = 0x1;
118 SetEncodingValue(0x1);
119 break;
120 case S16:
121 type_ = 0x0;
122 SetEncodingValue(0x2);
123 break;
124 case U16:
125 type_ = 0x1;
126 SetEncodingValue(0x2);
127 break;
128 case S32:
129 type_ = 0x0;
130 SetEncodingValue(0x4);
131 break;
132 case U32:
133 type_ = 0x1;
134 SetEncodingValue(0x4);
135 break;
136 case S64:
137 type_ = 0x0;
138 SetEncodingValue(0x8);
139 break;
140 case U64:
141 type_ = 0x1;
142 SetEncodingValue(0x8);
143 break;
144 default:
145 VIXL_UNREACHABLE();
146 type_ = 0x0;
147 break;
148 }
149}
150
151class Dt_L_imm6_2 : public EncodingValue {
152 uint32_t type_;
153
154 public:
155 explicit Dt_L_imm6_2(DataType dt);
156 uint32_t GetTypeEncodingValue() const { return type_; }
157};
158
159Dt_L_imm6_2::Dt_L_imm6_2(DataType dt) {
160 switch (dt.GetValue()) {
161 case S8:
162 type_ = 0x1;
163 SetEncodingValue(0x1);
164 break;
165 case S16:
166 type_ = 0x1;
167 SetEncodingValue(0x2);
168 break;
169 case S32:
170 type_ = 0x1;
171 SetEncodingValue(0x4);
172 break;
173 case S64:
174 type_ = 0x1;
175 SetEncodingValue(0x8);
176 break;
177 default:
178 VIXL_UNREACHABLE();
179 type_ = 0x0;
180 break;
181 }
182}
183
184class Dt_L_imm6_3 : public EncodingValue {
185 public:
186 explicit Dt_L_imm6_3(DataType dt);
187};
188
189Dt_L_imm6_3::Dt_L_imm6_3(DataType dt) {
190 switch (dt.GetValue()) {
191 case I8:
192 SetEncodingValue(0x1);
193 break;
194 case I16:
195 SetEncodingValue(0x2);
196 break;
197 case I32:
198 SetEncodingValue(0x4);
199 break;
200 case I64:
201 SetEncodingValue(0x8);
202 break;
203 default:
204 break;
205 }
206}
207
208class Dt_L_imm6_4 : public EncodingValue {
209 public:
210 explicit Dt_L_imm6_4(DataType dt);
211};
212
213Dt_L_imm6_4::Dt_L_imm6_4(DataType dt) {
214 switch (dt.GetValue()) {
215 case Untyped8:
216 SetEncodingValue(0x1);
217 break;
218 case Untyped16:
219 SetEncodingValue(0x2);
220 break;
221 case Untyped32:
222 SetEncodingValue(0x4);
223 break;
224 case Untyped64:
225 SetEncodingValue(0x8);
226 break;
227 default:
228 break;
229 }
230}
231
232class Dt_imm6_1 : public EncodingValue {
233 uint32_t type_;
234
235 public:
236 explicit Dt_imm6_1(DataType dt);
237 uint32_t GetTypeEncodingValue() const { return type_; }
238};
239
240Dt_imm6_1::Dt_imm6_1(DataType dt) {
241 switch (dt.GetValue()) {
242 case S16:
243 type_ = 0x0;
244 SetEncodingValue(0x1);
245 break;
246 case U16:
247 type_ = 0x1;
248 SetEncodingValue(0x1);
249 break;
250 case S32:
251 type_ = 0x0;
252 SetEncodingValue(0x2);
253 break;
254 case U32:
255 type_ = 0x1;
256 SetEncodingValue(0x2);
257 break;
258 case S64:
259 type_ = 0x0;
260 SetEncodingValue(0x4);
261 break;
262 case U64:
263 type_ = 0x1;
264 SetEncodingValue(0x4);
265 break;
266 default:
267 VIXL_UNREACHABLE();
268 type_ = 0x0;
269 break;
270 }
271}
272
273class Dt_imm6_2 : public EncodingValue {
274 uint32_t type_;
275
276 public:
277 explicit Dt_imm6_2(DataType dt);
278 uint32_t GetTypeEncodingValue() const { return type_; }
279};
280
281Dt_imm6_2::Dt_imm6_2(DataType dt) {
282 switch (dt.GetValue()) {
283 case S16:
284 type_ = 0x1;
285 SetEncodingValue(0x1);
286 break;
287 case S32:
288 type_ = 0x1;
289 SetEncodingValue(0x2);
290 break;
291 case S64:
292 type_ = 0x1;
293 SetEncodingValue(0x4);
294 break;
295 default:
296 VIXL_UNREACHABLE();
297 type_ = 0x0;
298 break;
299 }
300}
301
302class Dt_imm6_3 : public EncodingValue {
303 public:
304 explicit Dt_imm6_3(DataType dt);
305};
306
307Dt_imm6_3::Dt_imm6_3(DataType dt) {
308 switch (dt.GetValue()) {
309 case I16:
310 SetEncodingValue(0x1);
311 break;
312 case I32:
313 SetEncodingValue(0x2);
314 break;
315 case I64:
316 SetEncodingValue(0x4);
317 break;
318 default:
319 break;
320 }
321}
322
323class Dt_imm6_4 : public EncodingValue {
324 uint32_t type_;
325
326 public:
327 explicit Dt_imm6_4(DataType dt);
328 uint32_t GetTypeEncodingValue() const { return type_; }
329};
330
331Dt_imm6_4::Dt_imm6_4(DataType dt) {
332 switch (dt.GetValue()) {
333 case S8:
334 type_ = 0x0;
335 SetEncodingValue(0x1);
336 break;
337 case U8:
338 type_ = 0x1;
339 SetEncodingValue(0x1);
340 break;
341 case S16:
342 type_ = 0x0;
343 SetEncodingValue(0x2);
344 break;
345 case U16:
346 type_ = 0x1;
347 SetEncodingValue(0x2);
348 break;
349 case S32:
350 type_ = 0x0;
351 SetEncodingValue(0x4);
352 break;
353 case U32:
354 type_ = 0x1;
355 SetEncodingValue(0x4);
356 break;
357 default:
358 VIXL_UNREACHABLE();
359 type_ = 0x0;
360 break;
361 }
362}
363
364class Dt_op_U_size_1 : public EncodingValue {
365 public:
366 explicit Dt_op_U_size_1(DataType dt);
367};
368
369Dt_op_U_size_1::Dt_op_U_size_1(DataType dt) {
370 switch (dt.GetValue()) {
371 case S8:
372 SetEncodingValue(0x0);
373 break;
374 case S16:
375 SetEncodingValue(0x1);
376 break;
377 case S32:
378 SetEncodingValue(0x2);
379 break;
380 case U8:
381 SetEncodingValue(0x4);
382 break;
383 case U16:
384 SetEncodingValue(0x5);
385 break;
386 case U32:
387 SetEncodingValue(0x6);
388 break;
389 case P8:
390 SetEncodingValue(0x8);
391 break;
392 case P64:
393 SetEncodingValue(0xa);
394 break;
395 default:
396 break;
397 }
398}
399
400class Dt_op_size_1 : public EncodingValue {
401 public:
402 explicit Dt_op_size_1(DataType dt);
403};
404
405Dt_op_size_1::Dt_op_size_1(DataType dt) {
406 switch (dt.GetValue()) {
407 case I8:
408 SetEncodingValue(0x0);
409 break;
410 case I16:
411 SetEncodingValue(0x1);
412 break;
413 case I32:
414 SetEncodingValue(0x2);
415 break;
416 case P8:
417 SetEncodingValue(0x4);
418 break;
419 default:
420 break;
421 }
422}
423
424class Dt_op_size_2 : public EncodingValue {
425 public:
426 explicit Dt_op_size_2(DataType dt);
427};
428
429Dt_op_size_2::Dt_op_size_2(DataType dt) {
430 switch (dt.GetValue()) {
431 case S8:
432 SetEncodingValue(0x0);
433 break;
434 case S16:
435 SetEncodingValue(0x1);
436 break;
437 case S32:
438 SetEncodingValue(0x2);
439 break;
440 case U8:
441 SetEncodingValue(0x4);
442 break;
443 case U16:
444 SetEncodingValue(0x5);
445 break;
446 case U32:
447 SetEncodingValue(0x6);
448 break;
449 default:
450 break;
451 }
452}
453
454class Dt_op_size_3 : public EncodingValue {
455 public:
456 explicit Dt_op_size_3(DataType dt);
457};
458
459Dt_op_size_3::Dt_op_size_3(DataType dt) {
460 switch (dt.GetValue()) {
461 case S16:
462 SetEncodingValue(0x0);
463 break;
464 case S32:
465 SetEncodingValue(0x1);
466 break;
467 case S64:
468 SetEncodingValue(0x2);
469 break;
470 case U16:
471 SetEncodingValue(0x4);
472 break;
473 case U32:
474 SetEncodingValue(0x5);
475 break;
476 case U64:
477 SetEncodingValue(0x6);
478 break;
479 default:
480 break;
481 }
482}
483
484class Dt_U_imm3H_1 : public EncodingValue {
485 public:
486 explicit Dt_U_imm3H_1(DataType dt);
487};
488
489Dt_U_imm3H_1::Dt_U_imm3H_1(DataType dt) {
490 switch (dt.GetValue()) {
491 case S8:
492 SetEncodingValue(0x1);
493 break;
494 case S16:
495 SetEncodingValue(0x2);
496 break;
497 case S32:
498 SetEncodingValue(0x4);
499 break;
500 case U8:
501 SetEncodingValue(0x9);
502 break;
503 case U16:
504 SetEncodingValue(0xa);
505 break;
506 case U32:
507 SetEncodingValue(0xc);
508 break;
509 default:
510 break;
511 }
512}
513
514class Dt_U_opc1_opc2_1 : public EncodingValue {
515 public:
516 explicit Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
517};
518
519Dt_U_opc1_opc2_1::Dt_U_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
520 switch (dt.GetValue()) {
521 case S8:
522 if ((lane.GetLane() & 7) != lane.GetLane()) {
523 return;
524 }
525 SetEncodingValue(0x8 | lane.GetLane());
526 break;
527 case S16:
528 if ((lane.GetLane() & 3) != lane.GetLane()) {
529 return;
530 }
531 SetEncodingValue(0x1 | (lane.GetLane() << 1));
532 break;
533 case U8:
534 if ((lane.GetLane() & 7) != lane.GetLane()) {
535 return;
536 }
537 SetEncodingValue(0x18 | lane.GetLane());
538 break;
539 case U16:
540 if ((lane.GetLane() & 3) != lane.GetLane()) {
541 return;
542 }
543 SetEncodingValue(0x11 | (lane.GetLane() << 1));
544 break;
545 case Untyped32:
546 if ((lane.GetLane() & 1) != lane.GetLane()) {
547 return;
548 }
549 SetEncodingValue(0x0 | (lane.GetLane() << 2));
550 break;
551 case kDataTypeValueNone:
552 if ((lane.GetLane() & 1) != lane.GetLane()) {
553 return;
554 }
555 SetEncodingValue(0x0 | (lane.GetLane() << 2));
556 break;
557 default:
558 break;
559 }
560}
561
562class Dt_opc1_opc2_1 : public EncodingValue {
563 public:
564 explicit Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane);
565};
566
567Dt_opc1_opc2_1::Dt_opc1_opc2_1(DataType dt, const DRegisterLane& lane) {
568 switch (dt.GetValue()) {
569 case Untyped8:
570 if ((lane.GetLane() & 7) != lane.GetLane()) {
571 return;
572 }
573 SetEncodingValue(0x8 | lane.GetLane());
574 break;
575 case Untyped16:
576 if ((lane.GetLane() & 3) != lane.GetLane()) {
577 return;
578 }
579 SetEncodingValue(0x1 | (lane.GetLane() << 1));
580 break;
581 case Untyped32:
582 if ((lane.GetLane() & 1) != lane.GetLane()) {
583 return;
584 }
585 SetEncodingValue(0x0 | (lane.GetLane() << 2));
586 break;
587 case kDataTypeValueNone:
588 if ((lane.GetLane() & 1) != lane.GetLane()) {
589 return;
590 }
591 SetEncodingValue(0x0 | (lane.GetLane() << 2));
592 break;
593 default:
594 break;
595 }
596}
597
598class Dt_imm4_1 : public EncodingValue {
599 public:
600 explicit Dt_imm4_1(DataType dt, const DRegisterLane& lane);
601};
602
603Dt_imm4_1::Dt_imm4_1(DataType dt, const DRegisterLane& lane) {
604 switch (dt.GetValue()) {
605 case Untyped8:
606 if ((lane.GetLane() & 7) != lane.GetLane()) {
607 return;
608 }
609 SetEncodingValue(0x1 | (lane.GetLane() << 1));
610 break;
611 case Untyped16:
612 if ((lane.GetLane() & 3) != lane.GetLane()) {
613 return;
614 }
615 SetEncodingValue(0x2 | (lane.GetLane() << 2));
616 break;
617 case Untyped32:
618 if ((lane.GetLane() & 1) != lane.GetLane()) {
619 return;
620 }
621 SetEncodingValue(0x4 | (lane.GetLane() << 3));
622 break;
623 default:
624 break;
625 }
626}
627
628class Dt_B_E_1 : public EncodingValue {
629 public:
630 explicit Dt_B_E_1(DataType dt);
631};
632
633Dt_B_E_1::Dt_B_E_1(DataType dt) {
634 switch (dt.GetValue()) {
635 case Untyped8:
636 SetEncodingValue(0x2);
637 break;
638 case Untyped16:
639 SetEncodingValue(0x1);
640 break;
641 case Untyped32:
642 SetEncodingValue(0x0);
643 break;
644 default:
645 break;
646 }
647}
648
649class Dt_op_1 : public EncodingValue {
650 public:
651 Dt_op_1(DataType dt1, DataType dt2);
652};
653
654Dt_op_1::Dt_op_1(DataType dt1, DataType dt2) {
655 if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
656 SetEncodingValue(0x0);
657 return;
658 }
659 if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
660 SetEncodingValue(0x1);
661 return;
662 }
663 if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
664 SetEncodingValue(0x2);
665 return;
666 }
667 if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
668 SetEncodingValue(0x3);
669 return;
670 }
671}
672
673class Dt_op_2 : public EncodingValue {
674 public:
675 explicit Dt_op_2(DataType dt);
676};
677
678Dt_op_2::Dt_op_2(DataType dt) {
679 switch (dt.GetValue()) {
680 case U32:
681 SetEncodingValue(0x0);
682 break;
683 case S32:
684 SetEncodingValue(0x1);
685 break;
686 default:
687 break;
688 }
689}
690
691class Dt_op_3 : public EncodingValue {
692 public:
693 explicit Dt_op_3(DataType dt);
694};
695
696Dt_op_3::Dt_op_3(DataType dt) {
697 switch (dt.GetValue()) {
698 case S32:
699 SetEncodingValue(0x0);
700 break;
701 case U32:
702 SetEncodingValue(0x1);
703 break;
704 default:
705 break;
706 }
707}
708
709class Dt_U_sx_1 : public EncodingValue {
710 public:
711 explicit Dt_U_sx_1(DataType dt);
712};
713
714Dt_U_sx_1::Dt_U_sx_1(DataType dt) {
715 switch (dt.GetValue()) {
716 case S16:
717 SetEncodingValue(0x0);
718 break;
719 case S32:
720 SetEncodingValue(0x1);
721 break;
722 case U16:
723 SetEncodingValue(0x2);
724 break;
725 case U32:
726 SetEncodingValue(0x3);
727 break;
728 default:
729 break;
730 }
731}
732
733class Dt_op_U_1 : public EncodingValue {
734 public:
735 Dt_op_U_1(DataType dt1, DataType dt2);
736};
737
738Dt_op_U_1::Dt_op_U_1(DataType dt1, DataType dt2) {
739 if ((dt1.GetValue() == F32) && (dt2.GetValue() == S32)) {
740 SetEncodingValue(0x0);
741 return;
742 }
743 if ((dt1.GetValue() == F32) && (dt2.GetValue() == U32)) {
744 SetEncodingValue(0x1);
745 return;
746 }
747 if ((dt1.GetValue() == S32) && (dt2.GetValue() == F32)) {
748 SetEncodingValue(0x2);
749 return;
750 }
751 if ((dt1.GetValue() == U32) && (dt2.GetValue() == F32)) {
752 SetEncodingValue(0x3);
753 return;
754 }
755}
756
757class Dt_sz_1 : public EncodingValue {
758 public:
759 explicit Dt_sz_1(DataType dt);
760};
761
762Dt_sz_1::Dt_sz_1(DataType dt) {
763 switch (dt.GetValue()) {
764 case F32:
765 SetEncodingValue(0x0);
766 break;
767 default:
768 break;
769 }
770}
771
772class Dt_F_size_1 : public EncodingValue {
773 public:
774 explicit Dt_F_size_1(DataType dt);
775};
776
777Dt_F_size_1::Dt_F_size_1(DataType dt) {
778 switch (dt.GetValue()) {
779 case S8:
780 SetEncodingValue(0x0);
781 break;
782 case S16:
783 SetEncodingValue(0x1);
784 break;
785 case S32:
786 SetEncodingValue(0x2);
787 break;
788 case F32:
789 SetEncodingValue(0x6);
790 break;
791 default:
792 break;
793 }
794}
795
796class Dt_F_size_2 : public EncodingValue {
797 public:
798 explicit Dt_F_size_2(DataType dt);
799};
800
801Dt_F_size_2::Dt_F_size_2(DataType dt) {
802 switch (dt.GetValue()) {
803 case I8:
804 SetEncodingValue(0x0);
805 break;
806 case I16:
807 SetEncodingValue(0x1);
808 break;
809 case I32:
810 SetEncodingValue(0x2);
811 break;
812 case F32:
813 SetEncodingValue(0x6);
814 break;
815 default:
816 break;
817 }
818}
819
820class Dt_F_size_3 : public EncodingValue {
821 public:
822 explicit Dt_F_size_3(DataType dt);
823};
824
825Dt_F_size_3::Dt_F_size_3(DataType dt) {
826 switch (dt.GetValue()) {
827 case I16:
828 SetEncodingValue(0x1);
829 break;
830 case I32:
831 SetEncodingValue(0x2);
832 break;
833 case F32:
834 SetEncodingValue(0x6);
835 break;
836 default:
837 break;
838 }
839}
840
841class Dt_F_size_4 : public EncodingValue {
842 public:
843 explicit Dt_F_size_4(DataType dt);
844};
845
846Dt_F_size_4::Dt_F_size_4(DataType dt) {
847 switch (dt.GetValue()) {
848 case U32:
849 SetEncodingValue(0x2);
850 break;
851 case F32:
852 SetEncodingValue(0x6);
853 break;
854 default:
855 break;
856 }
857}
858
859class Dt_U_size_1 : public EncodingValue {
860 public:
861 explicit Dt_U_size_1(DataType dt);
862};
863
864Dt_U_size_1::Dt_U_size_1(DataType dt) {
865 switch (dt.GetValue()) {
866 case S8:
867 SetEncodingValue(0x0);
868 break;
869 case S16:
870 SetEncodingValue(0x1);
871 break;
872 case S32:
873 SetEncodingValue(0x2);
874 break;
875 case U8:
876 SetEncodingValue(0x4);
877 break;
878 case U16:
879 SetEncodingValue(0x5);
880 break;
881 case U32:
882 SetEncodingValue(0x6);
883 break;
884 default:
885 break;
886 }
887}
888
889class Dt_U_size_2 : public EncodingValue {
890 public:
891 explicit Dt_U_size_2(DataType dt);
892};
893
894Dt_U_size_2::Dt_U_size_2(DataType dt) {
895 switch (dt.GetValue()) {
896 case S16:
897 SetEncodingValue(0x1);
898 break;
899 case S32:
900 SetEncodingValue(0x2);
901 break;
902 case U16:
903 SetEncodingValue(0x5);
904 break;
905 case U32:
906 SetEncodingValue(0x6);
907 break;
908 default:
909 break;
910 }
911}
912
913class Dt_U_size_3 : public EncodingValue {
914 public:
915 explicit Dt_U_size_3(DataType dt);
916};
917
918Dt_U_size_3::Dt_U_size_3(DataType dt) {
919 switch (dt.GetValue()) {
920 case S8:
921 SetEncodingValue(0x0);
922 break;
923 case S16:
924 SetEncodingValue(0x1);
925 break;
926 case S32:
927 SetEncodingValue(0x2);
928 break;
929 case S64:
930 SetEncodingValue(0x3);
931 break;
932 case U8:
933 SetEncodingValue(0x4);
934 break;
935 case U16:
936 SetEncodingValue(0x5);
937 break;
938 case U32:
939 SetEncodingValue(0x6);
940 break;
941 case U64:
942 SetEncodingValue(0x7);
943 break;
944 default:
945 break;
946 }
947}
948
949class Dt_size_1 : public EncodingValue {
950 public:
951 explicit Dt_size_1(DataType dt);
952};
953
954Dt_size_1::Dt_size_1(DataType dt) {
955 switch (dt.GetValue()) {
956 case Untyped8:
957 SetEncodingValue(0x0);
958 break;
959 default:
960 break;
961 }
962}
963
964class Dt_size_2 : public EncodingValue {
965 public:
966 explicit Dt_size_2(DataType dt);
967};
968
969Dt_size_2::Dt_size_2(DataType dt) {
970 switch (dt.GetValue()) {
971 case I8:
972 SetEncodingValue(0x0);
973 break;
974 case I16:
975 SetEncodingValue(0x1);
976 break;
977 case I32:
978 SetEncodingValue(0x2);
979 break;
980 case I64:
981 SetEncodingValue(0x3);
982 break;
983 default:
984 break;
985 }
986}
987
988class Dt_size_3 : public EncodingValue {
989 public:
990 explicit Dt_size_3(DataType dt);
991};
992
993Dt_size_3::Dt_size_3(DataType dt) {
994 switch (dt.GetValue()) {
995 case I16:
996 SetEncodingValue(0x0);
997 break;
998 case I32:
999 SetEncodingValue(0x1);
1000 break;
1001 case I64:
1002 SetEncodingValue(0x2);
1003 break;
1004 default:
1005 break;
1006 }
1007}
1008
1009class Dt_size_4 : public EncodingValue {
1010 public:
1011 explicit Dt_size_4(DataType dt);
1012};
1013
1014Dt_size_4::Dt_size_4(DataType dt) {
1015 switch (dt.GetValue()) {
1016 case I8:
1017 SetEncodingValue(0x0);
1018 break;
1019 case I16:
1020 SetEncodingValue(0x1);
1021 break;
1022 case I32:
1023 SetEncodingValue(0x2);
1024 break;
1025 default:
1026 break;
1027 }
1028}
1029
1030class Dt_size_5 : public EncodingValue {
1031 public:
1032 explicit Dt_size_5(DataType dt);
1033};
1034
1035Dt_size_5::Dt_size_5(DataType dt) {
1036 switch (dt.GetValue()) {
1037 case S8:
1038 SetEncodingValue(0x0);
1039 break;
1040 case S16:
1041 SetEncodingValue(0x1);
1042 break;
1043 case S32:
1044 SetEncodingValue(0x2);
1045 break;
1046 default:
1047 break;
1048 }
1049}
1050
1051class Dt_size_6 : public EncodingValue {
1052 public:
1053 explicit Dt_size_6(DataType dt);
1054};
1055
1056Dt_size_6::Dt_size_6(DataType dt) {
1057 switch (dt.GetValue()) {
1058 case Untyped8:
1059 SetEncodingValue(0x0);
1060 break;
1061 case Untyped16:
1062 SetEncodingValue(0x1);
1063 break;
1064 case Untyped32:
1065 SetEncodingValue(0x2);
1066 break;
1067 case Untyped64:
1068 SetEncodingValue(0x3);
1069 break;
1070 default:
1071 break;
1072 }
1073}
1074
1075class Dt_size_7 : public EncodingValue {
1076 public:
1077 explicit Dt_size_7(DataType dt);
1078};
1079
1080Dt_size_7::Dt_size_7(DataType dt) {
1081 switch (dt.GetValue()) {
1082 case Untyped8:
1083 SetEncodingValue(0x0);
1084 break;
1085 case Untyped16:
1086 SetEncodingValue(0x1);
1087 break;
1088 case Untyped32:
1089 SetEncodingValue(0x2);
1090 break;
1091 default:
1092 break;
1093 }
1094}
1095
1096class Dt_size_8 : public EncodingValue {
1097 public:
1098 Dt_size_8(DataType dt, Alignment align);
1099};
1100
1101Dt_size_8::Dt_size_8(DataType dt, Alignment align) {
1102 switch (dt.GetValue()) {
1103 case Untyped8:
1104 SetEncodingValue(0x0);
1105 break;
1106 case Untyped16:
1107 SetEncodingValue(0x1);
1108 break;
1109 case Untyped32:
1110 if (align.Is(k64BitAlign) || align.Is(kNoAlignment)) {
1111 SetEncodingValue(0x2);
1112 } else if (align.Is(k128BitAlign)) {
1113 SetEncodingValue(0x3);
1114 }
1115 break;
1116 default:
1117 break;
1118 }
1119}
1120
1121class Dt_size_9 : public EncodingValue {
1122 uint32_t type_;
1123
1124 public:
1125 explicit Dt_size_9(DataType dt);
1126 uint32_t GetTypeEncodingValue() const { return type_; }
1127};
1128
1129Dt_size_9::Dt_size_9(DataType dt) {
1130 switch (dt.GetValue()) {
1131 case I16:
1132 type_ = 0x0;
1133 SetEncodingValue(0x1);
1134 break;
1135 case I32:
1136 type_ = 0x0;
1137 SetEncodingValue(0x2);
1138 break;
1139 case F32:
1140 type_ = 0x1;
1141 SetEncodingValue(0x2);
1142 break;
1143 default:
1144 VIXL_UNREACHABLE();
1145 type_ = 0x0;
1146 break;
1147 }
1148}
1149
1150class Dt_size_10 : public EncodingValue {
1151 public:
1152 explicit Dt_size_10(DataType dt);
1153};
1154
1155Dt_size_10::Dt_size_10(DataType dt) {
1156 switch (dt.GetValue()) {
1157 case S8:
1158 case U8:
1159 case I8:
1160 SetEncodingValue(0x0);
1161 break;
1162 case S16:
1163 case U16:
1164 case I16:
1165 SetEncodingValue(0x1);
1166 break;
1167 case S32:
1168 case U32:
1169 case I32:
1170 SetEncodingValue(0x2);
1171 break;
1172 default:
1173 break;
1174 }
1175}
1176
1177class Dt_size_11 : public EncodingValue {
1178 uint32_t type_;
1179
1180 public:
1181 explicit Dt_size_11(DataType dt);
1182 uint32_t GetTypeEncodingValue() const { return type_; }
1183};
1184
1185Dt_size_11::Dt_size_11(DataType dt) {
1186 switch (dt.GetValue()) {
1187 case S16:
1188 type_ = 0x0;
1189 SetEncodingValue(0x1);
1190 break;
1191 case U16:
1192 type_ = 0x1;
1193 SetEncodingValue(0x1);
1194 break;
1195 case S32:
1196 type_ = 0x0;
1197 SetEncodingValue(0x2);
1198 break;
1199 case U32:
1200 type_ = 0x1;
1201 SetEncodingValue(0x2);
1202 break;
1203 default:
1204 VIXL_UNREACHABLE();
1205 type_ = 0x0;
1206 break;
1207 }
1208}
1209
1210class Dt_size_12 : public EncodingValue {
1211 uint32_t type_;
1212
1213 public:
1214 explicit Dt_size_12(DataType dt);
1215 uint32_t GetTypeEncodingValue() const { return type_; }
1216};
1217
1218Dt_size_12::Dt_size_12(DataType dt) {
1219 switch (dt.GetValue()) {
1220 case S8:
1221 type_ = 0x0;
1222 SetEncodingValue(0x0);
1223 break;
1224 case U8:
1225 type_ = 0x1;
1226 SetEncodingValue(0x0);
1227 break;
1228 case S16:
1229 type_ = 0x0;
1230 SetEncodingValue(0x1);
1231 break;
1232 case U16:
1233 type_ = 0x1;
1234 SetEncodingValue(0x1);
1235 break;
1236 case S32:
1237 type_ = 0x0;
1238 SetEncodingValue(0x2);
1239 break;
1240 case U32:
1241 type_ = 0x1;
1242 SetEncodingValue(0x2);
1243 break;
1244 default:
1245 VIXL_UNREACHABLE();
1246 type_ = 0x0;
1247 break;
1248 }
1249}
1250
1251class Dt_size_13 : public EncodingValue {
1252 public:
1253 explicit Dt_size_13(DataType dt);
1254};
1255
1256Dt_size_13::Dt_size_13(DataType dt) {
1257 switch (dt.GetValue()) {
1258 case S16:
1259 SetEncodingValue(0x1);
1260 break;
1261 case S32:
1262 SetEncodingValue(0x2);
1263 break;
1264 default:
1265 break;
1266 }
1267}
1268
1269class Dt_size_14 : public EncodingValue {
1270 public:
1271 explicit Dt_size_14(DataType dt);
1272};
1273
1274Dt_size_14::Dt_size_14(DataType dt) {
1275 switch (dt.GetValue()) {
1276 case S16:
1277 SetEncodingValue(0x0);
1278 break;
1279 case S32:
1280 SetEncodingValue(0x1);
1281 break;
1282 case S64:
1283 SetEncodingValue(0x2);
1284 break;
1285 default:
1286 break;
1287 }
1288}
1289
1290class Dt_size_15 : public EncodingValue {
1291 public:
1292 explicit Dt_size_15(DataType dt);
1293};
1294
1295Dt_size_15::Dt_size_15(DataType dt) {
1296 switch (dt.GetValue()) {
1297 case Untyped8:
1298 SetEncodingValue(0x0);
1299 break;
1300 case Untyped16:
1301 SetEncodingValue(0x1);
1302 break;
1303 default:
1304 break;
1305 }
1306}
1307
1308class Dt_size_16 : public EncodingValue {
1309 public:
1310 explicit Dt_size_16(DataType dt);
1311};
1312
1313Dt_size_16::Dt_size_16(DataType dt) {
1314 switch (dt.GetValue()) {
1315 case I8:
1316 SetEncodingValue(0x0);
1317 break;
1318 case I16:
1319 SetEncodingValue(0x1);
1320 break;
1321 case I32:
1322 SetEncodingValue(0x2);
1323 break;
1324 default:
1325 break;
1326 }
1327}
1328
1329class Index_1 : public EncodingValue {
1330 public:
1331 Index_1(const NeonRegisterList& nreglist, DataType dt);
1332};
1333
1334Index_1::Index_1(const NeonRegisterList& nreglist, DataType dt) {
1335 switch (dt.GetValue()) {
1336 case Untyped8: {
1337 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1338 return;
1339 }
1340 uint32_t value = nreglist.GetTransferLane() << 1;
1341 if (!nreglist.IsSingleSpaced()) return;
1342 SetEncodingValue(value);
1343 break;
1344 }
1345 case Untyped16: {
1346 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1347 return;
1348 }
1349 uint32_t value = nreglist.GetTransferLane() << 2;
1350 if (nreglist.IsDoubleSpaced()) value |= 2;
1351 SetEncodingValue(value);
1352 break;
1353 }
1354 case Untyped32: {
1355 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1356 return;
1357 }
1358 uint32_t value = nreglist.GetTransferLane() << 3;
1359 if (nreglist.IsDoubleSpaced()) value |= 4;
1360 SetEncodingValue(value);
1361 break;
1362 }
1363 default:
1364 break;
1365 }
1366}
1367
1368class Align_index_align_1 : public EncodingValue {
1369 public:
1370 Align_index_align_1(Alignment align,
1371 const NeonRegisterList& nreglist,
1372 DataType dt);
1373};
1374
1375Align_index_align_1::Align_index_align_1(Alignment align,
1376 const NeonRegisterList& nreglist,
1377 DataType dt) {
1378 switch (dt.GetValue()) {
1379 case Untyped8: {
1380 uint32_t value;
1381 if (align.GetType() == kNoAlignment) {
1382 value = 0;
1383 } else {
1384 return;
1385 }
1386 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1387 return;
1388 }
1389 value |= nreglist.GetTransferLane() << 1;
1390 SetEncodingValue(value);
1391 break;
1392 }
1393 case Untyped16: {
1394 uint32_t value;
1395 if (align.GetType() == k16BitAlign) {
1396 value = 1;
1397 } else if (align.GetType() == kNoAlignment) {
1398 value = 0;
1399 } else {
1400 return;
1401 }
1402 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1403 return;
1404 }
1405 value |= nreglist.GetTransferLane() << 2;
1406 SetEncodingValue(value);
1407 break;
1408 }
1409 case Untyped32: {
1410 uint32_t value;
1411 if (align.GetType() == k32BitAlign) {
1412 value = 3;
1413 } else if (align.GetType() == kNoAlignment) {
1414 value = 0;
1415 } else {
1416 return;
1417 }
1418 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1419 return;
1420 }
1421 value |= nreglist.GetTransferLane() << 3;
1422 SetEncodingValue(value);
1423 break;
1424 }
1425 default:
1426 break;
1427 }
1428}
1429
1430class Align_index_align_2 : public EncodingValue {
1431 public:
1432 Align_index_align_2(Alignment align,
1433 const NeonRegisterList& nreglist,
1434 DataType dt);
1435};
1436
1437Align_index_align_2::Align_index_align_2(Alignment align,
1438 const NeonRegisterList& nreglist,
1439 DataType dt) {
1440 switch (dt.GetValue()) {
1441 case Untyped8: {
1442 uint32_t value;
1443 if (align.GetType() == k16BitAlign) {
1444 value = 1;
1445 } else if (align.GetType() == kNoAlignment) {
1446 value = 0;
1447 } else {
1448 return;
1449 }
1450 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1451 return;
1452 }
1453 value |= nreglist.GetTransferLane() << 1;
1454 if (!nreglist.IsSingleSpaced()) return;
1455 SetEncodingValue(value);
1456 break;
1457 }
1458 case Untyped16: {
1459 uint32_t value;
1460 if (align.GetType() == k32BitAlign) {
1461 value = 1;
1462 } else if (align.GetType() == kNoAlignment) {
1463 value = 0;
1464 } else {
1465 return;
1466 }
1467 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1468 return;
1469 }
1470 value |= nreglist.GetTransferLane() << 2;
1471 if (nreglist.IsDoubleSpaced()) value |= 2;
1472 SetEncodingValue(value);
1473 break;
1474 }
1475 case Untyped32: {
1476 uint32_t value;
1477 if (align.GetType() == k64BitAlign) {
1478 value = 1;
1479 } else if (align.GetType() == kNoAlignment) {
1480 value = 0;
1481 } else {
1482 return;
1483 }
1484 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1485 return;
1486 }
1487 value |= nreglist.GetTransferLane() << 3;
1488 if (nreglist.IsDoubleSpaced()) value |= 4;
1489 SetEncodingValue(value);
1490 break;
1491 }
1492 default:
1493 break;
1494 }
1495}
1496
1497class Align_index_align_3 : public EncodingValue {
1498 public:
1499 Align_index_align_3(Alignment align,
1500 const NeonRegisterList& nreglist,
1501 DataType dt);
1502};
1503
1504Align_index_align_3::Align_index_align_3(Alignment align,
1505 const NeonRegisterList& nreglist,
1506 DataType dt) {
1507 switch (dt.GetValue()) {
1508 case Untyped8: {
1509 uint32_t value;
1510 if (align.GetType() == k32BitAlign) {
1511 value = 1;
1512 } else if (align.GetType() == kNoAlignment) {
1513 value = 0;
1514 } else {
1515 return;
1516 }
1517 if ((nreglist.GetTransferLane() & 7) != nreglist.GetTransferLane()) {
1518 return;
1519 }
1520 value |= nreglist.GetTransferLane() << 1;
1521 if (!nreglist.IsSingleSpaced()) return;
1522 SetEncodingValue(value);
1523 break;
1524 }
1525 case Untyped16: {
1526 uint32_t value;
1527 if (align.GetType() == k64BitAlign) {
1528 value = 1;
1529 } else if (align.GetType() == kNoAlignment) {
1530 value = 0;
1531 } else {
1532 return;
1533 }
1534 if ((nreglist.GetTransferLane() & 3) != nreglist.GetTransferLane()) {
1535 return;
1536 }
1537 value |= nreglist.GetTransferLane() << 2;
1538 if (nreglist.IsDoubleSpaced()) value |= 2;
1539 SetEncodingValue(value);
1540 break;
1541 }
1542 case Untyped32: {
1543 uint32_t value;
1544 if (align.GetType() == k64BitAlign) {
1545 value = 1;
1546 } else if (align.GetType() == k128BitAlign) {
1547 value = 2;
1548 } else if (align.GetType() == kNoAlignment) {
1549 value = 0;
1550 } else {
1551 return;
1552 }
1553 if ((nreglist.GetTransferLane() & 1) != nreglist.GetTransferLane()) {
1554 return;
1555 }
1556 value |= nreglist.GetTransferLane() << 3;
1557 if (nreglist.IsDoubleSpaced()) value |= 4;
1558 SetEncodingValue(value);
1559 break;
1560 }
1561 default:
1562 break;
1563 }
1564}
1565
1566class Align_a_1 : public EncodingValue {
1567 public:
1568 Align_a_1(Alignment align, DataType dt);
1569};
1570
1571Align_a_1::Align_a_1(Alignment align, DataType dt) {
1572 switch (align.GetType()) {
1573 case k16BitAlign:
1574 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1575 break;
1576 case k32BitAlign:
1577 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1578 break;
1579 case kNoAlignment:
1580 SetEncodingValue(0x0);
1581 break;
1582 default:
1583 break;
1584 }
1585}
1586
1587class Align_a_2 : public EncodingValue {
1588 public:
1589 Align_a_2(Alignment align, DataType dt);
1590};
1591
1592Align_a_2::Align_a_2(Alignment align, DataType dt) {
1593 switch (align.GetType()) {
1594 case k16BitAlign:
1595 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1596 break;
1597 case k32BitAlign:
1598 if (dt.Is(Untyped16)) SetEncodingValue(0x1);
1599 break;
1600 case k64BitAlign:
1601 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1602 break;
1603 case kNoAlignment:
1604 SetEncodingValue(0x0);
1605 break;
1606 default:
1607 break;
1608 }
1609}
1610
1611class Align_a_3 : public EncodingValue {
1612 public:
1613 Align_a_3(Alignment align, DataType dt);
1614};
1615
1616Align_a_3::Align_a_3(Alignment align, DataType dt) {
1617 switch (align.GetType()) {
1618 case k32BitAlign:
1619 if (dt.Is(Untyped8)) SetEncodingValue(0x1);
1620 break;
1621 case k64BitAlign:
1622 if (dt.Is(Untyped16))
1623 SetEncodingValue(0x1);
1624 else if (dt.Is(Untyped32))
1625 SetEncodingValue(0x1);
1626 break;
1627 case k128BitAlign:
1628 if (dt.Is(Untyped32)) SetEncodingValue(0x1);
1629 break;
1630 case kNoAlignment:
1631 SetEncodingValue(0x0);
1632 break;
1633 default:
1634 break;
1635 }
1636}
1637
1638class Align_align_1 : public EncodingValue {
1639 public:
1640 Align_align_1(Alignment align, const NeonRegisterList& nreglist);
1641};
1642
1643Align_align_1::Align_align_1(Alignment align,
1644 const NeonRegisterList& nreglist) {
1645 switch (align.GetType()) {
1646 case k64BitAlign:
1647 SetEncodingValue(0x1);
1648 break;
1649 case k128BitAlign:
1650 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1651 SetEncodingValue(0x2);
1652 break;
1653 case k256BitAlign:
1654 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1655 SetEncodingValue(0x3);
1656 break;
1657 case kNoAlignment:
1658 SetEncodingValue(0x0);
1659 break;
1660 default:
1661 break;
1662 }
1663}
1664
1665class Align_align_2 : public EncodingValue {
1666 public:
1667 Align_align_2(Alignment align, const NeonRegisterList& nreglist);
1668};
1669
1670Align_align_2::Align_align_2(Alignment align,
1671 const NeonRegisterList& nreglist) {
1672 switch (align.GetType()) {
1673 case k64BitAlign:
1674 SetEncodingValue(0x1);
1675 break;
1676 case k128BitAlign:
1677 SetEncodingValue(0x2);
1678 break;
1679 case k256BitAlign:
1680 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1681 break;
1682 case kNoAlignment:
1683 SetEncodingValue(0x0);
1684 break;
1685 default:
1686 break;
1687 }
1688}
1689
1690class Align_align_3 : public EncodingValue {
1691 public:
1692 explicit Align_align_3(Alignment align);
1693};
1694
1695Align_align_3::Align_align_3(Alignment align) {
1696 switch (align.GetType()) {
1697 case k64BitAlign:
1698 SetEncodingValue(0x1);
1699 break;
1700 case kNoAlignment:
1701 SetEncodingValue(0x0);
1702 break;
1703 default:
1704 break;
1705 }
1706}
1707
1708class Align_align_4 : public EncodingValue {
1709 public:
1710 explicit Align_align_4(Alignment align);
1711};
1712
1713Align_align_4::Align_align_4(Alignment align) {
1714 switch (align.GetType()) {
1715 case k64BitAlign:
1716 SetEncodingValue(0x1);
1717 break;
1718 case k128BitAlign:
1719 SetEncodingValue(0x2);
1720 break;
1721 case k256BitAlign:
1722 SetEncodingValue(0x3);
1723 break;
1724 case kNoAlignment:
1725 SetEncodingValue(0x0);
1726 break;
1727 default:
1728 break;
1729 }
1730}
1731
1732class Align_align_5 : public EncodingValue {
1733 public:
1734 Align_align_5(Alignment align, const NeonRegisterList& nreglist);
1735};
1736
1737Align_align_5::Align_align_5(Alignment align,
1738 const NeonRegisterList& nreglist) {
1739 switch (align.GetType()) {
1740 case k64BitAlign:
1741 SetEncodingValue(0x1);
1742 break;
1743 case k128BitAlign:
1744 if ((nreglist.GetLength() == 2) || (nreglist.GetLength() == 4))
1745 SetEncodingValue(0x2);
1746 break;
1747 case k256BitAlign:
1748 if ((nreglist.GetLength() == 4)) SetEncodingValue(0x3);
1749 break;
1750 case kNoAlignment:
1751 SetEncodingValue(0x0);
1752 break;
1753 default:
1754 break;
1755 }
1756}
1757
Vincent Belliardac285442017-05-16 09:26:45 -07001758
1759// CBNZ{<q>} <Rn>, <label> ; T1
1760// CBZ{<q>} <Rn>, <label> ; T1
1761static const struct ReferenceInfo kT16CbzInfo =
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001762 {k16BitT32InstructionSizeInBytes,
1763 0, // Min offset.
1764 126, // Max offset.
1765 2, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001766 ReferenceInfo::kDontAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001767
1768
1769// B<c>{<q>} <label> ; T1
1770static const struct ReferenceInfo kT16ConditionalBranchInfo =
1771 {k16BitT32InstructionSizeInBytes,
1772 -256, // Min offset.
1773 254, // Max offset.
1774 2, // Alignment.
1775 ReferenceInfo::kDontAlignPc};
1776
1777
1778// ADR{<c>}{<q>} <Rd>, <label> ; T1
1779// LDR{<c>}{<q>} <Rt>, <label> ; T1
1780static const struct ReferenceInfo kT16DataInfo =
1781 {k16BitT32InstructionSizeInBytes,
1782 0, // Min offset.
1783 1020, // Max offset.
1784 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001785 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001786
1787
1788// B{<c>}{<q>} <label> ; T2
1789static const struct ReferenceInfo kT16BranchInfo =
1790 {k16BitT32InstructionSizeInBytes,
1791 -2048, // Min offset.
1792 2046, // Max offset.
1793 2, // Alignment.
1794 ReferenceInfo::kDontAlignPc};
1795
1796
1797// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
1798// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
1799// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
1800static const struct ReferenceInfo kT32DataInfo =
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001801 {k32BitT32InstructionSizeInBytes,
1802 -1020, // Min offset.
1803 1020, // Max offset.
1804 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001805 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001806
1807
1808// ADR{<c>}{<q>} <Rd>, <label> ; T3
1809// LDR{<c>}{<q>} <Rt>, <label> ; T2
1810// LDRB{<c>}{<q>} <Rt>, <label> ; T1
1811// LDRH{<c>}{<q>} <Rt>, <label> ; T1
1812// LDRSB{<c>}{<q>} <Rt>, <label> ; T1
1813// LDRSH{<c>}{<q>} <Rt>, <label> ; T1
1814// PLD{<c>}{<q>} <label> ; T1
1815// PLI{<c>}{<q>} <label> ; T3
1816static const struct ReferenceInfo kT32FarDataInfo =
1817 {k32BitT32InstructionSizeInBytes,
1818 -4095, // Min offset.
1819 4095, // Max offset.
1820 1, // Alignment.
1821 ReferenceInfo::kAlignPc};
1822
1823
1824// B<c>{<q>} <label> ; T3
1825static const struct ReferenceInfo kT32ConditionalBranchInfo =
1826 {k32BitT32InstructionSizeInBytes,
1827 -1048576, // Min offset.
1828 1048574, // Max offset.
1829 2, // Alignment.
1830 ReferenceInfo::kDontAlignPc};
1831
1832
1833// B{<c>}{<q>} <label> ; T4
1834// BL{<c>}{<q>} <label> ; T1
1835static const struct ReferenceInfo kT32BranchInfo =
1836 {k32BitT32InstructionSizeInBytes,
1837 -16777216, // Min offset.
1838 16777214, // Max offset.
1839 2, // Alignment.
1840 ReferenceInfo::kDontAlignPc};
1841
1842
1843// BLX{<c>}{<q>} <label> ; T2
1844static const struct ReferenceInfo kT32BlxInfo =
1845 {k32BitT32InstructionSizeInBytes,
1846 -16777216, // Min offset.
1847 16777212, // Max offset.
1848 4, // Alignment.
1849 ReferenceInfo::kAlignPc};
1850
1851
1852// LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
1853// LDRH{<c>}{<q>} <Rt>, <label> ; A1
1854// LDRSB{<c>}{<q>} <Rt>, <label> ; A1
1855// LDRSH{<c>}{<q>} <Rt>, <label> ; A1
1856static const struct ReferenceInfo kA32VeryNearDataInfo =
1857 {kA32InstructionSizeInBytes,
1858 -255, // Min offset.
1859 255, // Max offset.
1860 1, // Alignment.
1861 ReferenceInfo::kAlignPc};
1862
1863
1864// ADR{<c>}{<q>} <Rd>, <label> ; A1
1865static const struct ReferenceInfo kA32AdrInfo = {kA32InstructionSizeInBytes,
1866 -256, // Min offset.
1867 256, // Max offset.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001868 1, // Alignment.
1869 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001870
1871
1872// VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
1873// VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
1874static const struct ReferenceInfo kA32DataInfo = {kA32InstructionSizeInBytes,
1875 -1020, // Min offset.
1876 1020, // Max offset.
1877 4, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001878 ReferenceInfo::kAlignPc};
Vincent Belliardac285442017-05-16 09:26:45 -07001879
1880
1881// LDR{<c>}{<q>} <Rt>, <label> ; A1
1882// LDRB{<c>}{<q>} <Rt>, <label> ; A1
1883// PLD{<c>}{<q>} <label> ; A1
1884// PLI{<c>}{<q>} <label> ; A1
1885static const struct ReferenceInfo kA32FarDataInfo = {kA32InstructionSizeInBytes,
1886 -4095, // Min offset.
1887 4095, // Max offset.
1888 1, // Alignment.
1889 ReferenceInfo::kAlignPc};
1890
1891
1892// B{<c>}{<q>} <label> ; A1
1893// BL{<c>}{<q>} <label> ; A1
1894static const struct ReferenceInfo kA32BranchInfo =
1895 {kA32InstructionSizeInBytes,
1896 -33554432, // Min offset.
1897 33554428, // Max offset.
1898 4, // Alignment.
1899 ReferenceInfo::kDontAlignPc};
1900
1901
1902// BLX{<c>}{<q>} <label> ; A2
1903static const struct ReferenceInfo kA32BlxInfo = {kA32InstructionSizeInBytes,
1904 -33554432, // Min offset.
1905 33554430, // Max offset.
1906 2, // Alignment.
Georgia Kouveli8b57c862017-03-02 15:18:58 +00001907 ReferenceInfo::kAlignPc};
Georgia Kouveli4b139a22017-03-31 16:11:11 +01001908
Alexandre Ramesd3832962016-07-04 15:03:43 +01001909
1910void Assembler::adc(Condition cond,
1911 EncodingSize size,
1912 Register rd,
1913 Register rn,
1914 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07001915 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01001916 CheckIT(cond);
1917 if (operand.IsImmediate()) {
1918 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001919 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001920 ImmediateT32 immediate_t32(imm);
1921 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08001922 if (!size.IsNarrow() && immediate_t32.IsValid() &&
1923 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001924 EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1925 (immediate_t32.GetEncodingValue() & 0xff) |
1926 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
1927 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
1928 AdvanceIT();
1929 return;
1930 }
1931 } else {
1932 ImmediateA32 immediate_a32(imm);
1933 // ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
1934 if (immediate_a32.IsValid() && cond.IsNotNever()) {
1935 EmitA32(0x02a00000U | (cond.GetCondition() << 28) |
1936 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
1937 immediate_a32.GetEncodingValue());
1938 return;
1939 }
1940 }
1941 }
1942 if (operand.IsImmediateShiftedRegister()) {
1943 Register rm = operand.GetBaseRegister();
1944 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001945 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001946 // ADC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
1947 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
1948 rm.IsLow()) {
1949 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
1950 AdvanceIT();
1951 return;
1952 }
1953 }
1954 }
1955 Shift shift = operand.GetShift();
1956 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001957 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001958 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08001959 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
1960 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001961 uint32_t amount_ = amount % 32;
1962 EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
1963 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
1964 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
1965 AdvanceIT();
1966 return;
1967 }
1968 } else {
1969 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
1970 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
1971 uint32_t amount_ = amount % 32;
1972 EmitA32(0x00a00000U | (cond.GetCondition() << 28) |
1973 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
1974 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
1975 return;
1976 }
1977 }
1978 }
1979 if (operand.IsRegisterShiftedRegister()) {
1980 Register rm = operand.GetBaseRegister();
1981 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00001982 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01001983 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001984 // ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00001985 if (cond.IsNotNever() &&
1986 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
1987 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01001988 EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
1989 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00001990 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01001991 return;
1992 }
1993 }
1994 }
1995 Delegate(kAdc, &Assembler::adc, cond, size, rd, rn, operand);
1996}
1997
1998void Assembler::adcs(Condition cond,
1999 EncodingSize size,
2000 Register rd,
2001 Register rn,
2002 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002003 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002004 CheckIT(cond);
2005 if (operand.IsImmediate()) {
2006 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002007 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002008 ImmediateT32 immediate_t32(imm);
2009 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08002010 if (!size.IsNarrow() && immediate_t32.IsValid() &&
2011 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002012 EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2013 (immediate_t32.GetEncodingValue() & 0xff) |
2014 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2015 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2016 AdvanceIT();
2017 return;
2018 }
2019 } else {
2020 ImmediateA32 immediate_a32(imm);
2021 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2022 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2023 EmitA32(0x02b00000U | (cond.GetCondition() << 28) |
2024 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2025 immediate_a32.GetEncodingValue());
2026 return;
2027 }
2028 }
2029 }
2030 if (operand.IsImmediateShiftedRegister()) {
2031 Register rm = operand.GetBaseRegister();
2032 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002033 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002034 // ADCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2035 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2036 rm.IsLow()) {
2037 EmitT32_16(0x4140 | rd.GetCode() | (rm.GetCode() << 3));
2038 AdvanceIT();
2039 return;
2040 }
2041 }
2042 }
2043 Shift shift = operand.GetShift();
2044 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002045 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002046 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002047 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2048 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002049 uint32_t amount_ = amount % 32;
2050 EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2051 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2052 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2053 AdvanceIT();
2054 return;
2055 }
2056 } else {
2057 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2058 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2059 uint32_t amount_ = amount % 32;
2060 EmitA32(0x00b00000U | (cond.GetCondition() << 28) |
2061 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2062 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2063 return;
2064 }
2065 }
2066 }
2067 if (operand.IsRegisterShiftedRegister()) {
2068 Register rm = operand.GetBaseRegister();
2069 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002070 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002071 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002072 // ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002073 if (cond.IsNotNever() &&
2074 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2075 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002076 EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
2077 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002078 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002079 return;
2080 }
2081 }
2082 }
2083 Delegate(kAdcs, &Assembler::adcs, cond, size, rd, rn, operand);
2084}
2085
2086void Assembler::add(Condition cond,
2087 EncodingSize size,
2088 Register rd,
2089 Register rn,
2090 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002091 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002092 CheckIT(cond);
2093 if (operand.IsImmediate()) {
2094 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002095 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002096 ImmediateT32 immediate_t32(imm);
2097 // ADD{<c>}{<q>} <Rd>, PC, #<imm8> ; T1
2098 if (!size.IsWide() && rd.IsLow() && rn.Is(pc) && (imm <= 1020) &&
2099 ((imm % 4) == 0)) {
2100 uint32_t imm_ = imm >> 2;
2101 EmitT32_16(0xa000 | (rd.GetCode() << 8) | imm_);
2102 AdvanceIT();
2103 return;
2104 }
2105 // ADD<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
2106 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2107 (imm <= 7)) {
2108 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2109 AdvanceIT();
2110 return;
2111 }
2112 // ADD<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2113 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2114 (imm <= 255)) {
2115 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2116 AdvanceIT();
2117 return;
2118 }
2119 // ADD{<c>}{<q>} <Rd>, SP, #<imm8> ; T1
2120 if (!size.IsWide() && rd.IsLow() && rn.Is(sp) && (imm <= 1020) &&
2121 ((imm % 4) == 0)) {
2122 uint32_t imm_ = imm >> 2;
2123 EmitT32_16(0xa800 | (rd.GetCode() << 8) | imm_);
2124 AdvanceIT();
2125 return;
2126 }
2127 // ADD{<c>}{<q>} {SP}, SP, #<imm7> ; T2
2128 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
2129 ((imm % 4) == 0)) {
2130 uint32_t imm_ = imm >> 2;
2131 EmitT32_16(0xb000 | imm_);
2132 AdvanceIT();
2133 return;
2134 }
2135 // ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002136 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002137 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002138 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2139 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2140 AdvanceIT();
2141 return;
2142 }
2143 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002144 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
2145 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002146 EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2147 (immediate_t32.GetEncodingValue() & 0xff) |
2148 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2149 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2150 AdvanceIT();
2151 return;
2152 }
2153 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002154 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002155 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002156 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2157 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2158 AdvanceIT();
2159 return;
2160 }
2161 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002162 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002163 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002164 EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
2165 (immediate_t32.GetEncodingValue() & 0xff) |
2166 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2167 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2168 AdvanceIT();
2169 return;
2170 }
2171 // ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002172 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002173 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002174 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2175 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2176 AdvanceIT();
2177 return;
2178 }
2179 } else {
2180 ImmediateA32 immediate_a32(imm);
2181 // ADD{<c>}{<q>} <Rd>, PC, #<const> ; A1
2182 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
2183 EmitA32(0x028f0000U | (cond.GetCondition() << 28) |
2184 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2185 return;
2186 }
2187 // ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2188 if (immediate_a32.IsValid() && cond.IsNotNever() &&
2189 ((rn.GetCode() & 0xd) != 0xd)) {
2190 EmitA32(0x02800000U | (cond.GetCondition() << 28) |
2191 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2192 immediate_a32.GetEncodingValue());
2193 return;
2194 }
2195 // ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2196 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2197 EmitA32(0x028d0000U | (cond.GetCondition() << 28) |
2198 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2199 return;
2200 }
2201 }
2202 }
2203 if (operand.IsImmediateShiftedRegister()) {
2204 Register rm = operand.GetBaseRegister();
2205 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002206 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002207 // ADD<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
2208 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2209 rm.IsLow()) {
2210 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2211 (rm.GetCode() << 6));
2212 AdvanceIT();
2213 return;
2214 }
2215 // ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002216 if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
2217 (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2218 (!rd.IsPC() || !rm.IsPC())) ||
2219 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002220 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
2221 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
2222 AdvanceIT();
2223 return;
2224 }
2225 // ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
Vincent Belliardd17e3482016-11-22 15:46:43 -08002226 if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002227 ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
Vincent Belliardd17e3482016-11-22 15:46:43 -08002228 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002229 EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
2230 ((rd.GetCode() & 0x8) << 4));
2231 AdvanceIT();
2232 return;
2233 }
2234 // ADD{<c>}{<q>} {SP}, SP, <Rm> ; T2
2235 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && !rm.Is(sp)) {
2236 EmitT32_16(0x4485 | (rm.GetCode() << 3));
2237 AdvanceIT();
2238 return;
2239 }
2240 }
2241 }
2242 Shift shift = operand.GetShift();
2243 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002244 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002245 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002246 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
2247 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002248 uint32_t amount_ = amount % 32;
2249 EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2250 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2251 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2252 AdvanceIT();
2253 return;
2254 }
2255 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08002256 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
2257 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002258 uint32_t amount_ = amount % 32;
2259 EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2260 (operand.GetTypeEncodingValue() << 4) |
2261 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2262 AdvanceIT();
2263 return;
2264 }
2265 } else {
2266 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2267 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2268 uint32_t amount_ = amount % 32;
2269 EmitA32(0x00800000U | (cond.GetCondition() << 28) |
2270 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2271 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2272 return;
2273 }
2274 // ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2275 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2276 uint32_t amount_ = amount % 32;
2277 EmitA32(0x008d0000U | (cond.GetCondition() << 28) |
2278 (rd.GetCode() << 12) | rm.GetCode() |
2279 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2280 return;
2281 }
2282 }
2283 }
2284 if (operand.IsRegisterShiftedRegister()) {
2285 Register rm = operand.GetBaseRegister();
2286 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002287 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002288 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002289 // ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002290 if (cond.IsNotNever() &&
2291 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2292 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002293 EmitA32(0x00800010U | (cond.GetCondition() << 28) |
2294 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002295 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002296 return;
2297 }
2298 }
2299 }
2300 Delegate(kAdd, &Assembler::add, cond, size, rd, rn, operand);
2301}
2302
2303void Assembler::add(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002304 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002305 CheckIT(cond);
2306 if (operand.IsImmediate()) {
2307 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002308 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002309 // ADD<c>{<q>} <Rdn>, #<imm8> ; T2
2310 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
2311 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2312 AdvanceIT();
2313 return;
2314 }
2315 }
2316 }
2317 if (operand.IsPlainRegister()) {
2318 Register rm = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002319 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002320 // ADD<c>{<q>} <Rdn>, <Rm> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08002321 if (InITBlock() && !rm.Is(sp) &&
2322 (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
2323 (!rd.IsPC() || !rm.IsPC())) ||
2324 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002325 EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
2326 (rm.GetCode() << 3));
2327 AdvanceIT();
2328 return;
2329 }
2330 }
2331 }
2332 Delegate(kAdd, &Assembler::add, cond, rd, operand);
2333}
2334
2335void Assembler::adds(Condition cond,
2336 EncodingSize size,
2337 Register rd,
2338 Register rn,
2339 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002340 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002341 CheckIT(cond);
2342 if (operand.IsImmediate()) {
2343 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002344 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002345 ImmediateT32 immediate_t32(imm);
2346 // ADDS{<q>} <Rd>, <Rn>, #<imm3> ; T1
2347 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2348 (imm <= 7)) {
2349 EmitT32_16(0x1c00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
2350 AdvanceIT();
2351 return;
2352 }
2353 // ADDS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
2354 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2355 (imm <= 255)) {
2356 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2357 AdvanceIT();
2358 return;
2359 }
2360 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
2361 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002362 !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002363 EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2364 (immediate_t32.GetEncodingValue() & 0xff) |
2365 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2366 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2367 AdvanceIT();
2368 return;
2369 }
2370 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
2371 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
2372 !rd.Is(pc)) {
2373 EmitT32_32(0xf11d0000U | (rd.GetCode() << 8) |
2374 (immediate_t32.GetEncodingValue() & 0xff) |
2375 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2376 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2377 AdvanceIT();
2378 return;
2379 }
2380 } else {
2381 ImmediateA32 immediate_a32(imm);
2382 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2383 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
2384 EmitA32(0x02900000U | (cond.GetCondition() << 28) |
2385 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2386 immediate_a32.GetEncodingValue());
2387 return;
2388 }
2389 // ADDS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
2390 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
2391 EmitA32(0x029d0000U | (cond.GetCondition() << 28) |
2392 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
2393 return;
2394 }
2395 }
2396 }
2397 if (operand.IsImmediateShiftedRegister()) {
2398 Register rm = operand.GetBaseRegister();
2399 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002400 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002401 // ADDS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
2402 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
2403 rm.IsLow()) {
2404 EmitT32_16(0x1800 | rd.GetCode() | (rn.GetCode() << 3) |
2405 (rm.GetCode() << 6));
2406 AdvanceIT();
2407 return;
2408 }
2409 }
2410 }
2411 Shift shift = operand.GetShift();
2412 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002413 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002414 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
2415 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
Vincent Belliardd17e3482016-11-22 15:46:43 -08002416 !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002417 uint32_t amount_ = amount % 32;
2418 EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2419 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2420 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2421 AdvanceIT();
2422 return;
2423 }
2424 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
2425 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002426 !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002427 uint32_t amount_ = amount % 32;
2428 EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
2429 (operand.GetTypeEncodingValue() << 4) |
2430 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2431 AdvanceIT();
2432 return;
2433 }
2434 } else {
2435 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2436 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
2437 uint32_t amount_ = amount % 32;
2438 EmitA32(0x00900000U | (cond.GetCondition() << 28) |
2439 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2440 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2441 return;
2442 }
2443 // ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
2444 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
2445 uint32_t amount_ = amount % 32;
2446 EmitA32(0x009d0000U | (cond.GetCondition() << 28) |
2447 (rd.GetCode() << 12) | rm.GetCode() |
2448 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2449 return;
2450 }
2451 }
2452 }
2453 if (operand.IsRegisterShiftedRegister()) {
2454 Register rm = operand.GetBaseRegister();
2455 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002456 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002457 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002458 // ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002459 if (cond.IsNotNever() &&
2460 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2461 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002462 EmitA32(0x00900010U | (cond.GetCondition() << 28) |
2463 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002464 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002465 return;
2466 }
2467 }
2468 }
2469 Delegate(kAdds, &Assembler::adds, cond, size, rd, rn, operand);
2470}
2471
2472void Assembler::adds(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002473 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002474 CheckIT(al);
2475 if (operand.IsImmediate()) {
2476 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002477 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002478 // ADDS{<q>} <Rdn>, #<imm8> ; T2
2479 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
2480 EmitT32_16(0x3000 | (rd.GetCode() << 8) | imm);
2481 AdvanceIT();
2482 return;
2483 }
2484 }
2485 }
2486 Delegate(kAdds, &Assembler::adds, rd, operand);
2487}
2488
2489void Assembler::addw(Condition cond,
2490 Register rd,
2491 Register rn,
2492 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002493 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002494 CheckIT(cond);
2495 if (operand.IsImmediate()) {
2496 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002497 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002498 // ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08002499 if (rn.Is(pc) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002500 EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2501 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2502 AdvanceIT();
2503 return;
2504 }
2505 // ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Vincent Belliardd17e3482016-11-22 15:46:43 -08002506 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002507 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002508 EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2509 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2510 AdvanceIT();
2511 return;
2512 }
2513 // ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
Vincent Belliard942e3b72016-11-29 15:50:14 -08002514 if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002515 EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
2516 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
2517 AdvanceIT();
2518 return;
2519 }
2520 }
2521 }
2522 Delegate(kAddw, &Assembler::addw, cond, rd, rn, operand);
2523}
2524
2525void Assembler::adr(Condition cond,
2526 EncodingSize size,
2527 Register rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002528 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002529 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002530 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002531 Location::Offset offset =
2532 location->IsBound()
2533 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01002534 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
2535 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002536 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002537 int32_t neg_offset = -offset;
2538 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2539 if (!size.IsWide() && rd.IsLow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002540 ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002541 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002542 (!location->IsBound() && size.IsNarrow()))) {
2543 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002544 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002545 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002546 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002547 Location::Offset pc,
2548 const Location* location) const VIXL_OVERRIDE {
2549 pc += kT32PcDelta;
2550 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002551 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
2552 ((offset & 0x3) == 0));
2553 const int32_t target = offset >> 2;
2554 return instr | (target & 0xff);
2555 }
2556 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002557 EmitT32_16(
Vincent Belliardac285442017-05-16 09:26:45 -07002558 Link(0xa000 | (rd.GetCode() << 8), location, immop, &kT16DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002559 AdvanceIT();
2560 return;
2561 }
2562 // ADR{<c>}{<q>} <Rd>, <label> ; T2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002563 if (!size.IsNarrow() && location->IsBound() && (neg_offset > 0) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002564 (neg_offset <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002565 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
2566 ((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
2567 AdvanceIT();
2568 return;
2569 }
2570 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2571 if (!size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002572 (!location->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08002573 (!rd.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002574 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002575 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002576 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002577 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002578 Location::Offset pc,
2579 const Location* location) const VIXL_OVERRIDE {
2580 pc += kT32PcDelta;
2581 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002582 int32_t target;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00002583 if ((offset >= 0) && (offset <= 4095)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002584 target = offset;
2585 } else {
2586 target = -offset;
2587 VIXL_ASSERT((target >= 0) && (target <= 4095));
2588 // Emit the T2 encoding.
2589 instr |= 0x00a00000;
2590 }
2591 return instr | (target & 0xff) | ((target & 0x700) << 4) |
2592 ((target & 0x800) << 15);
2593 }
2594 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002595 EmitT32_32(Link(0xf20f0000U | (rd.GetCode() << 8),
2596 location,
2597 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07002598 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002599 AdvanceIT();
2600 return;
2601 }
2602 } else {
2603 ImmediateA32 positive_immediate_a32(offset);
2604 ImmediateA32 negative_immediate_a32(-offset);
2605 // ADR{<c>}{<q>} <Rd>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002606 if ((!location->IsBound() || positive_immediate_a32.IsValid()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002607 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002608 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002609 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002610 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00002611 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002612 Location::Offset pc,
2613 const Location* location) const VIXL_OVERRIDE {
2614 pc += kA32PcDelta;
2615 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002616 int32_t target;
2617 ImmediateA32 positive_immediate_a32(offset);
2618 if (positive_immediate_a32.IsValid()) {
2619 target = positive_immediate_a32.GetEncodingValue();
2620 } else {
2621 ImmediateA32 negative_immediate_a32(-offset);
2622 VIXL_ASSERT(negative_immediate_a32.IsValid());
2623 // Emit the A2 encoding.
2624 target = negative_immediate_a32.GetEncodingValue();
2625 instr = (instr & ~0x00f00000) | 0x00400000;
2626 }
2627 return instr | (target & 0xfff);
2628 }
2629 } immop;
2630 EmitA32(
2631 Link(0x028f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002632 location,
2633 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07002634 &kA32AdrInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002635 return;
2636 }
2637 // ADR{<c>}{<q>} <Rd>, <label> ; A2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002638 if (location->IsBound() && negative_immediate_a32.IsValid() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01002639 cond.IsNotNever()) {
2640 EmitA32(0x024f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
2641 negative_immediate_a32.GetEncodingValue());
2642 return;
2643 }
2644 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002645 Delegate(kAdr, &Assembler::adr, cond, size, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01002646}
2647
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002648bool Assembler::adr_info(Condition cond,
2649 EncodingSize size,
2650 Register rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002651 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002652 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002653 VIXL_ASSERT(!location->IsBound());
2654 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002655 if (IsUsingT32()) {
2656 // ADR{<c>}{<q>} <Rd>, <label> ; T1
2657 if (!size.IsWide() && rd.IsLow() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002658 *info = &kT16DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002659 return true;
2660 }
2661 // Skipped T2, as it is a negative offset variant.
2662 // The minimum offset is included in the corresponding
2663 // positive variant.
2664 // ADR{<c>}{<q>} <Rd>, <label> ; T3
2665 if (!size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002666 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002667 return true;
2668 }
2669 } else {
2670 // ADR{<c>}{<q>} <Rd>, <label> ; A1
2671 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07002672 *info = &kA32AdrInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01002673 return true;
2674 }
2675 // Skipped A2, as it is a negative offset variant.
2676 // The minimum offset is included in the corresponding
2677 // positive variant.
2678 }
2679 return false;
2680}
2681
Alexandre Ramesd3832962016-07-04 15:03:43 +01002682void Assembler::and_(Condition cond,
2683 EncodingSize size,
2684 Register rd,
2685 Register rn,
2686 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002687 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002688 CheckIT(cond);
2689 if (operand.IsImmediate()) {
2690 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002691 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002692 ImmediateT32 immediate_t32(imm);
2693 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00002694 if (!size.IsNarrow() && immediate_t32.IsValid() &&
2695 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002696 EmitT32_32(0xf0000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2697 (immediate_t32.GetEncodingValue() & 0xff) |
2698 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2699 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2700 AdvanceIT();
2701 return;
2702 }
2703 } else {
2704 ImmediateA32 immediate_a32(imm);
2705 // AND{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2706 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2707 EmitA32(0x02000000U | (cond.GetCondition() << 28) |
2708 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2709 immediate_a32.GetEncodingValue());
2710 return;
2711 }
2712 }
2713 }
2714 if (operand.IsImmediateShiftedRegister()) {
2715 Register rm = operand.GetBaseRegister();
2716 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002717 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002718 // AND<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2719 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2720 rm.IsLow()) {
2721 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2722 AdvanceIT();
2723 return;
2724 }
2725 }
2726 }
2727 Shift shift = operand.GetShift();
2728 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002729 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002730 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00002731 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
2732 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002733 uint32_t amount_ = amount % 32;
2734 EmitT32_32(0xea000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2735 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2736 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2737 AdvanceIT();
2738 return;
2739 }
2740 } else {
2741 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2742 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2743 uint32_t amount_ = amount % 32;
2744 EmitA32(0x00000000U | (cond.GetCondition() << 28) |
2745 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2746 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2747 return;
2748 }
2749 }
2750 }
2751 if (operand.IsRegisterShiftedRegister()) {
2752 Register rm = operand.GetBaseRegister();
2753 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002754 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002755 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002756 // AND{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002757 if (cond.IsNotNever() &&
2758 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2759 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002760 EmitA32(0x00000010U | (cond.GetCondition() << 28) |
2761 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002762 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002763 return;
2764 }
2765 }
2766 }
2767 Delegate(kAnd, &Assembler::and_, cond, size, rd, rn, operand);
2768}
2769
2770void Assembler::ands(Condition cond,
2771 EncodingSize size,
2772 Register rd,
2773 Register rn,
2774 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002775 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002776 CheckIT(cond);
2777 if (operand.IsImmediate()) {
2778 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002779 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002780 ImmediateT32 immediate_t32(imm);
2781 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00002782 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
2783 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002784 EmitT32_32(0xf0100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2785 (immediate_t32.GetEncodingValue() & 0xff) |
2786 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
2787 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
2788 AdvanceIT();
2789 return;
2790 }
2791 } else {
2792 ImmediateA32 immediate_a32(imm);
2793 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
2794 if (immediate_a32.IsValid() && cond.IsNotNever()) {
2795 EmitA32(0x02100000U | (cond.GetCondition() << 28) |
2796 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
2797 immediate_a32.GetEncodingValue());
2798 return;
2799 }
2800 }
2801 }
2802 if (operand.IsImmediateShiftedRegister()) {
2803 Register rm = operand.GetBaseRegister();
2804 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002806 // ANDS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
2807 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
2808 rm.IsLow()) {
2809 EmitT32_16(0x4000 | rd.GetCode() | (rm.GetCode() << 3));
2810 AdvanceIT();
2811 return;
2812 }
2813 }
2814 }
2815 Shift shift = operand.GetShift();
2816 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002817 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002818 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00002819 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
2820 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002821 uint32_t amount_ = amount % 32;
2822 EmitT32_32(0xea100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
2823 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
2824 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2825 AdvanceIT();
2826 return;
2827 }
2828 } else {
2829 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
2830 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
2831 uint32_t amount_ = amount % 32;
2832 EmitA32(0x00100000U | (cond.GetCondition() << 28) |
2833 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
2834 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
2835 return;
2836 }
2837 }
2838 }
2839 if (operand.IsRegisterShiftedRegister()) {
2840 Register rm = operand.GetBaseRegister();
2841 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00002842 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002843 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002844 // ANDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00002845 if (cond.IsNotNever() &&
2846 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
2847 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002848 EmitA32(0x00100010U | (cond.GetCondition() << 28) |
2849 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00002850 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01002851 return;
2852 }
2853 }
2854 }
2855 Delegate(kAnds, &Assembler::ands, cond, size, rd, rn, operand);
2856}
2857
2858void Assembler::asr(Condition cond,
2859 EncodingSize size,
2860 Register rd,
2861 Register rm,
2862 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002863 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002864 CheckIT(cond);
2865 if (operand.IsImmediate()) {
2866 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002867 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002868 // ASR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2869 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2870 (imm >= 1) && (imm <= 32)) {
2871 uint32_t amount_ = imm % 32;
2872 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2873 (amount_ << 6));
2874 AdvanceIT();
2875 return;
2876 }
2877 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002878 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2879 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002880 uint32_t amount_ = imm % 32;
2881 EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2882 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2883 AdvanceIT();
2884 return;
2885 }
2886 } else {
2887 // ASR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2888 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2889 uint32_t amount_ = imm % 32;
2890 EmitA32(0x01a00040U | (cond.GetCondition() << 28) |
2891 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2892 return;
2893 }
2894 }
2895 }
2896 if (operand.IsPlainRegister()) {
2897 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002898 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002899 // ASR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2900 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2901 rs.IsLow()) {
2902 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2903 AdvanceIT();
2904 return;
2905 }
2906 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002907 if (!size.IsNarrow() &&
2908 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002909 EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2910 rs.GetCode());
2911 AdvanceIT();
2912 return;
2913 }
2914 } else {
2915 // ASR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002916 if (cond.IsNotNever() &&
2917 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002918 EmitA32(0x01a00050U | (cond.GetCondition() << 28) |
2919 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2920 return;
2921 }
2922 }
2923 }
2924 Delegate(kAsr, &Assembler::asr, cond, size, rd, rm, operand);
2925}
2926
2927void Assembler::asrs(Condition cond,
2928 EncodingSize size,
2929 Register rd,
2930 Register rm,
2931 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002932 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01002933 CheckIT(cond);
2934 if (operand.IsImmediate()) {
2935 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002936 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002937 // ASRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
2938 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
2939 (imm >= 1) && (imm <= 32)) {
2940 uint32_t amount_ = imm % 32;
2941 EmitT32_16(0x1000 | rd.GetCode() | (rm.GetCode() << 3) |
2942 (amount_ << 6));
2943 AdvanceIT();
2944 return;
2945 }
2946 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002947 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
2948 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002949 uint32_t amount_ = imm % 32;
2950 EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() |
2951 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
2952 AdvanceIT();
2953 return;
2954 }
2955 } else {
2956 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
2957 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
2958 uint32_t amount_ = imm % 32;
2959 EmitA32(0x01b00040U | (cond.GetCondition() << 28) |
2960 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
2961 return;
2962 }
2963 }
2964 }
2965 if (operand.IsPlainRegister()) {
2966 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01002967 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002968 // ASRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
2969 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
2970 rs.IsLow()) {
2971 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
2972 AdvanceIT();
2973 return;
2974 }
2975 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002976 if (!size.IsNarrow() &&
2977 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002978 EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
2979 rs.GetCode());
2980 AdvanceIT();
2981 return;
2982 }
2983 } else {
2984 // ASRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00002985 if (cond.IsNotNever() &&
2986 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01002987 EmitA32(0x01b00050U | (cond.GetCondition() << 28) |
2988 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
2989 return;
2990 }
2991 }
2992 }
2993 Delegate(kAsrs, &Assembler::asrs, cond, size, rd, rm, operand);
2994}
2995
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002996void Assembler::b(Condition cond, EncodingSize size, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07002997 VIXL_ASSERT(AllowAssembler());
Georgia Kouveli275c9d42017-05-12 18:07:45 +01002998 Location::Offset offset =
2999 location->IsBound()
3000 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003001 (GetCursorOffset() + GetArchitectureStatePCOffset())
3002 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003003 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003004 // B<c>{<q>} <label> ; T1
3005 if (OutsideITBlock() && !size.IsWide() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003006 ((location->IsBound() && (offset >= -256) && (offset <= 254) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003007 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003008 (!location->IsBound() && size.IsNarrow())) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003009 !cond.Is(al) && cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003010 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003011 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003012 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003013 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003014 Location::Offset pc,
3015 const Location* location) const VIXL_OVERRIDE {
3016 pc += kT32PcDelta;
3017 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003018 VIXL_ASSERT((offset >= -256) && (offset <= 254) &&
3019 ((offset & 0x1) == 0));
3020 const int32_t target = offset >> 1;
3021 return instr | (target & 0xff);
3022 }
3023 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003024 EmitT32_16(Link(0xd000 | (cond.GetCondition() << 8),
3025 location,
3026 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003027 &kT16ConditionalBranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003028 AdvanceIT();
3029 return;
3030 }
3031 // B{<c>}{<q>} <label> ; T2
3032 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003033 ((location->IsBound() && (offset >= -2048) && (offset <= 2046) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003034 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003035 (!location->IsBound() && size.IsNarrow()))) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003036 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003037 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003038 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003039 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003040 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003041 Location::Offset pc,
3042 const Location* location) const VIXL_OVERRIDE {
3043 pc += kT32PcDelta;
3044 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003045 VIXL_ASSERT((offset >= -2048) && (offset <= 2046) &&
3046 ((offset & 0x1) == 0));
3047 const int32_t target = offset >> 1;
3048 return instr | (target & 0x7ff);
3049 }
3050 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003051 EmitT32_16(Link(0xe000, location, immop, &kT16BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003052 AdvanceIT();
3053 return;
3054 }
3055 // B<c>{<q>} <label> ; T3
3056 if (OutsideITBlock() && !size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003057 ((location->IsBound() && (offset >= -1048576) && (offset <= 1048574) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003058 ((offset & 0x1) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003059 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003060 !cond.Is(al) && cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003061 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003062 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003063 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003064 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003065 Location::Offset pc,
3066 const Location* location) const VIXL_OVERRIDE {
3067 pc += kT32PcDelta;
3068 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003069 VIXL_ASSERT((offset >= -1048576) && (offset <= 1048574) &&
3070 ((offset & 0x1) == 0));
3071 const int32_t target = offset >> 1;
3072 return instr | (target & 0x7ff) | ((target & 0x1f800) << 5) |
3073 ((target & 0x20000) >> 4) | ((target & 0x40000) >> 7) |
3074 ((target & 0x80000) << 7);
3075 }
3076 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003077 EmitT32_32(Link(0xf0008000U | (cond.GetCondition() << 22),
3078 location,
3079 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003080 &kT32ConditionalBranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003081 AdvanceIT();
3082 return;
3083 }
3084 // B{<c>}{<q>} <label> ; T4
3085 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003086 ((location->IsBound() && (offset >= -16777216) &&
3087 (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3088 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003089 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003090 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003091 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003092 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003093 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003094 Location::Offset pc,
3095 const Location* location) const VIXL_OVERRIDE {
3096 pc += kT32PcDelta;
3097 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003098 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3099 ((offset & 0x1) == 0));
3100 int32_t target = offset >> 1;
3101 uint32_t S = target & (1 << 23);
3102 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3103 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3104 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3105 ((target & 0x800000) << 3);
3106 }
3107 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003108 EmitT32_32(Link(0xf0009000U, location, immop, &kT32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003109 AdvanceIT();
3110 return;
3111 }
3112 } else {
3113 // B{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003114 if (((location->IsBound() && (offset >= -33554432) &&
3115 (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3116 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003117 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003118 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003119 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003120 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003121 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003122 Location::Offset pc,
3123 const Location* location) const VIXL_OVERRIDE {
3124 pc += kA32PcDelta;
3125 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003126 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3127 ((offset & 0x3) == 0));
3128 const int32_t target = offset >> 2;
3129 return instr | (target & 0xffffff);
3130 }
3131 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003132 EmitA32(Link(0x0a000000U | (cond.GetCondition() << 28),
3133 location,
3134 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003135 &kA32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003136 return;
3137 }
3138 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003139 Delegate(kB, &Assembler::b, cond, size, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003140}
3141
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003142bool Assembler::b_info(Condition cond,
3143 EncodingSize size,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003144 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003145 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003146 VIXL_ASSERT(!location->IsBound());
3147 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003148 if (IsUsingT32()) {
3149 // B<c>{<q>} <label> ; T1
3150 if (OutsideITBlock() && !size.IsWide() && size.IsNarrow() && !cond.Is(al) &&
3151 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003152 *info = &kT16ConditionalBranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003153 return true;
3154 }
3155 // B{<c>}{<q>} <label> ; T2
3156 if (OutsideITBlockAndAlOrLast(cond) && !size.IsWide() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003157 *info = &kT16BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003158 return true;
3159 }
3160 // B<c>{<q>} <label> ; T3
3161 if (OutsideITBlock() && !size.IsNarrow() && !cond.Is(al) &&
3162 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003163 *info = &kT32ConditionalBranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003164 return true;
3165 }
3166 // B{<c>}{<q>} <label> ; T4
3167 if (OutsideITBlockAndAlOrLast(cond) && !size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003168 *info = &kT32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003169 return true;
3170 }
3171 } else {
3172 // B{<c>}{<q>} <label> ; A1
3173 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003174 *info = &kA32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003175 return true;
3176 }
3177 }
3178 return false;
3179}
3180
Vincent Belliard609821f2017-02-08 14:17:25 -08003181void Assembler::bfc(Condition cond, Register rd, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003182 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003183 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08003184 if (IsUsingT32()) {
3185 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003186 if ((lsb <= 31) && (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3187 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003188 uint32_t msb = lsb + width - 1;
3189 EmitT32_32(0xf36f0000U | (rd.GetCode() << 8) | ((lsb & 0x3) << 6) |
3190 ((lsb & 0x1c) << 10) | msb);
3191 AdvanceIT();
3192 return;
3193 }
3194 } else {
3195 // BFC{<c>}{<q>} <Rd>, #<lsb>, #<width> ; A1
3196 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003197 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3198 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003199 uint32_t msb = lsb + width - 1;
3200 EmitA32(0x07c0001fU | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3201 (lsb << 7) | (msb << 16));
3202 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003203 }
3204 }
Vincent Belliard609821f2017-02-08 14:17:25 -08003205 Delegate(kBfc, &Assembler::bfc, cond, rd, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003206}
3207
Vincent Belliard609821f2017-02-08 14:17:25 -08003208void Assembler::bfi(
3209 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003210 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003211 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08003212 if (IsUsingT32()) {
3213 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
3214 if ((lsb <= 31) && !rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003215 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3216 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003217 uint32_t msb = lsb + width - 1;
3218 EmitT32_32(0xf3600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3219 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | msb);
3220 AdvanceIT();
3221 return;
3222 }
3223 } else {
3224 // BFI{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
3225 if ((lsb <= 31) && cond.IsNotNever() && !rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00003226 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC()) ||
3227 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08003228 uint32_t msb = lsb + width - 1;
3229 EmitA32(0x07c00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3230 rn.GetCode() | (lsb << 7) | (msb << 16));
3231 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003232 }
3233 }
Vincent Belliard609821f2017-02-08 14:17:25 -08003234 Delegate(kBfi, &Assembler::bfi, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003235}
3236
3237void Assembler::bic(Condition cond,
3238 EncodingSize size,
3239 Register rd,
3240 Register rn,
3241 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003243 CheckIT(cond);
3244 if (operand.IsImmediate()) {
3245 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003246 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003247 ImmediateT32 immediate_t32(imm);
3248 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003249 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3250 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003251 EmitT32_32(0xf0200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3252 (immediate_t32.GetEncodingValue() & 0xff) |
3253 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3254 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3255 AdvanceIT();
3256 return;
3257 }
3258 } else {
3259 ImmediateA32 immediate_a32(imm);
3260 // BIC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3261 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3262 EmitA32(0x03c00000U | (cond.GetCondition() << 28) |
3263 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3264 immediate_a32.GetEncodingValue());
3265 return;
3266 }
3267 }
3268 }
3269 if (operand.IsImmediateShiftedRegister()) {
3270 Register rm = operand.GetBaseRegister();
3271 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003272 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003273 // BIC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3274 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3275 rm.IsLow()) {
3276 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3277 AdvanceIT();
3278 return;
3279 }
3280 }
3281 }
3282 Shift shift = operand.GetShift();
3283 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003285 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003286 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3287 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003288 uint32_t amount_ = amount % 32;
3289 EmitT32_32(0xea200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3290 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3291 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3292 AdvanceIT();
3293 return;
3294 }
3295 } else {
3296 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3297 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3298 uint32_t amount_ = amount % 32;
3299 EmitA32(0x01c00000U | (cond.GetCondition() << 28) |
3300 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3301 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3302 return;
3303 }
3304 }
3305 }
3306 if (operand.IsRegisterShiftedRegister()) {
3307 Register rm = operand.GetBaseRegister();
3308 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003309 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003310 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003311 // BIC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00003312 if (cond.IsNotNever() &&
3313 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3314 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003315 EmitA32(0x01c00010U | (cond.GetCondition() << 28) |
3316 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003317 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003318 return;
3319 }
3320 }
3321 }
3322 Delegate(kBic, &Assembler::bic, cond, size, rd, rn, operand);
3323}
3324
3325void Assembler::bics(Condition cond,
3326 EncodingSize size,
3327 Register rd,
3328 Register rn,
3329 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003330 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003331 CheckIT(cond);
3332 if (operand.IsImmediate()) {
3333 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003334 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003335 ImmediateT32 immediate_t32(imm);
3336 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003337 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3338 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003339 EmitT32_32(0xf0300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3340 (immediate_t32.GetEncodingValue() & 0xff) |
3341 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3342 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3343 AdvanceIT();
3344 return;
3345 }
3346 } else {
3347 ImmediateA32 immediate_a32(imm);
3348 // BICS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
3349 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3350 EmitA32(0x03d00000U | (cond.GetCondition() << 28) |
3351 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
3352 immediate_a32.GetEncodingValue());
3353 return;
3354 }
3355 }
3356 }
3357 if (operand.IsImmediateShiftedRegister()) {
3358 Register rm = operand.GetBaseRegister();
3359 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003360 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003361 // BICS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
3362 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
3363 rm.IsLow()) {
3364 EmitT32_16(0x4380 | rd.GetCode() | (rm.GetCode() << 3));
3365 AdvanceIT();
3366 return;
3367 }
3368 }
3369 }
3370 Shift shift = operand.GetShift();
3371 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003372 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003373 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003374 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3375 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003376 uint32_t amount_ = amount % 32;
3377 EmitT32_32(0xea300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
3378 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
3379 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3380 AdvanceIT();
3381 return;
3382 }
3383 } else {
3384 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
3385 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3386 uint32_t amount_ = amount % 32;
3387 EmitA32(0x01d00000U | (cond.GetCondition() << 28) |
3388 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
3389 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3390 return;
3391 }
3392 }
3393 }
3394 if (operand.IsRegisterShiftedRegister()) {
3395 Register rm = operand.GetBaseRegister();
3396 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003397 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003398 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003399 // BICS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00003400 if (cond.IsNotNever() &&
3401 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
3402 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003403 EmitA32(0x01d00010U | (cond.GetCondition() << 28) |
3404 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003405 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003406 return;
3407 }
3408 }
3409 }
3410 Delegate(kBics, &Assembler::bics, cond, size, rd, rn, operand);
3411}
3412
3413void Assembler::bkpt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003414 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003415 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003416 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003417 // BKPT{<q>} {#}<imm> ; T1
3418 if ((imm <= 255)) {
3419 EmitT32_16(0xbe00 | imm);
3420 AdvanceIT();
3421 return;
3422 }
3423 } else {
3424 // BKPT{<q>} {#}<imm> ; A1
3425 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
3426 EmitA32(0x01200070U | (cond.GetCondition() << 28) | (imm & 0xf) |
3427 ((imm & 0xfff0) << 4));
3428 return;
3429 }
3430 }
3431 Delegate(kBkpt, &Assembler::bkpt, cond, imm);
3432}
3433
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003434void Assembler::bl(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003435 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003436 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003437 Location::Offset offset =
3438 location->IsBound()
3439 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003440 (GetCursorOffset() + GetArchitectureStatePCOffset())
3441 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003442 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003443 // BL{<c>}{<q>} <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003444 if (((location->IsBound() && (offset >= -16777216) &&
3445 (offset <= 16777214) && ((offset & 0x1) == 0)) ||
3446 !location->IsBound()) &&
Pierre Langloisdc626f32017-02-15 13:31:28 +00003447 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003448 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003449 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003450 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003451 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003452 Location::Offset pc,
3453 const Location* location) const VIXL_OVERRIDE {
3454 pc += kT32PcDelta;
3455 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003456 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777214) &&
3457 ((offset & 0x1) == 0));
3458 int32_t target = offset >> 1;
3459 uint32_t S = target & (1 << 23);
3460 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 21);
3461 return instr | (target & 0x7ff) | ((target & 0x1ff800) << 5) |
3462 ((target & 0x200000) >> 10) | ((target & 0x400000) >> 9) |
3463 ((target & 0x800000) << 3);
3464 }
3465 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003466 EmitT32_32(Link(0xf000d000U, location, immop, &kT32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003467 AdvanceIT();
3468 return;
3469 }
3470 } else {
3471 // BL{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003472 if (((location->IsBound() && (offset >= -33554432) &&
3473 (offset <= 33554428) && ((offset & 0x3) == 0)) ||
3474 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01003475 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003476 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003477 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003478 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003479 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003480 Location::Offset pc,
3481 const Location* location) const VIXL_OVERRIDE {
3482 pc += kA32PcDelta;
3483 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003484 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554428) &&
3485 ((offset & 0x3) == 0));
3486 const int32_t target = offset >> 2;
3487 return instr | (target & 0xffffff);
3488 }
3489 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003490 EmitA32(Link(0x0b000000U | (cond.GetCondition() << 28),
3491 location,
3492 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07003493 &kA32BranchInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003494 return;
3495 }
3496 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003497 Delegate(kBl, &Assembler::bl, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003498}
3499
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003500bool Assembler::bl_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003501 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003502 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003503 VIXL_ASSERT(!location->IsBound());
3504 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003505 if (IsUsingT32()) {
3506 // BL{<c>}{<q>} <label> ; T1
3507 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003508 *info = &kT32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003509 return true;
3510 }
3511 } else {
3512 // BL{<c>}{<q>} <label> ; A1
3513 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003514 *info = &kA32BranchInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003515 return true;
3516 }
3517 }
3518 return false;
3519}
3520
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003521void Assembler::blx(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003522 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003523 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003524 Location::Offset offset =
3525 location->IsBound()
3526 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003527 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
3528 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003529 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003530 // BLX{<c>}{<q>} <label> ; T2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003531 if (((location->IsBound() && (offset >= -16777216) &&
3532 (offset <= 16777212) && ((offset & 0x3) == 0)) ||
3533 !location->IsBound()) &&
Pierre Langloisdc626f32017-02-15 13:31:28 +00003534 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003535 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003536 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003537 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003538 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003539 Location::Offset pc,
3540 const Location* location) const VIXL_OVERRIDE {
3541 pc += kT32PcDelta;
3542 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003543 VIXL_ASSERT((offset >= -16777216) && (offset <= 16777212) &&
3544 ((offset & 0x3) == 0));
3545 int32_t target = offset >> 2;
3546 uint32_t S = target & (1 << 22);
3547 target ^= ((S >> 1) | (S >> 2)) ^ (3 << 20);
3548 return instr | ((target & 0x3ff) << 1) | ((target & 0xffc00) << 6) |
3549 ((target & 0x100000) >> 9) | ((target & 0x200000) >> 8) |
3550 ((target & 0x400000) << 4);
3551 }
3552 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003553 EmitT32_32(Link(0xf000c000U, location, immop, &kT32BlxInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003554 AdvanceIT();
3555 return;
3556 }
3557 } else {
3558 // BLX{<c>}{<q>} <label> ; A2
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003559 if (((location->IsBound() && (offset >= -33554432) &&
3560 (offset <= 33554430) && ((offset & 0x1) == 0)) ||
3561 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003562 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003563 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003564 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003565 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003566 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003567 Location::Offset pc,
3568 const Location* location) const
3569 VIXL_OVERRIDE {
3570 pc += kA32PcDelta;
3571 Location::Offset offset =
3572 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003573 VIXL_ASSERT((offset >= -33554432) && (offset <= 33554430) &&
3574 ((offset & 0x1) == 0));
3575 const int32_t target = offset >> 1;
3576 return instr | ((target & 0x1) << 24) | ((target & 0x1fffffe) >> 1);
3577 }
3578 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003579 EmitA32(Link(0xfa000000U, location, immop, &kA32BlxInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003580 return;
3581 }
3582 }
3583 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003584 Delegate(kBlx, &Assembler::blx, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003585}
3586
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003587bool Assembler::blx_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003588 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003589 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003590 VIXL_ASSERT(!location->IsBound());
3591 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003592 USE(cond);
3593 if (IsUsingT32()) {
3594 // BLX{<c>}{<q>} <label> ; T2
3595 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003596 *info = &kT32BlxInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003597 return true;
3598 }
3599 } else {
3600 // BLX{<c>}{<q>} <label> ; A2
3601 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07003602 *info = &kA32BlxInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003603 return true;
3604 }
3605 }
3606 return false;
3607}
3608
Alexandre Ramesd3832962016-07-04 15:03:43 +01003609void Assembler::blx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003610 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003611 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003612 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003613 // BLX{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003614 if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3615 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003616 EmitT32_16(0x4780 | (rm.GetCode() << 3));
3617 AdvanceIT();
3618 return;
3619 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003620 } else {
3621 // BLX{<c>}{<q>} <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003622 if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003623 EmitA32(0x012fff30U | (cond.GetCondition() << 28) | rm.GetCode());
3624 return;
3625 }
3626 }
3627 Delegate(kBlx, &Assembler::blx, cond, rm);
3628}
3629
3630void Assembler::bx(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003631 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003632 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003633 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003634 // BX{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003635 if ((OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
3636 EmitT32_16(0x4700 | (rm.GetCode() << 3));
3637 AdvanceIT();
3638 return;
3639 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003640 } else {
3641 // BX{<c>}{<q>} <Rm> ; A1
3642 if (cond.IsNotNever()) {
3643 EmitA32(0x012fff10U | (cond.GetCondition() << 28) | rm.GetCode());
3644 return;
3645 }
3646 }
3647 Delegate(kBx, &Assembler::bx, cond, rm);
3648}
3649
3650void Assembler::bxj(Condition cond, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003651 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003652 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003653 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003654 // BXJ{<c>}{<q>} <Rm> ; T1
Pierre Langloisdc626f32017-02-15 13:31:28 +00003655 if (((!rm.IsPC() && OutsideITBlockAndAlOrLast(cond)) ||
3656 AllowUnpredictable())) {
Pierre Langlois960d28b2017-02-15 13:06:01 +00003657 EmitT32_32(0xf3c08f00U | (rm.GetCode() << 16));
3658 AdvanceIT();
3659 return;
3660 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003661 } else {
3662 // BXJ{<c>}{<q>} <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003663 if (cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003664 EmitA32(0x012fff20U | (cond.GetCondition() << 28) | rm.GetCode());
3665 return;
3666 }
3667 }
3668 Delegate(kBxj, &Assembler::bxj, cond, rm);
3669}
3670
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003671void Assembler::cbnz(Register rn, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003672 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003673 CheckIT(al);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003674 Location::Offset offset =
3675 location->IsBound()
3676 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003677 (GetCursorOffset() + GetArchitectureStatePCOffset())
3678 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003679 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003680 // CBNZ{<q>} <Rn>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003681 if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3682 (offset <= 126) && ((offset & 0x1) == 0)) ||
3683 !location->IsBound())) {
3684 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003685 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003686 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003687 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003688 Location::Offset pc,
3689 const Location* location) const VIXL_OVERRIDE {
3690 pc += kT32PcDelta;
3691 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003692 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3693 ((offset & 0x1) == 0));
3694 const int32_t target = offset >> 1;
3695 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3696 }
3697 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003698 EmitT32_16(Link(0xb900 | rn.GetCode(), location, immop, &kT16CbzInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003699 AdvanceIT();
3700 return;
3701 }
3702 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003703 Delegate(kCbnz, &Assembler::cbnz, rn, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003704}
3705
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003706bool Assembler::cbnz_info(Register rn,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003707 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003708 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003709 VIXL_ASSERT(!location->IsBound());
3710 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003711 if (IsUsingT32()) {
3712 // CBNZ{<q>} <Rn>, <label> ; T1
3713 if (rn.IsLow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003714 *info = &kT16CbzInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003715 return true;
3716 }
3717 }
3718 return false;
3719}
3720
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003721void Assembler::cbz(Register rn, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003722 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003723 CheckIT(al);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003724 Location::Offset offset =
3725 location->IsBound()
3726 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01003727 (GetCursorOffset() + GetArchitectureStatePCOffset())
3728 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003729 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003730 // CBZ{<q>} <Rn>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003731 if (rn.IsLow() && ((location->IsBound() && (offset >= 0) &&
3732 (offset <= 126) && ((offset & 0x1) == 0)) ||
3733 !location->IsBound())) {
3734 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003735 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003736 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00003737 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003738 Location::Offset pc,
3739 const Location* location) const VIXL_OVERRIDE {
3740 pc += kT32PcDelta;
3741 Location::Offset offset = location->GetLocation() - pc;
Alexandre Ramesd3832962016-07-04 15:03:43 +01003742 VIXL_ASSERT((offset >= 0) && (offset <= 126) &&
3743 ((offset & 0x1) == 0));
3744 const int32_t target = offset >> 1;
3745 return instr | ((target & 0x1f) << 3) | ((target & 0x20) << 4);
3746 }
3747 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07003748 EmitT32_16(Link(0xb100 | rn.GetCode(), location, immop, &kT16CbzInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003749 AdvanceIT();
3750 return;
3751 }
3752 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003753 Delegate(kCbz, &Assembler::cbz, rn, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01003754}
3755
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003756bool Assembler::cbz_info(Register rn,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003757 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003758 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01003759 VIXL_ASSERT(!location->IsBound());
3760 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003761 if (IsUsingT32()) {
3762 // CBZ{<q>} <Rn>, <label> ; T1
3763 if (rn.IsLow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07003764 *info = &kT16CbzInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01003765 return true;
3766 }
3767 }
3768 return false;
3769}
3770
Alexandre Ramesd3832962016-07-04 15:03:43 +01003771void Assembler::clrex(Condition cond) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003772 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003773 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003774 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003775 // CLREX{<c>}{<q>} ; T1
3776 EmitT32_32(0xf3bf8f2fU);
3777 AdvanceIT();
3778 return;
3779 } else {
3780 // CLREX{<c>}{<q>} ; A1
3781 if (cond.Is(al)) {
3782 EmitA32(0xf57ff01fU);
3783 return;
3784 }
3785 }
3786 Delegate(kClrex, &Assembler::clrex, cond);
3787}
3788
3789void Assembler::clz(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003790 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003791 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003792 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003793 // CLZ{<c>}{<q>} <Rd>, <Rm> ; T1
Georgia Kouvelie99f34d2016-12-21 17:00:29 +00003794 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
3795 EmitT32_32(0xfab0f080U | (rd.GetCode() << 8) | rm.GetCode() |
3796 (rm.GetCode() << 16));
3797 AdvanceIT();
3798 return;
3799 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01003800 } else {
3801 // CLZ{<c>}{<q>} <Rd>, <Rm> ; A1
Georgia Kouvelie99f34d2016-12-21 17:00:29 +00003802 if (cond.IsNotNever() &&
3803 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003804 EmitA32(0x016f0f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
3805 rm.GetCode());
3806 return;
3807 }
3808 }
3809 Delegate(kClz, &Assembler::clz, cond, rd, rm);
3810}
3811
3812void Assembler::cmn(Condition cond,
3813 EncodingSize size,
3814 Register rn,
3815 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003816 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003817 CheckIT(cond);
3818 if (operand.IsImmediate()) {
3819 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003820 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003821 ImmediateT32 immediate_t32(imm);
3822 // CMN{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003823 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3824 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003825 EmitT32_32(0xf1100f00U | (rn.GetCode() << 16) |
3826 (immediate_t32.GetEncodingValue() & 0xff) |
3827 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3828 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3829 AdvanceIT();
3830 return;
3831 }
3832 } else {
3833 ImmediateA32 immediate_a32(imm);
3834 // CMN{<c>}{<q>} <Rn>, #<const> ; A1
3835 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3836 EmitA32(0x03700000U | (cond.GetCondition() << 28) |
3837 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3838 return;
3839 }
3840 }
3841 }
3842 if (operand.IsImmediateShiftedRegister()) {
3843 Register rm = operand.GetBaseRegister();
3844 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003845 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003846 // CMN{<c>}{<q>} <Rn>, <Rm> ; T1
3847 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3848 EmitT32_16(0x42c0 | rn.GetCode() | (rm.GetCode() << 3));
3849 AdvanceIT();
3850 return;
3851 }
3852 }
3853 }
3854 Shift shift = operand.GetShift();
3855 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003856 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003857 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003858 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3859 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003860 uint32_t amount_ = amount % 32;
3861 EmitT32_32(0xeb100f00U | (rn.GetCode() << 16) | rm.GetCode() |
3862 (operand.GetTypeEncodingValue() << 4) |
3863 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3864 AdvanceIT();
3865 return;
3866 }
3867 } else {
3868 // CMN{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3869 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3870 uint32_t amount_ = amount % 32;
3871 EmitA32(0x01700000U | (cond.GetCondition() << 28) |
3872 (rn.GetCode() << 16) | rm.GetCode() |
3873 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3874 return;
3875 }
3876 }
3877 }
3878 if (operand.IsRegisterShiftedRegister()) {
3879 Register rm = operand.GetBaseRegister();
3880 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003881 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003882 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003883 // CMN{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003884 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00003885 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003886 EmitA32(0x01700010U | (cond.GetCondition() << 28) |
3887 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003888 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003889 return;
3890 }
3891 }
3892 }
3893 Delegate(kCmn, &Assembler::cmn, cond, size, rn, operand);
3894}
3895
3896void Assembler::cmp(Condition cond,
3897 EncodingSize size,
3898 Register rn,
3899 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003900 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003901 CheckIT(cond);
3902 if (operand.IsImmediate()) {
3903 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003904 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003905 ImmediateT32 immediate_t32(imm);
3906 // CMP{<c>}{<q>} <Rn>, #<imm8> ; T1
3907 if (!size.IsWide() && rn.IsLow() && (imm <= 255)) {
3908 EmitT32_16(0x2800 | (rn.GetCode() << 8) | imm);
3909 AdvanceIT();
3910 return;
3911 }
3912 // CMP{<c>}{<q>} <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003913 if (!size.IsNarrow() && immediate_t32.IsValid() &&
3914 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003915 EmitT32_32(0xf1b00f00U | (rn.GetCode() << 16) |
3916 (immediate_t32.GetEncodingValue() & 0xff) |
3917 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
3918 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
3919 AdvanceIT();
3920 return;
3921 }
3922 } else {
3923 ImmediateA32 immediate_a32(imm);
3924 // CMP{<c>}{<q>} <Rn>, #<const> ; A1
3925 if (immediate_a32.IsValid() && cond.IsNotNever()) {
3926 EmitA32(0x03500000U | (cond.GetCondition() << 28) |
3927 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
3928 return;
3929 }
3930 }
3931 }
3932 if (operand.IsImmediateShiftedRegister()) {
3933 Register rm = operand.GetBaseRegister();
3934 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003936 // CMP{<c>}{<q>} <Rn>, <Rm> ; T1
3937 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
3938 EmitT32_16(0x4280 | rn.GetCode() | (rm.GetCode() << 3));
3939 AdvanceIT();
3940 return;
3941 }
3942 // CMP{<c>}{<q>} <Rn>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00003943 if (!size.IsWide() &&
3944 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003945 EmitT32_16(0x4500 | (rn.GetCode() & 0x7) |
3946 ((rn.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
3947 AdvanceIT();
3948 return;
3949 }
3950 }
3951 }
3952 Shift shift = operand.GetShift();
3953 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003954 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003955 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> #<amount> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +00003956 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
3957 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003958 uint32_t amount_ = amount % 32;
3959 EmitT32_32(0xebb00f00U | (rn.GetCode() << 16) | rm.GetCode() |
3960 (operand.GetTypeEncodingValue() << 4) |
3961 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
3962 AdvanceIT();
3963 return;
3964 }
3965 } else {
3966 // CMP{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
3967 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
3968 uint32_t amount_ = amount % 32;
3969 EmitA32(0x01500000U | (cond.GetCondition() << 28) |
3970 (rn.GetCode() << 16) | rm.GetCode() |
3971 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
3972 return;
3973 }
3974 }
3975 }
3976 if (operand.IsRegisterShiftedRegister()) {
3977 Register rm = operand.GetBaseRegister();
3978 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00003979 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003980 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003981 // CMP{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003982 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00003983 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003984 EmitA32(0x01500010U | (cond.GetCondition() << 28) |
3985 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00003986 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01003987 return;
3988 }
3989 }
3990 }
3991 Delegate(kCmp, &Assembler::cmp, cond, size, rn, operand);
3992}
3993
3994void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07003995 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01003996 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01003997 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01003998 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00003999 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4000 EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4001 rm.GetCode());
4002 AdvanceIT();
4003 return;
4004 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004005 } else {
4006 // CRC32B{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004007 if ((cond.Is(al) || AllowUnpredictable()) &&
4008 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004009 EmitA32(0x01000040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4010 (rn.GetCode() << 16) | rm.GetCode());
4011 return;
4012 }
4013 }
4014 Delegate(kCrc32b, &Assembler::crc32b, cond, rd, rn, rm);
4015}
4016
4017void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004018 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004019 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004020 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004021 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004022 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4023 EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4024 rm.GetCode());
4025 AdvanceIT();
4026 return;
4027 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004028 } else {
4029 // CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004030 if ((cond.Is(al) || AllowUnpredictable()) &&
4031 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004032 EmitA32(0x01000240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4033 (rn.GetCode() << 16) | rm.GetCode());
4034 return;
4035 }
4036 }
4037 Delegate(kCrc32cb, &Assembler::crc32cb, cond, rd, rn, rm);
4038}
4039
4040void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004041 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004042 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004043 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004044 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004045 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4046 EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4047 rm.GetCode());
4048 AdvanceIT();
4049 return;
4050 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004051 } else {
4052 // CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004053 if ((cond.Is(al) || AllowUnpredictable()) &&
4054 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004055 EmitA32(0x01200240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4056 (rn.GetCode() << 16) | rm.GetCode());
4057 return;
4058 }
4059 }
4060 Delegate(kCrc32ch, &Assembler::crc32ch, cond, rd, rn, rm);
4061}
4062
4063void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004064 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004065 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004066 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004067 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004068 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4069 EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4070 rm.GetCode());
4071 AdvanceIT();
4072 return;
4073 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004074 } else {
4075 // CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004076 if ((cond.Is(al) || AllowUnpredictable()) &&
4077 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004078 EmitA32(0x01400240U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4079 (rn.GetCode() << 16) | rm.GetCode());
4080 return;
4081 }
4082 }
4083 Delegate(kCrc32cw, &Assembler::crc32cw, cond, rd, rn, rm);
4084}
4085
4086void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004087 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004088 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004089 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004090 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004091 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4092 EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4093 rm.GetCode());
4094 AdvanceIT();
4095 return;
4096 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004097 } else {
4098 // CRC32H{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004099 if ((cond.Is(al) || AllowUnpredictable()) &&
4100 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004101 EmitA32(0x01200040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4102 (rn.GetCode() << 16) | rm.GetCode());
4103 return;
4104 }
4105 }
4106 Delegate(kCrc32h, &Assembler::crc32h, cond, rd, rn, rm);
4107}
4108
4109void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004110 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004111 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004112 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004113 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004114 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
4115 EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4116 rm.GetCode());
4117 AdvanceIT();
4118 return;
4119 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01004120 } else {
4121 // CRC32W{<q>} <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004122 if ((cond.Is(al) || AllowUnpredictable()) &&
4123 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004124 EmitA32(0x01400040U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
4125 (rn.GetCode() << 16) | rm.GetCode());
4126 return;
4127 }
4128 }
4129 Delegate(kCrc32w, &Assembler::crc32w, cond, rd, rn, rm);
4130}
4131
4132void Assembler::dmb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004133 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004134 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004135 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004136 // DMB{<c>}{<q>} {<option>} ; T1
4137 EmitT32_32(0xf3bf8f50U | option.GetType());
4138 AdvanceIT();
4139 return;
4140 } else {
4141 // DMB{<c>}{<q>} {<option>} ; A1
4142 if (cond.Is(al)) {
4143 EmitA32(0xf57ff050U | option.GetType());
4144 return;
4145 }
4146 }
4147 Delegate(kDmb, &Assembler::dmb, cond, option);
4148}
4149
4150void Assembler::dsb(Condition cond, MemoryBarrier option) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004151 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004152 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004153 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004154 // DSB{<c>}{<q>} {<option>} ; T1
4155 EmitT32_32(0xf3bf8f40U | option.GetType());
4156 AdvanceIT();
4157 return;
4158 } else {
4159 // DSB{<c>}{<q>} {<option>} ; A1
4160 if (cond.Is(al)) {
4161 EmitA32(0xf57ff040U | option.GetType());
4162 return;
4163 }
4164 }
4165 Delegate(kDsb, &Assembler::dsb, cond, option);
4166}
4167
4168void Assembler::eor(Condition cond,
4169 EncodingSize size,
4170 Register rd,
4171 Register rn,
4172 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004173 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004174 CheckIT(cond);
4175 if (operand.IsImmediate()) {
4176 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004177 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004178 ImmediateT32 immediate_t32(imm);
4179 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004180 if (!size.IsNarrow() && immediate_t32.IsValid() &&
4181 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004182 EmitT32_32(0xf0800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4183 (immediate_t32.GetEncodingValue() & 0xff) |
4184 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4185 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4186 AdvanceIT();
4187 return;
4188 }
4189 } else {
4190 ImmediateA32 immediate_a32(imm);
4191 // EOR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4192 if (immediate_a32.IsValid() && cond.IsNotNever()) {
4193 EmitA32(0x02200000U | (cond.GetCondition() << 28) |
4194 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4195 immediate_a32.GetEncodingValue());
4196 return;
4197 }
4198 }
4199 }
4200 if (operand.IsImmediateShiftedRegister()) {
4201 Register rm = operand.GetBaseRegister();
4202 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004203 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004204 // EOR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4205 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4206 rm.IsLow()) {
4207 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4208 AdvanceIT();
4209 return;
4210 }
4211 }
4212 }
4213 Shift shift = operand.GetShift();
4214 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004215 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004216 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004217 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
4218 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004219 uint32_t amount_ = amount % 32;
4220 EmitT32_32(0xea800000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4221 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4222 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4223 AdvanceIT();
4224 return;
4225 }
4226 } else {
4227 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4228 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4229 uint32_t amount_ = amount % 32;
4230 EmitA32(0x00200000U | (cond.GetCondition() << 28) |
4231 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4232 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4233 return;
4234 }
4235 }
4236 }
4237 if (operand.IsRegisterShiftedRegister()) {
4238 Register rm = operand.GetBaseRegister();
4239 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00004240 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004241 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004242 // EOR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00004243 if (cond.IsNotNever() &&
4244 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4245 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004246 EmitA32(0x00200010U | (cond.GetCondition() << 28) |
4247 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00004248 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004249 return;
4250 }
4251 }
4252 }
4253 Delegate(kEor, &Assembler::eor, cond, size, rd, rn, operand);
4254}
4255
4256void Assembler::eors(Condition cond,
4257 EncodingSize size,
4258 Register rd,
4259 Register rn,
4260 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004261 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004262 CheckIT(cond);
4263 if (operand.IsImmediate()) {
4264 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004265 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004266 ImmediateT32 immediate_t32(imm);
4267 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004268 if (!size.IsNarrow() && immediate_t32.IsValid() && !rd.Is(pc) &&
4269 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004270 EmitT32_32(0xf0900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4271 (immediate_t32.GetEncodingValue() & 0xff) |
4272 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
4273 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
4274 AdvanceIT();
4275 return;
4276 }
4277 } else {
4278 ImmediateA32 immediate_a32(imm);
4279 // EORS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
4280 if (immediate_a32.IsValid() && cond.IsNotNever()) {
4281 EmitA32(0x02300000U | (cond.GetCondition() << 28) |
4282 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
4283 immediate_a32.GetEncodingValue());
4284 return;
4285 }
4286 }
4287 }
4288 if (operand.IsImmediateShiftedRegister()) {
4289 Register rm = operand.GetBaseRegister();
4290 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004291 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004292 // EORS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
4293 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
4294 rm.IsLow()) {
4295 EmitT32_16(0x4040 | rd.GetCode() | (rm.GetCode() << 3));
4296 AdvanceIT();
4297 return;
4298 }
4299 }
4300 }
4301 Shift shift = operand.GetShift();
4302 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004303 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004304 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004305 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rd.Is(pc) &&
4306 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004307 uint32_t amount_ = amount % 32;
4308 EmitT32_32(0xea900000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
4309 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
4310 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
4311 AdvanceIT();
4312 return;
4313 }
4314 } else {
4315 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
4316 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
4317 uint32_t amount_ = amount % 32;
4318 EmitA32(0x00300000U | (cond.GetCondition() << 28) |
4319 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
4320 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
4321 return;
4322 }
4323 }
4324 }
4325 if (operand.IsRegisterShiftedRegister()) {
4326 Register rm = operand.GetBaseRegister();
4327 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00004328 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004329 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004330 // EORS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00004331 if (cond.IsNotNever() &&
4332 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
4333 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004334 EmitA32(0x00300010U | (cond.GetCondition() << 28) |
4335 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00004336 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01004337 return;
4338 }
4339 }
4340 }
4341 Delegate(kEors, &Assembler::eors, cond, size, rd, rn, operand);
4342}
4343
4344void Assembler::fldmdbx(Condition cond,
4345 Register rn,
4346 WriteBack write_back,
4347 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004349 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004350 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004351 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4352 if (write_back.DoesWriteBack() &&
4353 (((dreglist.GetLength() <= 16) &&
4354 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4355 AllowUnpredictable())) {
4356 const DRegister& dreg = dreglist.GetFirstDRegister();
4357 unsigned len = dreglist.GetLength() * 2;
4358 EmitT32_32(0xed300b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4359 (len & 0xff));
4360 AdvanceIT();
4361 return;
4362 }
4363 } else {
4364 // FLDMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4365 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4366 (((dreglist.GetLength() <= 16) &&
4367 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4368 AllowUnpredictable())) {
4369 const DRegister& dreg = dreglist.GetFirstDRegister();
4370 unsigned len = dreglist.GetLength() * 2;
4371 EmitA32(0x0d300b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4372 dreg.Encode(22, 12) | (len & 0xff));
4373 return;
4374 }
4375 }
4376 Delegate(kFldmdbx, &Assembler::fldmdbx, cond, rn, write_back, dreglist);
4377}
4378
4379void Assembler::fldmiax(Condition cond,
4380 Register rn,
4381 WriteBack write_back,
4382 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004383 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004384 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004385 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004386 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4387 if ((((dreglist.GetLength() <= 16) &&
4388 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4389 AllowUnpredictable())) {
4390 const DRegister& dreg = dreglist.GetFirstDRegister();
4391 unsigned len = dreglist.GetLength() * 2;
4392 EmitT32_32(0xec900b01U | (rn.GetCode() << 16) |
4393 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4394 (len & 0xff));
4395 AdvanceIT();
4396 return;
4397 }
4398 } else {
4399 // FLDMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4400 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4401 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4402 AllowUnpredictable())) {
4403 const DRegister& dreg = dreglist.GetFirstDRegister();
4404 unsigned len = dreglist.GetLength() * 2;
4405 EmitA32(0x0c900b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4406 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4407 (len & 0xff));
4408 return;
4409 }
4410 }
4411 Delegate(kFldmiax, &Assembler::fldmiax, cond, rn, write_back, dreglist);
4412}
4413
4414void Assembler::fstmdbx(Condition cond,
4415 Register rn,
4416 WriteBack write_back,
4417 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004418 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004419 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004420 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004421 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; T1
4422 if (write_back.DoesWriteBack() &&
4423 (((dreglist.GetLength() <= 16) &&
4424 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4425 AllowUnpredictable())) {
4426 const DRegister& dreg = dreglist.GetFirstDRegister();
4427 unsigned len = dreglist.GetLength() * 2;
4428 EmitT32_32(0xed200b01U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
4429 (len & 0xff));
4430 AdvanceIT();
4431 return;
4432 }
4433 } else {
4434 // FSTMDBX{<c>}{<q>} <Rn>!, <dreglist> ; A1
4435 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
4436 (((dreglist.GetLength() <= 16) &&
4437 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4438 AllowUnpredictable())) {
4439 const DRegister& dreg = dreglist.GetFirstDRegister();
4440 unsigned len = dreglist.GetLength() * 2;
4441 EmitA32(0x0d200b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4442 dreg.Encode(22, 12) | (len & 0xff));
4443 return;
4444 }
4445 }
4446 Delegate(kFstmdbx, &Assembler::fstmdbx, cond, rn, write_back, dreglist);
4447}
4448
4449void Assembler::fstmiax(Condition cond,
4450 Register rn,
4451 WriteBack write_back,
4452 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004453 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004454 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004455 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004456 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; T1
4457 if ((((dreglist.GetLength() <= 16) &&
4458 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4459 AllowUnpredictable())) {
4460 const DRegister& dreg = dreglist.GetFirstDRegister();
4461 unsigned len = dreglist.GetLength() * 2;
4462 EmitT32_32(0xec800b01U | (rn.GetCode() << 16) |
4463 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4464 (len & 0xff));
4465 AdvanceIT();
4466 return;
4467 }
4468 } else {
4469 // FSTMIAX{<c>}{<q>} <Rn>{!}, <dreglist> ; A1
4470 if (cond.IsNotNever() && (((dreglist.GetLength() <= 16) &&
4471 (dreglist.GetLastDRegister().GetCode() < 16)) ||
4472 AllowUnpredictable())) {
4473 const DRegister& dreg = dreglist.GetFirstDRegister();
4474 unsigned len = dreglist.GetLength() * 2;
4475 EmitA32(0x0c800b01U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4476 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
4477 (len & 0xff));
4478 return;
4479 }
4480 }
4481 Delegate(kFstmiax, &Assembler::fstmiax, cond, rn, write_back, dreglist);
4482}
4483
4484void Assembler::hlt(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004485 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004486 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004487 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004488 // HLT{<q>} {#}<imm> ; T1
4489 if ((imm <= 63)) {
4490 EmitT32_16(0xba80 | imm);
4491 AdvanceIT();
4492 return;
4493 }
4494 } else {
4495 // HLT{<q>} {#}<imm> ; A1
4496 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4497 EmitA32(0x01000070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4498 ((imm & 0xfff0) << 4));
4499 return;
4500 }
4501 }
4502 Delegate(kHlt, &Assembler::hlt, cond, imm);
4503}
4504
4505void Assembler::hvc(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 // HVC{<q>} {#}<imm16> ; T1
4510 if ((imm <= 65535)) {
4511 EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
4512 AdvanceIT();
4513 return;
4514 }
4515 } else {
4516 // HVC{<q>} {#}<imm16> ; A1
4517 if ((imm <= 65535) && (cond.Is(al) || AllowUnpredictable())) {
4518 EmitA32(0x01400070U | (cond.GetCondition() << 28) | (imm & 0xf) |
4519 ((imm & 0xfff0) << 4));
4520 return;
4521 }
4522 }
4523 Delegate(kHvc, &Assembler::hvc, cond, imm);
4524}
4525
4526void Assembler::isb(Condition cond, MemoryBarrier option) {
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 // ISB{<c>}{<q>} {<option>} ; T1
4531 EmitT32_32(0xf3bf8f60U | option.GetType());
4532 AdvanceIT();
4533 return;
4534 } else {
4535 // ISB{<c>}{<q>} {<option>} ; A1
4536 if (cond.Is(al)) {
4537 EmitA32(0xf57ff060U | option.GetType());
4538 return;
4539 }
4540 }
4541 Delegate(kIsb, &Assembler::isb, cond, option);
4542}
4543
4544void Assembler::it(Condition cond, uint16_t mask) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004545 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004546 CheckNotIT();
4547 if (mask != 0) {
4548 if ((cond.GetCondition() & 0x1) != 0) {
4549 if ((mask & 0x1) != 0) {
4550 mask ^= 0xE;
4551 } else if ((mask & 0x2) != 0) {
4552 mask ^= 0xC;
4553 } else if ((mask & 0x4) != 0) {
4554 mask ^= 0x8;
4555 }
4556 }
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004557 if (IsUsingT32()) EmitT32_16(0xbf00 | (cond.GetCondition() << 4) | mask);
Alexandre Ramesd3832962016-07-04 15:03:43 +01004558 SetIT(cond, mask);
4559 return;
4560 }
4561 DelegateIt(cond, mask);
4562}
4563
4564void Assembler::lda(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004565 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004566 CheckIT(cond);
4567 if (operand.IsImmediateZero()) {
4568 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004569 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004570 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004571 if (operand.IsOffset() &&
4572 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004573 EmitT32_32(0xe8d00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4574 AdvanceIT();
4575 return;
4576 }
4577 } else {
4578 // LDA{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004579 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004580 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004581 EmitA32(0x01900c9fU | (cond.GetCondition() << 28) |
4582 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4583 return;
4584 }
4585 }
4586 }
4587 Delegate(kLda, &Assembler::lda, cond, rt, operand);
4588}
4589
4590void Assembler::ldab(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004591 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004592 CheckIT(cond);
4593 if (operand.IsImmediateZero()) {
4594 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004595 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004596 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004597 if (operand.IsOffset() &&
4598 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004599 EmitT32_32(0xe8d00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4600 AdvanceIT();
4601 return;
4602 }
4603 } else {
4604 // LDAB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004605 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004606 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004607 EmitA32(0x01d00c9fU | (cond.GetCondition() << 28) |
4608 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4609 return;
4610 }
4611 }
4612 }
4613 Delegate(kLdab, &Assembler::ldab, cond, rt, operand);
4614}
4615
4616void Assembler::ldaex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004617 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004618 CheckIT(cond);
4619 if (operand.IsImmediateZero()) {
4620 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004621 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004622 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004623 if (operand.IsOffset() &&
4624 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004625 EmitT32_32(0xe8d00fefU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4626 AdvanceIT();
4627 return;
4628 }
4629 } else {
4630 // LDAEX{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004631 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004632 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004633 EmitA32(0x01900e9fU | (cond.GetCondition() << 28) |
4634 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4635 return;
4636 }
4637 }
4638 }
4639 Delegate(kLdaex, &Assembler::ldaex, cond, rt, operand);
4640}
4641
4642void Assembler::ldaexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004643 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004644 CheckIT(cond);
4645 if (operand.IsImmediateZero()) {
4646 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004647 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004648 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004649 if (operand.IsOffset() &&
4650 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004651 EmitT32_32(0xe8d00fcfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4652 AdvanceIT();
4653 return;
4654 }
4655 } else {
4656 // LDAEXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004657 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004658 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004659 EmitA32(0x01d00e9fU | (cond.GetCondition() << 28) |
4660 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4661 return;
4662 }
4663 }
4664 }
4665 Delegate(kLdaexb, &Assembler::ldaexb, cond, rt, operand);
4666}
4667
4668void Assembler::ldaexd(Condition cond,
4669 Register rt,
4670 Register rt2,
4671 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004672 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004673 CheckIT(cond);
4674 if (operand.IsImmediateZero()) {
4675 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004676 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004677 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004678 if (operand.IsOffset() &&
4679 ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004680 EmitT32_32(0xe8d000ffU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
4681 (rn.GetCode() << 16));
4682 AdvanceIT();
4683 return;
4684 }
4685 } else {
4686 // LDAEXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
4687 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004688 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00004689 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01004690 AllowUnpredictable())) {
4691 EmitA32(0x01b00e9fU | (cond.GetCondition() << 28) |
4692 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4693 return;
4694 }
4695 }
4696 }
4697 Delegate(kLdaexd, &Assembler::ldaexd, cond, rt, rt2, operand);
4698}
4699
4700void Assembler::ldaexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004701 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004702 CheckIT(cond);
4703 if (operand.IsImmediateZero()) {
4704 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004705 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004706 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004707 if (operand.IsOffset() &&
4708 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004709 EmitT32_32(0xe8d00fdfU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4710 AdvanceIT();
4711 return;
4712 }
4713 } else {
4714 // LDAEXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004715 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004716 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004717 EmitA32(0x01f00e9fU | (cond.GetCondition() << 28) |
4718 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4719 return;
4720 }
4721 }
4722 }
4723 Delegate(kLdaexh, &Assembler::ldaexh, cond, rt, operand);
4724}
4725
4726void Assembler::ldah(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004727 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004728 CheckIT(cond);
4729 if (operand.IsImmediateZero()) {
4730 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004731 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004732 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004733 if (operand.IsOffset() &&
4734 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004735 EmitT32_32(0xe8d00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
4736 AdvanceIT();
4737 return;
4738 }
4739 } else {
4740 // LDAH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004741 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00004742 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004743 EmitA32(0x01f00c9fU | (cond.GetCondition() << 28) |
4744 (rt.GetCode() << 12) | (rn.GetCode() << 16));
4745 return;
4746 }
4747 }
4748 }
4749 Delegate(kLdah, &Assembler::ldah, cond, rt, operand);
4750}
4751
4752void Assembler::ldm(Condition cond,
4753 EncodingSize size,
4754 Register rn,
4755 WriteBack write_back,
4756 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004757 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004758 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004759 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004760 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T1
4761 if (!size.IsWide() && rn.IsLow() &&
4762 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4763 write_back.DoesWriteBack()) &&
4764 ((registers.GetList() & ~0xff) == 0)) {
4765 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4766 GetRegisterListEncoding(registers, 0, 8));
4767 AdvanceIT();
4768 return;
4769 }
4770 // LDM{<c>}{<q>} SP!, <registers> ; T1
4771 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
4772 ((registers.GetList() & ~0x80ff) == 0)) {
4773 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
4774 GetRegisterListEncoding(registers, 0, 8));
4775 AdvanceIT();
4776 return;
4777 }
4778 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004779 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4780 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004781 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4782 (write_back.GetWriteBackUint32() << 21) |
4783 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4784 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4785 GetRegisterListEncoding(registers, 0, 13));
4786 AdvanceIT();
4787 return;
4788 }
4789 } else {
4790 // LDM{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004791 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004792 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4793 (write_back.GetWriteBackUint32() << 21) |
4794 GetRegisterListEncoding(registers, 0, 16));
4795 return;
4796 }
4797 }
4798 Delegate(kLdm, &Assembler::ldm, cond, size, rn, write_back, registers);
4799}
4800
4801void Assembler::ldmda(Condition cond,
4802 Register rn,
4803 WriteBack write_back,
4804 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004805 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004806 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004807 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004808 // LDMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004809 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004810 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4811 (write_back.GetWriteBackUint32() << 21) |
4812 GetRegisterListEncoding(registers, 0, 16));
4813 return;
4814 }
4815 }
4816 Delegate(kLdmda, &Assembler::ldmda, cond, rn, write_back, registers);
4817}
4818
4819void Assembler::ldmdb(Condition cond,
4820 Register rn,
4821 WriteBack write_back,
4822 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004823 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004824 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004825 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004826 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004827 if (((registers.GetList() & ~0xdfff) == 0) &&
4828 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004829 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4830 (write_back.GetWriteBackUint32() << 21) |
4831 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4832 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4833 GetRegisterListEncoding(registers, 0, 13));
4834 AdvanceIT();
4835 return;
4836 }
4837 } else {
4838 // LDMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004839 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004840 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4841 (write_back.GetWriteBackUint32() << 21) |
4842 GetRegisterListEncoding(registers, 0, 16));
4843 return;
4844 }
4845 }
4846 Delegate(kLdmdb, &Assembler::ldmdb, cond, rn, write_back, registers);
4847}
4848
4849void Assembler::ldmea(Condition cond,
4850 Register rn,
4851 WriteBack write_back,
4852 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004853 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004854 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004855 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004856 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004857 if (((registers.GetList() & ~0xdfff) == 0) &&
4858 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004859 EmitT32_32(0xe9100000U | (rn.GetCode() << 16) |
4860 (write_back.GetWriteBackUint32() << 21) |
4861 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4862 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4863 GetRegisterListEncoding(registers, 0, 13));
4864 AdvanceIT();
4865 return;
4866 }
4867 } else {
4868 // LDMEA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004869 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004870 EmitA32(0x09100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4871 (write_back.GetWriteBackUint32() << 21) |
4872 GetRegisterListEncoding(registers, 0, 16));
4873 return;
4874 }
4875 }
4876 Delegate(kLdmea, &Assembler::ldmea, cond, rn, write_back, registers);
4877}
4878
4879void Assembler::ldmed(Condition cond,
4880 Register rn,
4881 WriteBack write_back,
4882 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004883 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004884 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004885 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004886 // LDMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004887 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004888 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4889 (write_back.GetWriteBackUint32() << 21) |
4890 GetRegisterListEncoding(registers, 0, 16));
4891 return;
4892 }
4893 }
4894 Delegate(kLdmed, &Assembler::ldmed, cond, rn, write_back, registers);
4895}
4896
4897void Assembler::ldmfa(Condition cond,
4898 Register rn,
4899 WriteBack write_back,
4900 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004901 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004902 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004903 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004904 // LDMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004905 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004906 EmitA32(0x08100000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4907 (write_back.GetWriteBackUint32() << 21) |
4908 GetRegisterListEncoding(registers, 0, 16));
4909 return;
4910 }
4911 }
4912 Delegate(kLdmfa, &Assembler::ldmfa, cond, rn, write_back, registers);
4913}
4914
4915void Assembler::ldmfd(Condition cond,
4916 EncodingSize size,
4917 Register rn,
4918 WriteBack write_back,
4919 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004920 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004921 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004922 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004923 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
4924 if (!size.IsWide() && rn.IsLow() &&
4925 (((registers.GetList() & (1 << rn.GetCode())) == 0) ==
4926 write_back.DoesWriteBack()) &&
4927 ((registers.GetList() & ~0xff) == 0)) {
4928 EmitT32_16(0xc800 | (rn.GetCode() << 8) |
4929 GetRegisterListEncoding(registers, 0, 8));
4930 AdvanceIT();
4931 return;
4932 }
4933 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00004934 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0) &&
4935 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004936 EmitT32_32(0xe8900000U | (rn.GetCode() << 16) |
4937 (write_back.GetWriteBackUint32() << 21) |
4938 (GetRegisterListEncoding(registers, 15, 1) << 15) |
4939 (GetRegisterListEncoding(registers, 14, 1) << 14) |
4940 GetRegisterListEncoding(registers, 0, 13));
4941 AdvanceIT();
4942 return;
4943 }
4944 } else {
4945 // LDMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004946 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004947 EmitA32(0x08900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4948 (write_back.GetWriteBackUint32() << 21) |
4949 GetRegisterListEncoding(registers, 0, 16));
4950 return;
4951 }
4952 }
4953 Delegate(kLdmfd, &Assembler::ldmfd, cond, size, rn, write_back, registers);
4954}
4955
4956void Assembler::ldmib(Condition cond,
4957 Register rn,
4958 WriteBack write_back,
4959 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004960 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004961 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004962 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004963 // LDMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00004964 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004965 EmitA32(0x09900000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
4966 (write_back.GetWriteBackUint32() << 21) |
4967 GetRegisterListEncoding(registers, 0, 16));
4968 return;
4969 }
4970 }
4971 Delegate(kLdmib, &Assembler::ldmib, cond, rn, write_back, registers);
4972}
4973
4974void Assembler::ldr(Condition cond,
4975 EncodingSize size,
4976 Register rt,
4977 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07004978 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01004979 CheckIT(cond);
4980 if (operand.IsImmediate()) {
4981 Register rn = operand.GetBaseRegister();
4982 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01004983 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004984 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
4985 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004986 (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004987 int32_t offset_ = offset >> 2;
4988 EmitT32_16(0x6800 | rt.GetCode() | (rn.GetCode() << 3) |
4989 ((offset_ & 0x1f) << 6));
4990 AdvanceIT();
4991 return;
4992 }
4993 // LDR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
4994 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08004995 ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01004996 int32_t offset_ = offset >> 2;
4997 EmitT32_16(0x9800 | (rt.GetCode() << 8) | (offset_ & 0xff));
4998 AdvanceIT();
4999 return;
5000 }
5001 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
5002 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005003 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5004 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5005 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005006 EmitT32_32(0xf8d00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5007 (offset & 0xfff));
5008 AdvanceIT();
5009 return;
5010 }
5011 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
5012 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005013 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5014 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5015 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005016 EmitT32_32(0xf8500c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5017 (-offset & 0xff));
5018 AdvanceIT();
5019 return;
5020 }
5021 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
5022 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005023 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5024 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5025 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005026 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5027 uint32_t offset_ = abs(offset);
5028 EmitT32_32(0xf8500900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5029 offset_ | (sign << 9));
5030 AdvanceIT();
5031 return;
5032 }
5033 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
5034 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005035 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5036 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5037 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005038 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5039 uint32_t offset_ = abs(offset);
5040 EmitT32_32(0xf8500d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5041 offset_ | (sign << 9));
5042 AdvanceIT();
5043 return;
5044 }
5045 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T2
5046 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005047 rn.Is(pc) && operand.IsOffset() &&
5048 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5049 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005050 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5051 uint32_t offset_ = abs(offset);
5052 EmitT32_32(0xf85f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5053 AdvanceIT();
5054 return;
5055 }
5056 } else {
5057 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005058 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
5059 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005060 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5061 uint32_t offset_ = abs(offset);
5062 EmitA32(0x05100000U | (cond.GetCondition() << 28) |
5063 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5064 (sign << 23));
5065 return;
5066 }
5067 // LDR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005068 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
5069 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005070 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5071 uint32_t offset_ = abs(offset);
5072 EmitA32(0x04100000U | (cond.GetCondition() << 28) |
5073 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5074 (sign << 23));
5075 return;
5076 }
5077 // LDR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005078 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
5079 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005080 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5081 uint32_t offset_ = abs(offset);
5082 EmitA32(0x05300000U | (cond.GetCondition() << 28) |
5083 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5084 (sign << 23));
5085 return;
5086 }
5087 // LDR{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5088 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005089 operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005090 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5091 uint32_t offset_ = abs(offset);
5092 EmitA32(0x051f0000U | (cond.GetCondition() << 28) |
5093 (rt.GetCode() << 12) | offset_ | (sign << 23));
5094 return;
5095 }
5096 }
5097 }
5098 if (operand.IsPlainRegister()) {
5099 Register rn = operand.GetBaseRegister();
5100 Sign sign = operand.GetSign();
5101 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005102 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005103 // LDR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5104 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005105 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005106 EmitT32_16(0x5800 | rt.GetCode() | (rn.GetCode() << 3) |
5107 (rm.GetCode() << 6));
5108 AdvanceIT();
5109 return;
5110 }
5111 }
5112 }
5113 if (operand.IsShiftedRegister()) {
5114 Register rn = operand.GetBaseRegister();
5115 Sign sign = operand.GetSign();
5116 Register rm = operand.GetOffsetRegister();
5117 Shift shift = operand.GetShift();
5118 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005119 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005120 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5121 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005122 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5123 ((!rm.IsPC() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
5124 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005125 EmitT32_32(0xf8500000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5126 rm.GetCode() | (amount << 4));
5127 AdvanceIT();
5128 return;
5129 }
5130 } else {
5131 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005132 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5133 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005134 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5135 uint32_t shift_ = TypeEncodingValue(shift);
5136 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5137 EmitA32(0x07100000U | (cond.GetCondition() << 28) |
5138 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5139 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5140 return;
5141 }
5142 // LDR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005143 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005144 cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005145 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5146 uint32_t shift_ = TypeEncodingValue(shift);
5147 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5148 EmitA32(0x06100000U | (cond.GetCondition() << 28) |
5149 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5150 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5151 return;
5152 }
5153 // LDR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005154 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5155 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005156 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5157 uint32_t shift_ = TypeEncodingValue(shift);
5158 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5159 EmitA32(0x07300000U | (cond.GetCondition() << 28) |
5160 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5161 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5162 return;
5163 }
5164 }
5165 }
5166 Delegate(kLdr, &Assembler::ldr, cond, size, rt, operand);
5167}
5168
5169void Assembler::ldr(Condition cond,
5170 EncodingSize size,
5171 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005172 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005173 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005174 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005175 Location::Offset offset =
5176 location->IsBound()
5177 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005178 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5179 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005180 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005181 // LDR{<c>}{<q>} <Rt>, <label> ; T1
5182 if (!size.IsWide() && rt.IsLow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005183 ((location->IsBound() && (offset >= 0) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005184 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005185 (!location->IsBound() && size.IsNarrow()))) {
5186 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005187 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005188 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005189 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005190 Location::Offset pc,
5191 const Location* location) const VIXL_OVERRIDE {
5192 pc += kT32PcDelta;
5193 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005194 VIXL_ASSERT((offset >= 0) && (offset <= 1020) &&
5195 ((offset & 0x3) == 0));
5196 const int32_t target = offset >> 2;
5197 return instr | (target & 0xff);
5198 }
5199 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005200 EmitT32_16(
Vincent Belliardac285442017-05-16 09:26:45 -07005201 Link(0x4800 | (rt.GetCode() << 8), location, immop, &kT16DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005202 AdvanceIT();
5203 return;
5204 }
5205 // LDR{<c>}{<q>} <Rt>, <label> ; T2
5206 if (!size.IsNarrow() &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005207 ((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5208 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005209 ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
5210 AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005211 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005212 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005213 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005214 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005215 Location::Offset pc,
5216 const Location* location) const VIXL_OVERRIDE {
5217 pc += kT32PcDelta;
5218 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005219 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005220 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005221 int32_t target = abs(offset) | (U << 12);
5222 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5223 }
5224 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005225 EmitT32_32(Link(0xf85f0000U | (rt.GetCode() << 12),
5226 location,
5227 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005228 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005229 AdvanceIT();
5230 return;
5231 }
5232 } else {
5233 // LDR{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005234 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5235 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005236 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005237 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005238 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005239 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005240 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005241 Location::Offset pc,
5242 const Location* location) const VIXL_OVERRIDE {
5243 pc += kA32PcDelta;
5244 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005245 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005246 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005247 int32_t target = abs(offset) | (U << 12);
5248 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5249 }
5250 } immop;
5251 EmitA32(
5252 Link(0x051f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005253 location,
5254 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005255 &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005256 return;
5257 }
5258 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005259 Delegate(kLdr, &Assembler::ldr, cond, size, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005260}
5261
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005262bool Assembler::ldr_info(Condition cond,
5263 EncodingSize size,
5264 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005265 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005266 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005267 VIXL_ASSERT(!location->IsBound());
5268 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005269 if (IsUsingT32()) {
5270 // LDR{<c>}{<q>} <Rt>, <label> ; T1
5271 if (!size.IsWide() && rt.IsLow() && size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005272 *info = &kT16DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005273 return true;
5274 }
5275 // LDR{<c>}{<q>} <Rt>, <label> ; T2
5276 if (!size.IsNarrow()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005277 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005278 return true;
5279 }
5280 } else {
5281 // LDR{<c>}{<q>} <Rt>, <label> ; A1
5282 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005283 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005284 return true;
5285 }
5286 }
5287 return false;
5288}
5289
Alexandre Ramesd3832962016-07-04 15:03:43 +01005290void Assembler::ldrb(Condition cond,
5291 EncodingSize size,
5292 Register rt,
5293 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005294 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005295 CheckIT(cond);
5296 if (operand.IsImmediate()) {
5297 Register rn = operand.GetBaseRegister();
5298 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005299 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005300 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5301 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005302 (offset <= 31) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005303 EmitT32_16(0x7800 | rt.GetCode() | (rn.GetCode() << 3) |
5304 ((offset & 0x1f) << 6));
5305 AdvanceIT();
5306 return;
5307 }
5308 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5309 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005310 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005311 EmitT32_32(0xf8900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5312 (offset & 0xfff));
5313 AdvanceIT();
5314 return;
5315 }
5316 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5317 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005318 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005319 EmitT32_32(0xf8100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5320 (-offset & 0xff));
5321 AdvanceIT();
5322 return;
5323 }
5324 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5325 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005326 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005327 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5328 uint32_t offset_ = abs(offset);
5329 EmitT32_32(0xf8100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5330 offset_ | (sign << 9));
5331 AdvanceIT();
5332 return;
5333 }
5334 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5335 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005336 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005337 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5338 uint32_t offset_ = abs(offset);
5339 EmitT32_32(0xf8100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5340 offset_ | (sign << 9));
5341 AdvanceIT();
5342 return;
5343 }
5344 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5345 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005346 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005347 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5348 uint32_t offset_ = abs(offset);
5349 EmitT32_32(0xf81f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5350 AdvanceIT();
5351 return;
5352 }
5353 } else {
5354 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005355 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005356 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5357 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005358 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5359 uint32_t offset_ = abs(offset);
5360 EmitA32(0x05500000U | (cond.GetCondition() << 28) |
5361 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5362 (sign << 23));
5363 return;
5364 }
5365 // LDRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005366 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005367 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5368 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005369 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5370 uint32_t offset_ = abs(offset);
5371 EmitA32(0x04500000U | (cond.GetCondition() << 28) |
5372 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5373 (sign << 23));
5374 return;
5375 }
5376 // LDRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005377 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005378 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5379 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005380 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5381 uint32_t offset_ = abs(offset);
5382 EmitA32(0x05700000U | (cond.GetCondition() << 28) |
5383 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
5384 (sign << 23));
5385 return;
5386 }
5387 // LDRB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
5388 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005389 operand.IsOffset() && cond.IsNotNever() &&
5390 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005391 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5392 uint32_t offset_ = abs(offset);
5393 EmitA32(0x055f0000U | (cond.GetCondition() << 28) |
5394 (rt.GetCode() << 12) | offset_ | (sign << 23));
5395 return;
5396 }
5397 }
5398 }
5399 if (operand.IsPlainRegister()) {
5400 Register rn = operand.GetBaseRegister();
5401 Sign sign = operand.GetSign();
5402 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005403 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005404 // LDRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
5405 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005406 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005407 EmitT32_16(0x5c00 | rt.GetCode() | (rn.GetCode() << 3) |
5408 (rm.GetCode() << 6));
5409 AdvanceIT();
5410 return;
5411 }
5412 }
5413 }
5414 if (operand.IsShiftedRegister()) {
5415 Register rn = operand.GetBaseRegister();
5416 Sign sign = operand.GetSign();
5417 Register rm = operand.GetOffsetRegister();
5418 Shift shift = operand.GetShift();
5419 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005420 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005421 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
5422 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005423 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
5424 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005425 EmitT32_32(0xf8100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5426 rm.GetCode() | (amount << 4));
5427 AdvanceIT();
5428 return;
5429 }
5430 } else {
5431 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005432 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
5433 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005434 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5435 uint32_t shift_ = TypeEncodingValue(shift);
5436 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5437 EmitA32(0x07500000U | (cond.GetCondition() << 28) |
5438 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5439 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5440 return;
5441 }
5442 // LDRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005443 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005444 cond.IsNotNever() &&
5445 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005446 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5447 uint32_t shift_ = TypeEncodingValue(shift);
5448 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5449 EmitA32(0x06500000U | (cond.GetCondition() << 28) |
5450 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5451 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5452 return;
5453 }
5454 // LDRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005455 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
5456 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005457 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5458 uint32_t shift_ = TypeEncodingValue(shift);
5459 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
5460 EmitA32(0x07700000U | (cond.GetCondition() << 28) |
5461 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5462 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
5463 return;
5464 }
5465 }
5466 }
5467 Delegate(kLdrb, &Assembler::ldrb, cond, size, rt, operand);
5468}
5469
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005470void Assembler::ldrb(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005471 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005472 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005473 Location::Offset offset =
5474 location->IsBound()
5475 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005476 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5477 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005478 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005479 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005480 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5481 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005482 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005483 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005484 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005485 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005486 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005487 Location::Offset pc,
5488 const Location* location) const VIXL_OVERRIDE {
5489 pc += kT32PcDelta;
5490 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005491 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005492 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005493 int32_t target = abs(offset) | (U << 12);
5494 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5495 }
5496 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005497 EmitT32_32(Link(0xf81f0000U | (rt.GetCode() << 12),
5498 location,
5499 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005500 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005501 AdvanceIT();
5502 return;
5503 }
5504 } else {
5505 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005506 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
5507 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005508 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005509 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005510 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005511 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005512 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005513 Location::Offset pc,
5514 const Location* location) const VIXL_OVERRIDE {
5515 pc += kA32PcDelta;
5516 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005517 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005518 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005519 int32_t target = abs(offset) | (U << 12);
5520 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
5521 }
5522 } immop;
5523 EmitA32(
5524 Link(0x055f0000U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005525 location,
5526 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005527 &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005528 return;
5529 }
5530 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005531 Delegate(kLdrb, &Assembler::ldrb, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005532}
5533
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005534bool Assembler::ldrb_info(Condition cond,
5535 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005536 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005537 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005538 VIXL_ASSERT(!location->IsBound());
5539 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005540 if (IsUsingT32()) {
5541 // LDRB{<c>}{<q>} <Rt>, <label> ; T1
5542 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07005543 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005544 return true;
5545 }
5546 } else {
5547 // LDRB{<c>}{<q>} <Rt>, <label> ; A1
5548 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005549 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005550 return true;
5551 }
5552 }
5553 return false;
5554}
5555
Alexandre Ramesd3832962016-07-04 15:03:43 +01005556void Assembler::ldrd(Condition cond,
5557 Register rt,
5558 Register rt2,
5559 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005560 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005561 CheckIT(cond);
5562 if (operand.IsImmediate()) {
5563 Register rn = operand.GetBaseRegister();
5564 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005565 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005566 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
5567 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005568 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
5569 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005570 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5571 uint32_t offset_ = abs(offset) >> 2;
5572 EmitT32_32(0xe9500000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5573 (rn.GetCode() << 16) | offset_ | (sign << 23));
5574 AdvanceIT();
5575 return;
5576 }
5577 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
5578 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005579 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5580 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005581 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5582 uint32_t offset_ = abs(offset) >> 2;
5583 EmitT32_32(0xe8700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5584 (rn.GetCode() << 16) | offset_ | (sign << 23));
5585 AdvanceIT();
5586 return;
5587 }
5588 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
5589 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005590 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
5591 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005592 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5593 uint32_t offset_ = abs(offset) >> 2;
5594 EmitT32_32(0xe9700000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5595 (rn.GetCode() << 16) | offset_ | (sign << 23));
5596 AdvanceIT();
5597 return;
5598 }
5599 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm>] ; T1
5600 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005601 operand.IsOffset() &&
5602 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005603 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5604 uint32_t offset_ = abs(offset);
5605 EmitT32_32(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5606 offset_ | (sign << 23));
5607 AdvanceIT();
5608 return;
5609 }
5610 } else {
5611 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
5612 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005613 (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
5614 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005615 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005616 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005617 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5618 uint32_t offset_ = abs(offset);
5619 EmitA32(0x014000d0U | (cond.GetCondition() << 28) |
5620 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5621 ((offset_ & 0xf0) << 4) | (sign << 23));
5622 return;
5623 }
5624 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
5625 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005626 (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
5627 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005628 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005629 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005630 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5631 uint32_t offset_ = abs(offset);
5632 EmitA32(0x004000d0U | (cond.GetCondition() << 28) |
5633 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5634 ((offset_ & 0xf0) << 4) | (sign << 23));
5635 return;
5636 }
5637 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
5638 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005639 (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
5640 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005641 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005642 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005643 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5644 uint32_t offset_ = abs(offset);
5645 EmitA32(0x016000d0U | (cond.GetCondition() << 28) |
5646 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5647 ((offset_ & 0xf0) << 4) | (sign << 23));
5648 return;
5649 }
5650 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [PC, #<_plusminus_><imm_1>] ; A1
5651 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5652 (offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005653 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005654 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005655 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005656 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5657 uint32_t offset_ = abs(offset);
5658 EmitA32(0x014f00d0U | (cond.GetCondition() << 28) |
5659 (rt.GetCode() << 12) | (offset_ & 0xf) |
5660 ((offset_ & 0xf0) << 4) | (sign << 23));
5661 return;
5662 }
5663 }
5664 }
5665 if (operand.IsPlainRegister()) {
5666 Register rn = operand.GetBaseRegister();
5667 Sign sign = operand.GetSign();
5668 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005669 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005670 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
5671 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005672 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005673 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005674 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005675 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5676 EmitA32(0x010000d0U | (cond.GetCondition() << 28) |
5677 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5678 (sign_ << 23));
5679 return;
5680 }
5681 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
5682 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005683 operand.IsPostIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005684 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005685 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005686 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5687 EmitA32(0x000000d0U | (cond.GetCondition() << 28) |
5688 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5689 (sign_ << 23));
5690 return;
5691 }
5692 // LDRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
5693 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005694 operand.IsPreIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005695 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +00005696 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005697 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
5698 EmitA32(0x012000d0U | (cond.GetCondition() << 28) |
5699 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
5700 (sign_ << 23));
5701 return;
5702 }
5703 }
5704 }
5705 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, operand);
5706}
5707
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005708void Assembler::ldrd(Condition cond,
5709 Register rt,
5710 Register rt2,
5711 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005712 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005713 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005714 Location::Offset offset =
5715 location->IsBound()
5716 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01005717 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
5718 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005719 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005720 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005721 if (((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005722 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005723 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005724 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005725 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005726 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005727 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005728 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005729 Location::Offset pc,
5730 const Location* location) const VIXL_OVERRIDE {
5731 pc += kT32PcDelta;
5732 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005733 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
5734 ((offset & 0x3) == 0));
5735 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005736 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005737 target = abs(target) | (U << 8);
5738 return instr | (target & 0xff) | ((target & 0x100) << 15);
5739 }
5740 } immop;
5741 EmitT32_32(Link(0xe95f0000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005742 location,
5743 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005744 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005745 AdvanceIT();
5746 return;
5747 }
5748 } else {
5749 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5750 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005751 ((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
5752 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01005753 cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005754 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005755 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005756 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005757 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00005758 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005759 Location::Offset pc,
5760 const Location* location) const VIXL_OVERRIDE {
5761 pc += kA32PcDelta;
5762 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005763 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00005764 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005765 int32_t target = abs(offset) | (U << 8);
5766 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
5767 ((target & 0x100) << 15);
5768 }
5769 } immop;
5770 EmitA32(
5771 Link(0x014f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005772 location,
5773 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07005774 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01005775 return;
5776 }
5777 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005778 Delegate(kLdrd, &Assembler::ldrd, cond, rt, rt2, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01005779}
5780
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005781bool Assembler::ldrd_info(Condition cond,
5782 Register rt,
5783 Register rt2,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005784 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005785 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01005786 VIXL_ASSERT(!location->IsBound());
5787 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005788 if (IsUsingT32()) {
5789 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; T1
5790 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07005791 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005792 return true;
5793 }
5794 } else {
5795 // LDRD{<c>}{<q>} <Rt>, <Rt2>, <label> ; A1
5796 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
5797 cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07005798 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01005799 return true;
5800 }
5801 }
5802 return false;
5803}
5804
Alexandre Ramesd3832962016-07-04 15:03:43 +01005805void Assembler::ldrex(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005806 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005807 CheckIT(cond);
5808 if (operand.IsImmediate()) {
5809 Register rn = operand.GetBaseRegister();
5810 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005811 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005812 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm>}] ; T1
5813 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005814 operand.IsOffset() &&
5815 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005816 int32_t offset_ = offset >> 2;
5817 EmitT32_32(0xe8500f00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5818 (offset_ & 0xff));
5819 AdvanceIT();
5820 return;
5821 }
5822 } else {
5823 // LDREX{<c>}{<q>} <Rt>, [<Rn>{, #<imm_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005824 if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
5825 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005826 EmitA32(0x01900f9fU | (cond.GetCondition() << 28) |
5827 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5828 return;
5829 }
5830 }
5831 }
5832 Delegate(kLdrex, &Assembler::ldrex, cond, rt, operand);
5833}
5834
5835void Assembler::ldrexb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005836 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005837 CheckIT(cond);
5838 if (operand.IsImmediateZero()) {
5839 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005840 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005841 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005842 if (operand.IsOffset() &&
5843 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005844 EmitT32_32(0xe8d00f4fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5845 AdvanceIT();
5846 return;
5847 }
5848 } else {
5849 // LDREXB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005850 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005851 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005852 EmitA32(0x01d00f9fU | (cond.GetCondition() << 28) |
5853 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5854 return;
5855 }
5856 }
5857 }
5858 Delegate(kLdrexb, &Assembler::ldrexb, cond, rt, operand);
5859}
5860
5861void Assembler::ldrexd(Condition cond,
5862 Register rt,
5863 Register rt2,
5864 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005865 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005866 CheckIT(cond);
5867 if (operand.IsImmediateZero()) {
5868 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005869 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005870 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005871 if (operand.IsOffset() &&
5872 ((!rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005873 EmitT32_32(0xe8d0007fU | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
5874 (rn.GetCode() << 16));
5875 AdvanceIT();
5876 return;
5877 }
5878 } else {
5879 // LDREXD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>] ; A1
5880 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005881 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +00005882 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +01005883 AllowUnpredictable())) {
5884 EmitA32(0x01b00f9fU | (cond.GetCondition() << 28) |
5885 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5886 return;
5887 }
5888 }
5889 }
5890 Delegate(kLdrexd, &Assembler::ldrexd, cond, rt, rt2, operand);
5891}
5892
5893void Assembler::ldrexh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005894 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005895 CheckIT(cond);
5896 if (operand.IsImmediateZero()) {
5897 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005898 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005899 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00005900 if (operand.IsOffset() &&
5901 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005902 EmitT32_32(0xe8d00f5fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
5903 AdvanceIT();
5904 return;
5905 }
5906 } else {
5907 // LDREXH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005908 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005909 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005910 EmitA32(0x01f00f9fU | (cond.GetCondition() << 28) |
5911 (rt.GetCode() << 12) | (rn.GetCode() << 16));
5912 return;
5913 }
5914 }
5915 }
5916 Delegate(kLdrexh, &Assembler::ldrexh, cond, rt, operand);
5917}
5918
5919void Assembler::ldrh(Condition cond,
5920 EncodingSize size,
5921 Register rt,
5922 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07005923 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01005924 CheckIT(cond);
5925 if (operand.IsImmediate()) {
5926 Register rn = operand.GetBaseRegister();
5927 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01005928 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005929 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
5930 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005931 (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005932 int32_t offset_ = offset >> 1;
5933 EmitT32_16(0x8800 | rt.GetCode() | (rn.GetCode() << 3) |
5934 ((offset_ & 0x1f) << 6));
5935 AdvanceIT();
5936 return;
5937 }
5938 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
5939 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005940 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005941 EmitT32_32(0xf8b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5942 (offset & 0xfff));
5943 AdvanceIT();
5944 return;
5945 }
5946 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
5947 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005948 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005949 EmitT32_32(0xf8300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5950 (-offset & 0xff));
5951 AdvanceIT();
5952 return;
5953 }
5954 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
5955 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005956 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005957 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5958 uint32_t offset_ = abs(offset);
5959 EmitT32_32(0xf8300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5960 offset_ | (sign << 9));
5961 AdvanceIT();
5962 return;
5963 }
5964 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
5965 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005966 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005967 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5968 uint32_t offset_ = abs(offset);
5969 EmitT32_32(0xf8300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
5970 offset_ | (sign << 9));
5971 AdvanceIT();
5972 return;
5973 }
5974 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
5975 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005976 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005977 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5978 uint32_t offset_ = abs(offset);
5979 EmitT32_32(0xf83f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
5980 AdvanceIT();
5981 return;
5982 }
5983 } else {
5984 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005985 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005986 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5987 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005988 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
5989 uint32_t offset_ = abs(offset);
5990 EmitA32(0x015000b0U | (cond.GetCondition() << 28) |
5991 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
5992 ((offset_ & 0xf0) << 4) | (sign << 23));
5993 return;
5994 }
5995 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08005996 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00005997 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
5998 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01005999 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6000 uint32_t offset_ = abs(offset);
6001 EmitA32(0x005000b0U | (cond.GetCondition() << 28) |
6002 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6003 ((offset_ & 0xf0) << 4) | (sign << 23));
6004 return;
6005 }
6006 // LDRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006007 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006008 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6009 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006010 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6011 uint32_t offset_ = abs(offset);
6012 EmitA32(0x017000b0U | (cond.GetCondition() << 28) |
6013 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6014 ((offset_ & 0xf0) << 4) | (sign << 23));
6015 return;
6016 }
6017 // LDRH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6018 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006019 operand.IsOffset() && cond.IsNotNever() &&
6020 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006021 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6022 uint32_t offset_ = abs(offset);
6023 EmitA32(0x015f00b0U | (cond.GetCondition() << 28) |
6024 (rt.GetCode() << 12) | (offset_ & 0xf) |
6025 ((offset_ & 0xf0) << 4) | (sign << 23));
6026 return;
6027 }
6028 }
6029 }
6030 if (operand.IsPlainRegister()) {
6031 Register rn = operand.GetBaseRegister();
6032 Sign sign = operand.GetSign();
6033 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006034 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006035 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6036 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006037 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006038 EmitT32_16(0x5a00 | rt.GetCode() | (rn.GetCode() << 3) |
6039 (rm.GetCode() << 6));
6040 AdvanceIT();
6041 return;
6042 }
6043 } else {
6044 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006045 if (operand.IsOffset() && cond.IsNotNever() &&
6046 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006047 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6048 EmitA32(0x011000b0U | (cond.GetCondition() << 28) |
6049 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6050 (sign_ << 23));
6051 return;
6052 }
6053 // LDRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006054 if (operand.IsPostIndex() && cond.IsNotNever() &&
6055 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006056 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6057 EmitA32(0x001000b0U | (cond.GetCondition() << 28) |
6058 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6059 (sign_ << 23));
6060 return;
6061 }
6062 // LDRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006063 if (operand.IsPreIndex() && cond.IsNotNever() &&
6064 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006065 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6066 EmitA32(0x013000b0U | (cond.GetCondition() << 28) |
6067 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6068 (sign_ << 23));
6069 return;
6070 }
6071 }
6072 }
6073 if (operand.IsShiftedRegister()) {
6074 Register rn = operand.GetBaseRegister();
6075 Sign sign = operand.GetSign();
6076 Register rm = operand.GetOffsetRegister();
6077 Shift shift = operand.GetShift();
6078 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006079 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006080 // LDRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6081 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006082 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6083 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006084 EmitT32_32(0xf8300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6085 rm.GetCode() | (amount << 4));
6086 AdvanceIT();
6087 return;
6088 }
6089 }
6090 }
6091 Delegate(kLdrh, &Assembler::ldrh, cond, size, rt, operand);
6092}
6093
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006094void Assembler::ldrh(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006095 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006096 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006097 Location::Offset offset =
6098 location->IsBound()
6099 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006100 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6101 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006102 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006103 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006104 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6105 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006106 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006107 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006108 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006109 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006110 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006111 Location::Offset pc,
6112 const Location* location) const VIXL_OVERRIDE {
6113 pc += kT32PcDelta;
6114 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006115 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006116 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006117 int32_t target = abs(offset) | (U << 12);
6118 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6119 }
6120 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006121 EmitT32_32(Link(0xf83f0000U | (rt.GetCode() << 12),
6122 location,
6123 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006124 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006125 AdvanceIT();
6126 return;
6127 }
6128 } else {
6129 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006130 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6131 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006132 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006133 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006134 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006135 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006136 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006137 Location::Offset pc,
6138 const Location* location) const VIXL_OVERRIDE {
6139 pc += kA32PcDelta;
6140 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006141 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006142 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006143 int32_t target = abs(offset) | (U << 8);
6144 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6145 ((target & 0x100) << 15);
6146 }
6147 } immop;
6148 EmitA32(
6149 Link(0x015f00b0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006150 location,
6151 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006152 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006153 return;
6154 }
6155 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006156 Delegate(kLdrh, &Assembler::ldrh, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006157}
6158
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006159bool Assembler::ldrh_info(Condition cond,
6160 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006161 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006162 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006163 VIXL_ASSERT(!location->IsBound());
6164 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006165 if (IsUsingT32()) {
6166 // LDRH{<c>}{<q>} <Rt>, <label> ; T1
6167 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006168 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006169 return true;
6170 }
6171 } else {
6172 // LDRH{<c>}{<q>} <Rt>, <label> ; A1
6173 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006174 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006175 return true;
6176 }
6177 }
6178 return false;
6179}
6180
Alexandre Ramesd3832962016-07-04 15:03:43 +01006181void Assembler::ldrsb(Condition cond,
6182 EncodingSize size,
6183 Register rt,
6184 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006186 CheckIT(cond);
6187 if (operand.IsImmediate()) {
6188 Register rn = operand.GetBaseRegister();
6189 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006190 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006191 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6192 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006193 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006194 EmitT32_32(0xf9900000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6195 (offset & 0xfff));
6196 AdvanceIT();
6197 return;
6198 }
6199 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6200 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006201 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006202 EmitT32_32(0xf9100c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6203 (-offset & 0xff));
6204 AdvanceIT();
6205 return;
6206 }
6207 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6208 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006209 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006210 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6211 uint32_t offset_ = abs(offset);
6212 EmitT32_32(0xf9100900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6213 offset_ | (sign << 9));
6214 AdvanceIT();
6215 return;
6216 }
6217 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6218 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006219 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006220 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6221 uint32_t offset_ = abs(offset);
6222 EmitT32_32(0xf9100d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6223 offset_ | (sign << 9));
6224 AdvanceIT();
6225 return;
6226 }
6227 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6228 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006229 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006230 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6231 uint32_t offset_ = abs(offset);
6232 EmitT32_32(0xf91f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6233 AdvanceIT();
6234 return;
6235 }
6236 } else {
6237 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006238 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006239 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6240 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006241 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6242 uint32_t offset_ = abs(offset);
6243 EmitA32(0x015000d0U | (cond.GetCondition() << 28) |
6244 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6245 ((offset_ & 0xf0) << 4) | (sign << 23));
6246 return;
6247 }
6248 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006249 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006250 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6251 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006252 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6253 uint32_t offset_ = abs(offset);
6254 EmitA32(0x005000d0U | (cond.GetCondition() << 28) |
6255 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6256 ((offset_ & 0xf0) << 4) | (sign << 23));
6257 return;
6258 }
6259 // LDRSB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006260 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006261 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6262 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006263 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6264 uint32_t offset_ = abs(offset);
6265 EmitA32(0x017000d0U | (cond.GetCondition() << 28) |
6266 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6267 ((offset_ & 0xf0) << 4) | (sign << 23));
6268 return;
6269 }
6270 // LDRSB{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6271 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006272 operand.IsOffset() && cond.IsNotNever() &&
6273 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006274 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6275 uint32_t offset_ = abs(offset);
6276 EmitA32(0x015f00d0U | (cond.GetCondition() << 28) |
6277 (rt.GetCode() << 12) | (offset_ & 0xf) |
6278 ((offset_ & 0xf0) << 4) | (sign << 23));
6279 return;
6280 }
6281 }
6282 }
6283 if (operand.IsPlainRegister()) {
6284 Register rn = operand.GetBaseRegister();
6285 Sign sign = operand.GetSign();
6286 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006287 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006288 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6289 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006290 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006291 EmitT32_16(0x5600 | rt.GetCode() | (rn.GetCode() << 3) |
6292 (rm.GetCode() << 6));
6293 AdvanceIT();
6294 return;
6295 }
6296 } else {
6297 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006298 if (operand.IsOffset() && cond.IsNotNever() &&
6299 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006300 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6301 EmitA32(0x011000d0U | (cond.GetCondition() << 28) |
6302 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6303 (sign_ << 23));
6304 return;
6305 }
6306 // LDRSB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006307 if (operand.IsPostIndex() && cond.IsNotNever() &&
6308 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006309 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6310 EmitA32(0x001000d0U | (cond.GetCondition() << 28) |
6311 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6312 (sign_ << 23));
6313 return;
6314 }
6315 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006316 if (operand.IsPreIndex() && cond.IsNotNever() &&
6317 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006318 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6319 EmitA32(0x013000d0U | (cond.GetCondition() << 28) |
6320 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6321 (sign_ << 23));
6322 return;
6323 }
6324 }
6325 }
6326 if (operand.IsShiftedRegister()) {
6327 Register rn = operand.GetBaseRegister();
6328 Sign sign = operand.GetSign();
6329 Register rm = operand.GetOffsetRegister();
6330 Shift shift = operand.GetShift();
6331 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006332 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006333 // LDRSB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6334 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006335 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6336 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006337 EmitT32_32(0xf9100000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6338 rm.GetCode() | (amount << 4));
6339 AdvanceIT();
6340 return;
6341 }
6342 }
6343 }
6344 Delegate(kLdrsb, &Assembler::ldrsb, cond, size, rt, operand);
6345}
6346
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006347void Assembler::ldrsb(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006349 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006350 Location::Offset offset =
6351 location->IsBound()
6352 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006353 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6354 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006355 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006356 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006357 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6358 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006359 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006360 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006361 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006362 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006363 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006364 Location::Offset pc,
6365 const Location* location) const VIXL_OVERRIDE {
6366 pc += kT32PcDelta;
6367 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006368 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006369 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006370 int32_t target = abs(offset) | (U << 12);
6371 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6372 }
6373 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006374 EmitT32_32(Link(0xf91f0000U | (rt.GetCode() << 12),
6375 location,
6376 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006377 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006378 AdvanceIT();
6379 return;
6380 }
6381 } else {
6382 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006383 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6384 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006385 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006386 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006387 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006388 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006389 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006390 Location::Offset pc,
6391 const Location* location) const VIXL_OVERRIDE {
6392 pc += kA32PcDelta;
6393 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006394 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006395 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006396 int32_t target = abs(offset) | (U << 8);
6397 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6398 ((target & 0x100) << 15);
6399 }
6400 } immop;
6401 EmitA32(
6402 Link(0x015f00d0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006403 location,
6404 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006405 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006406 return;
6407 }
6408 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006409 Delegate(kLdrsb, &Assembler::ldrsb, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006410}
6411
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006412bool Assembler::ldrsb_info(Condition cond,
6413 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006414 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006415 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006416 VIXL_ASSERT(!location->IsBound());
6417 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006418 if (IsUsingT32()) {
6419 // LDRSB{<c>}{<q>} <Rt>, <label> ; T1
6420 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006421 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006422 return true;
6423 }
6424 } else {
6425 // LDRSB{<c>}{<q>} <Rt>, <label> ; A1
6426 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006427 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006428 return true;
6429 }
6430 }
6431 return false;
6432}
6433
Alexandre Ramesd3832962016-07-04 15:03:43 +01006434void Assembler::ldrsh(Condition cond,
6435 EncodingSize size,
6436 Register rt,
6437 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006438 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006439 CheckIT(cond);
6440 if (operand.IsImmediate()) {
6441 Register rn = operand.GetBaseRegister();
6442 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006443 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006444 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
6445 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006446 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006447 EmitT32_32(0xf9b00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6448 (offset & 0xfff));
6449 AdvanceIT();
6450 return;
6451 }
6452 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_1>}] ; T2
6453 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006454 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006455 EmitT32_32(0xf9300c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6456 (-offset & 0xff));
6457 AdvanceIT();
6458 return;
6459 }
6460 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_1> ; T2
6461 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006462 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006463 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6464 uint32_t offset_ = abs(offset);
6465 EmitT32_32(0xf9300900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6466 offset_ | (sign << 9));
6467 AdvanceIT();
6468 return;
6469 }
6470 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_1>}]! ; T2
6471 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006472 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006473 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6474 uint32_t offset_ = abs(offset);
6475 EmitT32_32(0xf9300d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6476 offset_ | (sign << 9));
6477 AdvanceIT();
6478 return;
6479 }
6480 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm>] ; T1
6481 if (!size.IsNarrow() && (offset >= -4095) && (offset <= 4095) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006482 rn.Is(pc) && operand.IsOffset() && !rt.Is(pc)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006483 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6484 uint32_t offset_ = abs(offset);
6485 EmitT32_32(0xf93f0000U | (rt.GetCode() << 12) | offset_ | (sign << 23));
6486 AdvanceIT();
6487 return;
6488 }
6489 } else {
6490 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006491 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006492 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6493 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006494 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6495 uint32_t offset_ = abs(offset);
6496 EmitA32(0x015000f0U | (cond.GetCondition() << 28) |
6497 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6498 ((offset_ & 0xf0) << 4) | (sign << 23));
6499 return;
6500 }
6501 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006502 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006503 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6504 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006505 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6506 uint32_t offset_ = abs(offset);
6507 EmitA32(0x005000f0U | (cond.GetCondition() << 28) |
6508 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6509 ((offset_ & 0xf0) << 4) | (sign << 23));
6510 return;
6511 }
6512 // LDRSH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006513 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006514 cond.IsNotNever() && ((rn.GetCode() & 0xf) != 0xf) &&
6515 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006516 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6517 uint32_t offset_ = abs(offset);
6518 EmitA32(0x017000f0U | (cond.GetCondition() << 28) |
6519 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
6520 ((offset_ & 0xf0) << 4) | (sign << 23));
6521 return;
6522 }
6523 // LDRSH{<c>}{<q>} <Rt>, [PC, #<_plusminus_><imm_1>] ; A1
6524 if ((offset >= -255) && (offset <= 255) && rn.Is(pc) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006525 operand.IsOffset() && cond.IsNotNever() &&
6526 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006527 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
6528 uint32_t offset_ = abs(offset);
6529 EmitA32(0x015f00f0U | (cond.GetCondition() << 28) |
6530 (rt.GetCode() << 12) | (offset_ & 0xf) |
6531 ((offset_ & 0xf0) << 4) | (sign << 23));
6532 return;
6533 }
6534 }
6535 }
6536 if (operand.IsPlainRegister()) {
6537 Register rn = operand.GetBaseRegister();
6538 Sign sign = operand.GetSign();
6539 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006540 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006541 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
6542 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08006543 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006544 EmitT32_16(0x5e00 | rt.GetCode() | (rn.GetCode() << 3) |
6545 (rm.GetCode() << 6));
6546 AdvanceIT();
6547 return;
6548 }
6549 } else {
6550 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006551 if (operand.IsOffset() && cond.IsNotNever() &&
6552 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006553 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6554 EmitA32(0x011000f0U | (cond.GetCondition() << 28) |
6555 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6556 (sign_ << 23));
6557 return;
6558 }
6559 // LDRSH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006560 if (operand.IsPostIndex() && cond.IsNotNever() &&
6561 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006562 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6563 EmitA32(0x001000f0U | (cond.GetCondition() << 28) |
6564 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6565 (sign_ << 23));
6566 return;
6567 }
6568 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006569 if (operand.IsPreIndex() && cond.IsNotNever() &&
6570 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006571 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
6572 EmitA32(0x013000f0U | (cond.GetCondition() << 28) |
6573 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
6574 (sign_ << 23));
6575 return;
6576 }
6577 }
6578 }
6579 if (operand.IsShiftedRegister()) {
6580 Register rn = operand.GetBaseRegister();
6581 Sign sign = operand.GetSign();
6582 Register rm = operand.GetOffsetRegister();
6583 Shift shift = operand.GetShift();
6584 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006585 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006586 // LDRSH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
6587 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006588 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) && !rt.Is(pc) &&
6589 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006590 EmitT32_32(0xf9300000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
6591 rm.GetCode() | (amount << 4));
6592 AdvanceIT();
6593 return;
6594 }
6595 }
6596 }
6597 Delegate(kLdrsh, &Assembler::ldrsh, cond, size, rt, operand);
6598}
6599
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006600void Assembler::ldrsh(Condition cond, Register rt, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006601 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006602 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006603 Location::Offset offset =
6604 location->IsBound()
6605 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01006606 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
6607 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006608 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006609 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006610 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
6611 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01006612 !rt.Is(pc)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006613 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006614 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006615 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006616 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006617 Location::Offset pc,
6618 const Location* location) const VIXL_OVERRIDE {
6619 pc += kT32PcDelta;
6620 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006621 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006622 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006623 int32_t target = abs(offset) | (U << 12);
6624 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
6625 }
6626 } immop;
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006627 EmitT32_32(Link(0xf93f0000U | (rt.GetCode() << 12),
6628 location,
6629 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006630 &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006631 AdvanceIT();
6632 return;
6633 }
6634 } else {
6635 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006636 if (((location->IsBound() && (offset >= -255) && (offset <= 255)) ||
6637 !location->IsBound()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00006638 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006639 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006640 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006641 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00006642 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006643 Location::Offset pc,
6644 const Location* location) const VIXL_OVERRIDE {
6645 pc += kA32PcDelta;
6646 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006647 VIXL_ASSERT((offset >= -255) && (offset <= 255));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00006648 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006649 int32_t target = abs(offset) | (U << 8);
6650 return instr | (target & 0xf) | ((target & 0xf0) << 4) |
6651 ((target & 0x100) << 15);
6652 }
6653 } immop;
6654 EmitA32(
6655 Link(0x015f00f0U | (cond.GetCondition() << 28) | (rt.GetCode() << 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006656 location,
6657 immop,
Vincent Belliardac285442017-05-16 09:26:45 -07006658 &kA32VeryNearDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01006659 return;
6660 }
6661 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006662 Delegate(kLdrsh, &Assembler::ldrsh, cond, rt, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01006663}
6664
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006665bool Assembler::ldrsh_info(Condition cond,
6666 Register rt,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006667 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006668 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01006669 VIXL_ASSERT(!location->IsBound());
6670 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006671 if (IsUsingT32()) {
6672 // LDRSH{<c>}{<q>} <Rt>, <label> ; T1
6673 if (!rt.Is(pc)) {
Vincent Belliardac285442017-05-16 09:26:45 -07006674 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006675 return true;
6676 }
6677 } else {
6678 // LDRSH{<c>}{<q>} <Rt>, <label> ; A1
6679 if (cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -07006680 *info = &kA32VeryNearDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01006681 return true;
6682 }
6683 }
6684 return false;
6685}
6686
Alexandre Ramesd3832962016-07-04 15:03:43 +01006687void Assembler::lsl(Condition cond,
6688 EncodingSize size,
6689 Register rd,
6690 Register rm,
6691 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006692 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006693 CheckIT(cond);
6694 if (operand.IsImmediate()) {
6695 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006696 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006697 // LSL<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6698 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6699 (imm >= 1) && (imm <= 31)) {
6700 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6701 AdvanceIT();
6702 return;
6703 }
6704 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006705 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6706 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006707 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6708 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6709 AdvanceIT();
6710 return;
6711 }
6712 } else {
6713 // LSL{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6714 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6715 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
6716 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6717 return;
6718 }
6719 }
6720 }
6721 if (operand.IsPlainRegister()) {
6722 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006723 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006724 // LSL<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6725 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6726 rs.IsLow()) {
6727 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6728 AdvanceIT();
6729 return;
6730 }
6731 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006732 if (!size.IsNarrow() &&
6733 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006734 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6735 rs.GetCode());
6736 AdvanceIT();
6737 return;
6738 }
6739 } else {
6740 // LSL{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006741 if (cond.IsNotNever() &&
6742 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006743 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
6744 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6745 return;
6746 }
6747 }
6748 }
6749 Delegate(kLsl, &Assembler::lsl, cond, size, rd, rm, operand);
6750}
6751
6752void Assembler::lsls(Condition cond,
6753 EncodingSize size,
6754 Register rd,
6755 Register rm,
6756 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006757 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006758 CheckIT(cond);
6759 if (operand.IsImmediate()) {
6760 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006761 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006762 // LSLS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6763 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6764 (imm >= 1) && (imm <= 31)) {
6765 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) | (imm << 6));
6766 AdvanceIT();
6767 return;
6768 }
6769 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006770 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
6771 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006772 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
6773 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
6774 AdvanceIT();
6775 return;
6776 }
6777 } else {
6778 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6779 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
6780 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
6781 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
6782 return;
6783 }
6784 }
6785 }
6786 if (operand.IsPlainRegister()) {
6787 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006788 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006789 // LSLS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6790 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6791 rs.IsLow()) {
6792 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
6793 AdvanceIT();
6794 return;
6795 }
6796 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006797 if (!size.IsNarrow() &&
6798 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006799 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6800 rs.GetCode());
6801 AdvanceIT();
6802 return;
6803 }
6804 } else {
6805 // LSLS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006806 if (cond.IsNotNever() &&
6807 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006808 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
6809 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6810 return;
6811 }
6812 }
6813 }
6814 Delegate(kLsls, &Assembler::lsls, cond, size, rd, rm, operand);
6815}
6816
6817void Assembler::lsr(Condition cond,
6818 EncodingSize size,
6819 Register rd,
6820 Register rm,
6821 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006822 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006823 CheckIT(cond);
6824 if (operand.IsImmediate()) {
6825 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006826 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006827 // LSR<c>{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6828 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6829 (imm >= 1) && (imm <= 32)) {
6830 uint32_t amount_ = imm % 32;
6831 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6832 (amount_ << 6));
6833 AdvanceIT();
6834 return;
6835 }
6836 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006837 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6838 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006839 uint32_t amount_ = imm % 32;
6840 EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6841 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6842 AdvanceIT();
6843 return;
6844 }
6845 } else {
6846 // LSR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6847 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6848 uint32_t amount_ = imm % 32;
6849 EmitA32(0x01a00020U | (cond.GetCondition() << 28) |
6850 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6851 return;
6852 }
6853 }
6854 }
6855 if (operand.IsPlainRegister()) {
6856 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006857 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006858 // LSR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6859 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6860 rs.IsLow()) {
6861 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6862 AdvanceIT();
6863 return;
6864 }
6865 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006866 if (!size.IsNarrow() &&
6867 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006868 EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6869 rs.GetCode());
6870 AdvanceIT();
6871 return;
6872 }
6873 } else {
6874 // LSR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006875 if (cond.IsNotNever() &&
6876 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006877 EmitA32(0x01a00030U | (cond.GetCondition() << 28) |
6878 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6879 return;
6880 }
6881 }
6882 }
6883 Delegate(kLsr, &Assembler::lsr, cond, size, rd, rm, operand);
6884}
6885
6886void Assembler::lsrs(Condition cond,
6887 EncodingSize size,
6888 Register rd,
6889 Register rm,
6890 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006891 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006892 CheckIT(cond);
6893 if (operand.IsImmediate()) {
6894 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006896 // LSRS{<q>} {<Rd>}, <Rm>, #<imm> ; T2
6897 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow() &&
6898 (imm >= 1) && (imm <= 32)) {
6899 uint32_t amount_ = imm % 32;
6900 EmitT32_16(0x0800 | rd.GetCode() | (rm.GetCode() << 3) |
6901 (amount_ << 6));
6902 AdvanceIT();
6903 return;
6904 }
6905 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006906 if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) &&
6907 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006908 uint32_t amount_ = imm % 32;
6909 EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() |
6910 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
6911 AdvanceIT();
6912 return;
6913 }
6914 } else {
6915 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
6916 if ((imm >= 1) && (imm <= 32) && cond.IsNotNever()) {
6917 uint32_t amount_ = imm % 32;
6918 EmitA32(0x01b00020U | (cond.GetCondition() << 28) |
6919 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 7));
6920 return;
6921 }
6922 }
6923 }
6924 if (operand.IsPlainRegister()) {
6925 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006926 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006927 // LSRS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
6928 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
6929 rs.IsLow()) {
6930 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
6931 AdvanceIT();
6932 return;
6933 }
6934 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006935 if (!size.IsNarrow() &&
6936 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006937 EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
6938 rs.GetCode());
6939 AdvanceIT();
6940 return;
6941 }
6942 } else {
6943 // LSRS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00006944 if (cond.IsNotNever() &&
6945 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006946 EmitA32(0x01b00030U | (cond.GetCondition() << 28) |
6947 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
6948 return;
6949 }
6950 }
6951 }
6952 Delegate(kLsrs, &Assembler::lsrs, cond, size, rd, rm, operand);
6953}
6954
6955void Assembler::mla(
6956 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006957 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006958 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006959 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006960 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006961 if (!ra.Is(pc) &&
6962 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006963 EmitT32_32(0xfb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
6964 rm.GetCode() | (ra.GetCode() << 12));
6965 AdvanceIT();
6966 return;
6967 }
6968 } else {
6969 // MLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006970 if (cond.IsNotNever() &&
6971 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6972 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006973 EmitA32(0x00200090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6974 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6975 return;
6976 }
6977 }
6978 Delegate(kMla, &Assembler::mla, cond, rd, rn, rm, ra);
6979}
6980
6981void Assembler::mlas(
6982 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07006983 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01006984 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01006985 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006986 // MLAS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00006987 if (cond.IsNotNever() &&
6988 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
6989 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01006990 EmitA32(0x00300090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
6991 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
6992 return;
6993 }
6994 }
6995 Delegate(kMlas, &Assembler::mlas, cond, rd, rn, rm, ra);
6996}
6997
6998void Assembler::mls(
6999 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007000 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007001 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007002 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007003 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007004 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7005 AllowUnpredictable())) {
7006 EmitT32_32(0xfb000010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7007 rm.GetCode() | (ra.GetCode() << 12));
7008 AdvanceIT();
7009 return;
7010 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007011 } else {
7012 // MLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007013 if (cond.IsNotNever() &&
7014 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
7015 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007016 EmitA32(0x00600090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7017 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
7018 return;
7019 }
7020 }
7021 Delegate(kMls, &Assembler::mls, cond, rd, rn, rm, ra);
7022}
7023
7024void Assembler::mov(Condition cond,
7025 EncodingSize size,
7026 Register rd,
7027 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007028 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007029 CheckIT(cond);
7030 if (operand.IsImmediateShiftedRegister()) {
7031 Register rm = operand.GetBaseRegister();
7032 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007033 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007034 // MOV{<c>}{<q>} <Rd>, <Rm> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007035 if (!size.IsWide() &&
7036 ((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
7037 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007038 EmitT32_16(0x4600 | (rd.GetCode() & 0x7) |
7039 ((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
7040 AdvanceIT();
7041 return;
7042 }
7043 }
7044 }
7045 Shift shift = operand.GetShift();
7046 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007047 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007048 // MOV<c>{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7049 if (InITBlock() && !size.IsWide() && rd.IsLow() &&
7050 shift.IsValidAmount(amount) && rm.IsLow() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007051 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR)) &&
7052 ((!shift.Is(LSL) || (amount != 0)) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007053 uint32_t amount_ = amount % 32;
7054 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7055 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7056 AdvanceIT();
7057 return;
7058 }
7059 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007060 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7061 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007062 uint32_t amount_ = amount % 32;
7063 EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7064 (operand.GetTypeEncodingValue() << 4) |
7065 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7066 AdvanceIT();
7067 return;
7068 }
7069 } else {
7070 // MOV{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7071 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7072 uint32_t amount_ = amount % 32;
7073 EmitA32(0x01a00000U | (cond.GetCondition() << 28) |
7074 (rd.GetCode() << 12) | rm.GetCode() |
7075 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7076 return;
7077 }
7078 }
7079 }
7080 if (operand.IsRegisterShiftedRegister()) {
7081 Register rm = operand.GetBaseRegister();
7082 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007083 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007084 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007085 // MOV<c>{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7086 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007087 shift.IsASR() && rs.IsLow()) {
7088 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007089 AdvanceIT();
7090 return;
7091 }
7092 // MOV<c>{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7093 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007094 shift.IsLSL() && rs.IsLow()) {
7095 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007096 AdvanceIT();
7097 return;
7098 }
7099 // MOV<c>{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7100 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007101 shift.IsLSR() && rs.IsLow()) {
7102 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007103 AdvanceIT();
7104 return;
7105 }
7106 // MOV<c>{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7107 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007108 shift.IsROR() && rs.IsLow()) {
7109 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007110 AdvanceIT();
7111 return;
7112 }
7113 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
Vincent Belliard942e3b72016-11-29 15:50:14 -08007114 if (!size.IsNarrow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007115 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007116 EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007117 (shift.GetType() << 21) | rs.GetCode());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007118 AdvanceIT();
7119 return;
7120 }
7121 } else {
7122 // MOV{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007123 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007124 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007125 EmitA32(0x01a00010U | (cond.GetCondition() << 28) |
7126 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007127 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007128 return;
7129 }
7130 }
7131 }
7132 if (operand.IsImmediate()) {
7133 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007134 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007135 ImmediateT32 immediate_t32(imm);
7136 // MOV<c>{<q>} <Rd>, #<imm8> ; T1
7137 if (InITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7138 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7139 AdvanceIT();
7140 return;
7141 }
7142 // MOV{<c>}{<q>} <Rd>, #<const> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007143 if (!size.IsNarrow() && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007144 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007145 EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
7146 (immediate_t32.GetEncodingValue() & 0xff) |
7147 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7148 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7149 AdvanceIT();
7150 return;
7151 }
7152 // MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
Vincent Belliardd17e3482016-11-22 15:46:43 -08007153 if (!size.IsNarrow() && (imm <= 65535) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007154 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007155 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7156 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7157 ((imm & 0xf000) << 4));
7158 AdvanceIT();
7159 return;
7160 }
7161 } else {
7162 ImmediateA32 immediate_a32(imm);
7163 // MOV{<c>}{<q>} <Rd>, #<const> ; A1
7164 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7165 EmitA32(0x03a00000U | (cond.GetCondition() << 28) |
7166 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7167 return;
7168 }
7169 // MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007170 if ((imm <= 65535) && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007171 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007172 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7173 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7174 return;
7175 }
7176 }
7177 }
7178 Delegate(kMov, &Assembler::mov, cond, size, rd, operand);
7179}
7180
7181void Assembler::movs(Condition cond,
7182 EncodingSize size,
7183 Register rd,
7184 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007186 CheckIT(cond);
7187 if (operand.IsImmediateShiftedRegister()) {
7188 Register rm = operand.GetBaseRegister();
7189 Shift shift = operand.GetShift();
7190 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007191 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007192 // MOVS{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
7193 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() &&
7194 shift.IsValidAmount(amount) && rm.IsLow() &&
7195 (shift.Is(LSL) || shift.Is(LSR) || shift.Is(ASR))) {
7196 uint32_t amount_ = amount % 32;
7197 EmitT32_16(0x0000 | rd.GetCode() | (rm.GetCode() << 3) |
7198 (operand.GetTypeEncodingValue() << 11) | (amount_ << 6));
7199 AdvanceIT();
7200 return;
7201 }
7202 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007203 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7204 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007205 uint32_t amount_ = amount % 32;
7206 EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7207 (operand.GetTypeEncodingValue() << 4) |
7208 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7209 AdvanceIT();
7210 return;
7211 }
7212 } else {
7213 // MOVS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007214 if (shift.IsValidAmount(amount) && cond.IsNotNever() &&
7215 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007216 uint32_t amount_ = amount % 32;
7217 EmitA32(0x01b00000U | (cond.GetCondition() << 28) |
7218 (rd.GetCode() << 12) | rm.GetCode() |
7219 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7220 return;
7221 }
7222 }
7223 }
7224 if (operand.IsRegisterShiftedRegister()) {
7225 Register rm = operand.GetBaseRegister();
7226 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007227 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007228 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007229 // MOVS{<q>} <Rdm>, <Rdm>, ASR <Rs> ; T1
7230 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007231 shift.IsASR() && rs.IsLow()) {
7232 EmitT32_16(0x4100 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007233 AdvanceIT();
7234 return;
7235 }
7236 // MOVS{<q>} <Rdm>, <Rdm>, LSL <Rs> ; T1
7237 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007238 shift.IsLSL() && rs.IsLow()) {
7239 EmitT32_16(0x4080 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007240 AdvanceIT();
7241 return;
7242 }
7243 // MOVS{<q>} <Rdm>, <Rdm>, LSR <Rs> ; T1
7244 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007245 shift.IsLSR() && rs.IsLow()) {
7246 EmitT32_16(0x40c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007247 AdvanceIT();
7248 return;
7249 }
7250 // MOVS{<q>} <Rdm>, <Rdm>, ROR <Rs> ; T1
7251 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007252 shift.IsROR() && rs.IsLow()) {
7253 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007254 AdvanceIT();
7255 return;
7256 }
7257 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; T2
Vincent Belliard942e3b72016-11-29 15:50:14 -08007258 if (!size.IsNarrow() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007259 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007260 EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007261 (shift.GetType() << 21) | rs.GetCode());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007262 AdvanceIT();
7263 return;
7264 }
7265 } else {
7266 // MOVS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007267 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007268 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007269 EmitA32(0x01b00010U | (cond.GetCondition() << 28) |
7270 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007271 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007272 return;
7273 }
7274 }
7275 }
7276 if (operand.IsImmediate()) {
7277 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007278 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007279 ImmediateT32 immediate_t32(imm);
7280 // MOVS{<q>} <Rd>, #<imm8> ; T1
7281 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && (imm <= 255)) {
7282 EmitT32_16(0x2000 | (rd.GetCode() << 8) | imm);
7283 AdvanceIT();
7284 return;
7285 }
7286 // MOVS{<c>}{<q>} <Rd>, #<const> ; T2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007287 if (!size.IsNarrow() && immediate_t32.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007288 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007289 EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
7290 (immediate_t32.GetEncodingValue() & 0xff) |
7291 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7292 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7293 AdvanceIT();
7294 return;
7295 }
7296 } else {
7297 ImmediateA32 immediate_a32(imm);
7298 // MOVS{<c>}{<q>} <Rd>, #<const> ; A1
7299 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7300 EmitA32(0x03b00000U | (cond.GetCondition() << 28) |
7301 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7302 return;
7303 }
7304 }
7305 }
7306 Delegate(kMovs, &Assembler::movs, cond, size, rd, operand);
7307}
7308
7309void Assembler::movt(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007310 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007311 CheckIT(cond);
7312 if (operand.IsImmediate()) {
7313 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007314 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007315 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007316 if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007317 EmitT32_32(0xf2c00000U | (rd.GetCode() << 8) | (imm & 0xff) |
7318 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7319 ((imm & 0xf000) << 4));
7320 AdvanceIT();
7321 return;
7322 }
7323 } else {
7324 // MOVT{<c>}{<q>} <Rd>, #<imm16> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08007325 if ((imm <= 65535) && cond.IsNotNever() &&
7326 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007327 EmitA32(0x03400000U | (cond.GetCondition() << 28) |
7328 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7329 return;
7330 }
7331 }
7332 }
7333 Delegate(kMovt, &Assembler::movt, cond, rd, operand);
7334}
7335
7336void Assembler::movw(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007337 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007338 CheckIT(cond);
7339 if (operand.IsImmediate()) {
7340 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007341 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007342 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
Vincent Belliard942e3b72016-11-29 15:50:14 -08007343 if ((imm <= 65535) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007344 EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
7345 ((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
7346 ((imm & 0xf000) << 4));
7347 AdvanceIT();
7348 return;
7349 }
7350 } else {
7351 // MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
Vincent Belliardd17e3482016-11-22 15:46:43 -08007352 if ((imm <= 65535) && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -08007353 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007354 EmitA32(0x03000000U | (cond.GetCondition() << 28) |
7355 (rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
7356 return;
7357 }
7358 }
7359 }
7360 Delegate(kMovw, &Assembler::movw, cond, rd, operand);
7361}
7362
7363void Assembler::mrs(Condition cond, Register rd, SpecialRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007364 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007365 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007366 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007367 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007368 if ((!rd.IsPC() || AllowUnpredictable())) {
7369 EmitT32_32(0xf3ef8000U | (rd.GetCode() << 8) | (spec_reg.GetReg() << 20));
7370 AdvanceIT();
7371 return;
7372 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007373 } else {
7374 // MRS{<c>}{<q>} <Rd>, <spec_reg> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007375 if (cond.IsNotNever() && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007376 EmitA32(0x010f0000U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
7377 (spec_reg.GetReg() << 22));
7378 return;
7379 }
7380 }
7381 Delegate(kMrs, &Assembler::mrs, cond, rd, spec_reg);
7382}
7383
7384void Assembler::msr(Condition cond,
7385 MaskedSpecialRegister spec_reg,
7386 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007387 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007388 CheckIT(cond);
7389 if (operand.IsImmediate()) {
7390 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007391 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007392 ImmediateA32 immediate_a32(imm);
7393 // MSR{<c>}{<q>} <spec_reg>, #<imm> ; A1
7394 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7395 EmitA32(0x0320f000U | (cond.GetCondition() << 28) |
7396 ((spec_reg.GetReg() & 0xf) << 16) |
7397 ((spec_reg.GetReg() & 0x10) << 18) |
7398 immediate_a32.GetEncodingValue());
7399 return;
7400 }
7401 }
7402 }
7403 if (operand.IsPlainRegister()) {
7404 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007405 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007406 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007407 if ((!rn.IsPC() || AllowUnpredictable())) {
7408 EmitT32_32(0xf3808000U | ((spec_reg.GetReg() & 0xf) << 8) |
7409 ((spec_reg.GetReg() & 0x10) << 16) | (rn.GetCode() << 16));
7410 AdvanceIT();
7411 return;
7412 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01007413 } else {
7414 // MSR{<c>}{<q>} <spec_reg>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007415 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007416 EmitA32(0x0120f000U | (cond.GetCondition() << 28) |
7417 ((spec_reg.GetReg() & 0xf) << 16) |
7418 ((spec_reg.GetReg() & 0x10) << 18) | rn.GetCode());
7419 return;
7420 }
7421 }
7422 }
7423 Delegate(kMsr, &Assembler::msr, cond, spec_reg, operand);
7424}
7425
7426void Assembler::mul(
7427 Condition cond, EncodingSize size, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007428 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007429 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007430 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007431 // MUL<c>{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7432 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rn.IsLow() &&
7433 rm.IsLow()) {
7434 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7435 AdvanceIT();
7436 return;
7437 }
7438 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007439 if (!size.IsNarrow() &&
7440 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007441 EmitT32_32(0xfb00f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7442 rm.GetCode());
7443 AdvanceIT();
7444 return;
7445 }
7446 } else {
7447 // MUL{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007448 if (cond.IsNotNever() &&
7449 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007450 EmitA32(0x00000090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7451 rn.GetCode() | (rm.GetCode() << 8));
7452 return;
7453 }
7454 }
7455 Delegate(kMul, &Assembler::mul, cond, size, rd, rn, rm);
7456}
7457
7458void Assembler::muls(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007459 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007460 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007461 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007462 // MULS{<q>} <Rdm>, <Rn>, {<Rdm>} ; T1
7463 if (OutsideITBlock() && rd.Is(rm) && rn.IsLow() && rm.IsLow()) {
7464 EmitT32_16(0x4340 | rd.GetCode() | (rn.GetCode() << 3));
7465 AdvanceIT();
7466 return;
7467 }
7468 } else {
7469 // MULS{<c>}{<q>} <Rd>, <Rn>, {<Rm>} ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007470 if (cond.IsNotNever() &&
7471 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007472 EmitA32(0x00100090U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
7473 rn.GetCode() | (rm.GetCode() << 8));
7474 return;
7475 }
7476 }
7477 Delegate(kMuls, &Assembler::muls, cond, rd, rn, rm);
7478}
7479
7480void Assembler::mvn(Condition cond,
7481 EncodingSize size,
7482 Register rd,
7483 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007484 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007485 CheckIT(cond);
7486 if (operand.IsImmediate()) {
7487 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007488 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007489 ImmediateT32 immediate_t32(imm);
7490 // MVN{<c>}{<q>} <Rd>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007491 if (!size.IsNarrow() && immediate_t32.IsValid() &&
7492 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007493 EmitT32_32(0xf06f0000U | (rd.GetCode() << 8) |
7494 (immediate_t32.GetEncodingValue() & 0xff) |
7495 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7496 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7497 AdvanceIT();
7498 return;
7499 }
7500 } else {
7501 ImmediateA32 immediate_a32(imm);
7502 // MVN{<c>}{<q>} <Rd>, #<const> ; A1
7503 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7504 EmitA32(0x03e00000U | (cond.GetCondition() << 28) |
7505 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7506 return;
7507 }
7508 }
7509 }
7510 if (operand.IsImmediateShiftedRegister()) {
7511 Register rm = operand.GetBaseRegister();
7512 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007513 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007514 // MVN<c>{<q>} <Rd>, <Rm> ; T1
7515 if (InITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7516 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7517 AdvanceIT();
7518 return;
7519 }
7520 }
7521 }
7522 Shift shift = operand.GetShift();
7523 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007524 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007525 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007526 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7527 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007528 uint32_t amount_ = amount % 32;
7529 EmitT32_32(0xea6f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7530 (operand.GetTypeEncodingValue() << 4) |
7531 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7532 AdvanceIT();
7533 return;
7534 }
7535 } else {
7536 // MVN{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7537 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7538 uint32_t amount_ = amount % 32;
7539 EmitA32(0x01e00000U | (cond.GetCondition() << 28) |
7540 (rd.GetCode() << 12) | rm.GetCode() |
7541 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7542 return;
7543 }
7544 }
7545 }
7546 if (operand.IsRegisterShiftedRegister()) {
7547 Register rm = operand.GetBaseRegister();
7548 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007549 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007550 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007551 // MVN{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007552 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007553 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007554 EmitA32(0x01e00010U | (cond.GetCondition() << 28) |
7555 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007556 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007557 return;
7558 }
7559 }
7560 }
7561 Delegate(kMvn, &Assembler::mvn, cond, size, rd, operand);
7562}
7563
7564void Assembler::mvns(Condition cond,
7565 EncodingSize size,
7566 Register rd,
7567 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007568 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007569 CheckIT(cond);
7570 if (operand.IsImmediate()) {
7571 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007572 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007573 ImmediateT32 immediate_t32(imm);
7574 // MVNS{<c>}{<q>} <Rd>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007575 if (!size.IsNarrow() && immediate_t32.IsValid() &&
7576 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007577 EmitT32_32(0xf07f0000U | (rd.GetCode() << 8) |
7578 (immediate_t32.GetEncodingValue() & 0xff) |
7579 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7580 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7581 AdvanceIT();
7582 return;
7583 }
7584 } else {
7585 ImmediateA32 immediate_a32(imm);
7586 // MVNS{<c>}{<q>} <Rd>, #<const> ; A1
7587 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7588 EmitA32(0x03f00000U | (cond.GetCondition() << 28) |
7589 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
7590 return;
7591 }
7592 }
7593 }
7594 if (operand.IsImmediateShiftedRegister()) {
7595 Register rm = operand.GetBaseRegister();
7596 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007597 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007598 // MVNS{<q>} <Rd>, <Rm> ; T1
7599 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rm.IsLow()) {
7600 EmitT32_16(0x43c0 | rd.GetCode() | (rm.GetCode() << 3));
7601 AdvanceIT();
7602 return;
7603 }
7604 }
7605 }
7606 Shift shift = operand.GetShift();
7607 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007608 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007609 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007610 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
7611 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007612 uint32_t amount_ = amount % 32;
7613 EmitT32_32(0xea7f0000U | (rd.GetCode() << 8) | rm.GetCode() |
7614 (operand.GetTypeEncodingValue() << 4) |
7615 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7616 AdvanceIT();
7617 return;
7618 }
7619 } else {
7620 // MVNS{<c>}{<q>} <Rd>, <Rm> {, <shift> #<amount> } ; A1
7621 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7622 uint32_t amount_ = amount % 32;
7623 EmitA32(0x01f00000U | (cond.GetCondition() << 28) |
7624 (rd.GetCode() << 12) | rm.GetCode() |
7625 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7626 return;
7627 }
7628 }
7629 }
7630 if (operand.IsRegisterShiftedRegister()) {
7631 Register rm = operand.GetBaseRegister();
7632 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007633 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007634 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007635 // MVNS{<c>}{<q>} <Rd>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007636 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +00007637 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007638 EmitA32(0x01f00010U | (cond.GetCondition() << 28) |
7639 (rd.GetCode() << 12) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007640 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007641 return;
7642 }
7643 }
7644 }
7645 Delegate(kMvns, &Assembler::mvns, cond, size, rd, operand);
7646}
7647
7648void Assembler::nop(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007649 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007650 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007652 // NOP{<c>}{<q>} ; T1
7653 if (!size.IsWide()) {
7654 EmitT32_16(0xbf00);
7655 AdvanceIT();
7656 return;
7657 }
7658 // NOP{<c>}.W ; T2
7659 if (!size.IsNarrow()) {
7660 EmitT32_32(0xf3af8000U);
7661 AdvanceIT();
7662 return;
7663 }
7664 } else {
7665 // NOP{<c>}{<q>} ; A1
7666 if (cond.IsNotNever()) {
7667 EmitA32(0x0320f000U | (cond.GetCondition() << 28));
7668 return;
7669 }
7670 }
7671 Delegate(kNop, &Assembler::nop, cond, size);
7672}
7673
7674void Assembler::orn(Condition cond,
7675 Register rd,
7676 Register rn,
7677 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007678 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007679 CheckIT(cond);
7680 if (operand.IsImmediate()) {
7681 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007682 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007683 ImmediateT32 immediate_t32(imm);
7684 // ORN{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007685 if (immediate_t32.IsValid() && !rn.Is(pc) &&
7686 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007687 EmitT32_32(0xf0600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7688 (immediate_t32.GetEncodingValue() & 0xff) |
7689 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7690 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7691 AdvanceIT();
7692 return;
7693 }
7694 }
7695 }
7696 if (operand.IsImmediateShiftedRegister()) {
7697 Register rm = operand.GetBaseRegister();
7698 Shift shift = operand.GetShift();
7699 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007700 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007701 // ORN{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007702 if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7703 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007704 uint32_t amount_ = amount % 32;
7705 EmitT32_32(0xea600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7706 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7707 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7708 AdvanceIT();
7709 return;
7710 }
7711 }
7712 }
7713 Delegate(kOrn, &Assembler::orn, cond, rd, rn, operand);
7714}
7715
7716void Assembler::orns(Condition cond,
7717 Register rd,
7718 Register rn,
7719 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007721 CheckIT(cond);
7722 if (operand.IsImmediate()) {
7723 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007724 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007725 ImmediateT32 immediate_t32(imm);
7726 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007727 if (immediate_t32.IsValid() && !rn.Is(pc) &&
7728 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007729 EmitT32_32(0xf0700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7730 (immediate_t32.GetEncodingValue() & 0xff) |
7731 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7732 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7733 AdvanceIT();
7734 return;
7735 }
7736 }
7737 }
7738 if (operand.IsImmediateShiftedRegister()) {
7739 Register rm = operand.GetBaseRegister();
7740 Shift shift = operand.GetShift();
7741 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007743 // ORNS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007744 if (shift.IsValidAmount(amount) && !rn.Is(pc) &&
7745 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007746 uint32_t amount_ = amount % 32;
7747 EmitT32_32(0xea700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7748 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7749 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7750 AdvanceIT();
7751 return;
7752 }
7753 }
7754 }
7755 Delegate(kOrns, &Assembler::orns, cond, rd, rn, operand);
7756}
7757
7758void Assembler::orr(Condition cond,
7759 EncodingSize size,
7760 Register rd,
7761 Register rn,
7762 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007763 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007764 CheckIT(cond);
7765 if (operand.IsImmediate()) {
7766 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007767 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007768 ImmediateT32 immediate_t32(imm);
7769 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007770 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7771 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007772 EmitT32_32(0xf0400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7773 (immediate_t32.GetEncodingValue() & 0xff) |
7774 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7775 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7776 AdvanceIT();
7777 return;
7778 }
7779 } else {
7780 ImmediateA32 immediate_a32(imm);
7781 // ORR{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7782 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7783 EmitA32(0x03800000U | (cond.GetCondition() << 28) |
7784 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7785 immediate_a32.GetEncodingValue());
7786 return;
7787 }
7788 }
7789 }
7790 if (operand.IsImmediateShiftedRegister()) {
7791 Register rm = operand.GetBaseRegister();
7792 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007793 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007794 // ORR<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7795 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7796 rm.IsLow()) {
7797 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7798 AdvanceIT();
7799 return;
7800 }
7801 }
7802 }
7803 Shift shift = operand.GetShift();
7804 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007806 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007807 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7808 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007809 uint32_t amount_ = amount % 32;
7810 EmitT32_32(0xea400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7811 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7812 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7813 AdvanceIT();
7814 return;
7815 }
7816 } else {
7817 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7818 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7819 uint32_t amount_ = amount % 32;
7820 EmitA32(0x01800000U | (cond.GetCondition() << 28) |
7821 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7822 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7823 return;
7824 }
7825 }
7826 }
7827 if (operand.IsRegisterShiftedRegister()) {
7828 Register rm = operand.GetBaseRegister();
7829 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007830 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007831 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007832 // ORR{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00007833 if (cond.IsNotNever() &&
7834 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7835 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007836 EmitA32(0x01800010U | (cond.GetCondition() << 28) |
7837 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007838 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007839 return;
7840 }
7841 }
7842 }
7843 Delegate(kOrr, &Assembler::orr, cond, size, rd, rn, operand);
7844}
7845
7846void Assembler::orrs(Condition cond,
7847 EncodingSize size,
7848 Register rd,
7849 Register rn,
7850 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007851 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007852 CheckIT(cond);
7853 if (operand.IsImmediate()) {
7854 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007855 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007856 ImmediateT32 immediate_t32(imm);
7857 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007858 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(pc) &&
7859 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007860 EmitT32_32(0xf0500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7861 (immediate_t32.GetEncodingValue() & 0xff) |
7862 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
7863 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
7864 AdvanceIT();
7865 return;
7866 }
7867 } else {
7868 ImmediateA32 immediate_a32(imm);
7869 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
7870 if (immediate_a32.IsValid() && cond.IsNotNever()) {
7871 EmitA32(0x03900000U | (cond.GetCondition() << 28) |
7872 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
7873 immediate_a32.GetEncodingValue());
7874 return;
7875 }
7876 }
7877 }
7878 if (operand.IsImmediateShiftedRegister()) {
7879 Register rm = operand.GetBaseRegister();
7880 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007881 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007882 // ORRS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
7883 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
7884 rm.IsLow()) {
7885 EmitT32_16(0x4300 | rd.GetCode() | (rm.GetCode() << 3));
7886 AdvanceIT();
7887 return;
7888 }
7889 }
7890 }
7891 Shift shift = operand.GetShift();
7892 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007893 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007894 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00007895 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(pc) &&
7896 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007897 uint32_t amount_ = amount % 32;
7898 EmitT32_32(0xea500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7899 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
7900 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
7901 AdvanceIT();
7902 return;
7903 }
7904 } else {
7905 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
7906 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
7907 uint32_t amount_ = amount % 32;
7908 EmitA32(0x01900000U | (cond.GetCondition() << 28) |
7909 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7910 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
7911 return;
7912 }
7913 }
7914 }
7915 if (operand.IsRegisterShiftedRegister()) {
7916 Register rm = operand.GetBaseRegister();
7917 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00007918 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007919 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007920 // ORRS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00007921 if (cond.IsNotNever() &&
7922 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
7923 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007924 EmitA32(0x01900010U | (cond.GetCondition() << 28) |
7925 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00007926 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01007927 return;
7928 }
7929 }
7930 }
7931 Delegate(kOrrs, &Assembler::orrs, cond, size, rd, rn, operand);
7932}
7933
7934void Assembler::pkhbt(Condition cond,
7935 Register rd,
7936 Register rn,
7937 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007938 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007939 CheckIT(cond);
7940 if (operand.IsImmediateShiftedRegister()) {
7941 Register rm = operand.GetBaseRegister();
7942 Shift shift = operand.GetShift();
7943 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007944 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007945 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007946 if (shift.IsLSL() && shift.IsValidAmount(amount) &&
7947 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007948 EmitT32_32(0xeac00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7949 rm.GetCode() | ((amount & 0x3) << 6) |
7950 ((amount & 0x1c) << 10));
7951 AdvanceIT();
7952 return;
7953 }
7954 } else {
7955 // PKHBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, LSL #<imm> } ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007956 if (shift.IsLSL() && shift.IsValidAmount(amount) && cond.IsNotNever() &&
7957 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007958 EmitA32(0x06800010U | (cond.GetCondition() << 28) |
7959 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7960 (amount << 7));
7961 return;
7962 }
7963 }
7964 }
7965 Delegate(kPkhbt, &Assembler::pkhbt, cond, rd, rn, operand);
7966}
7967
7968void Assembler::pkhtb(Condition cond,
7969 Register rd,
7970 Register rn,
7971 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07007972 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01007973 CheckIT(cond);
7974 if (operand.IsImmediateShiftedRegister()) {
7975 Register rm = operand.GetBaseRegister();
7976 Shift shift = operand.GetShift();
7977 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01007978 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007979 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00007980 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
7981 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007982 uint32_t amount_ = amount % 32;
7983 EmitT32_32(0xeac00020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
7984 rm.GetCode() | ((amount_ & 0x3) << 6) |
7985 ((amount_ & 0x1c) << 10));
7986 AdvanceIT();
7987 return;
7988 }
7989 } else {
7990 // PKHTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ASR #<imm> } ; A1
7991 if ((shift.IsASR() || (amount == 0)) && shift.IsValidAmount(amount) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00007992 cond.IsNotNever() &&
7993 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01007994 uint32_t amount_ = amount % 32;
7995 EmitA32(0x06800050U | (cond.GetCondition() << 28) |
7996 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
7997 (amount_ << 7));
7998 return;
7999 }
8000 }
8001 }
8002 Delegate(kPkhtb, &Assembler::pkhtb, cond, rd, rn, operand);
8003}
8004
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008005void Assembler::pld(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008006 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008007 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008008 Location::Offset offset =
8009 location->IsBound()
8010 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01008011 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8012 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008013 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008014 // PLD{<c>}{<q>} <label> ; T1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008015 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8016 !location->IsBound())) {
8017 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008018 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008019 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008020 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008021 Location::Offset pc,
8022 const Location* location) const VIXL_OVERRIDE {
8023 pc += kT32PcDelta;
8024 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008025 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008026 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008027 int32_t target = abs(offset) | (U << 12);
8028 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8029 }
8030 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008031 EmitT32_32(Link(0xf81ff000U, location, immop, &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008032 AdvanceIT();
8033 return;
8034 }
8035 } else {
8036 // PLD{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008037 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8038 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008039 if (cond.Is(al)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008040 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008041 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008042 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008043 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008044 Location::Offset pc,
8045 const Location* location) const
8046 VIXL_OVERRIDE {
8047 pc += kA32PcDelta;
8048 Location::Offset offset =
8049 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008050 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008051 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008052 int32_t target = abs(offset) | (U << 12);
8053 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8054 }
8055 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008056 EmitA32(Link(0xf55ff000U, location, immop, &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008057 return;
8058 }
8059 }
8060 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008061 Delegate(kPld, &Assembler::pld, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008062}
8063
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008064bool Assembler::pld_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008065 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008066 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008067 VIXL_ASSERT(!location->IsBound());
8068 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008069 USE(cond);
8070 if (IsUsingT32()) {
8071 // PLD{<c>}{<q>} <label> ; T1
8072 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008073 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008074 return true;
8075 }
8076 } else {
8077 // PLD{<c>}{<q>} <label> ; A1
8078 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008079 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008080 return true;
8081 }
8082 }
8083 return false;
8084}
8085
Alexandre Ramesd3832962016-07-04 15:03:43 +01008086void Assembler::pld(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008087 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008088 CheckIT(cond);
8089 if (operand.IsImmediate()) {
8090 Register rn = operand.GetBaseRegister();
8091 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008092 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008093 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm>] ; T1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008094 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8095 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008096 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8097 uint32_t offset_ = abs(offset);
8098 EmitT32_32(0xf81ff000U | offset_ | (sign << 23));
8099 AdvanceIT();
8100 return;
8101 }
8102 } else {
8103 // PLD{<c>}{<q>} [PC, #<_plusminus_><imm_1>] ; A1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008104 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8105 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008106 if (cond.Is(al)) {
8107 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8108 uint32_t offset_ = abs(offset);
8109 EmitA32(0xf55ff000U | offset_ | (sign << 23));
8110 return;
8111 }
8112 }
8113 }
8114 }
8115 if (operand.IsImmediate()) {
8116 Register rn = operand.GetBaseRegister();
8117 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008118 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008119 // PLD{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008120 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8121 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008122 EmitT32_32(0xf890f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8123 AdvanceIT();
8124 return;
8125 }
8126 // PLD{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008127 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8128 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008129 EmitT32_32(0xf810fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8130 AdvanceIT();
8131 return;
8132 }
8133 } else {
8134 // PLD{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008135 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008136 ((rn.GetCode() & 0xf) != 0xf)) {
8137 if (cond.Is(al)) {
8138 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8139 uint32_t offset_ = abs(offset);
8140 EmitA32(0xf550f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8141 return;
8142 }
8143 }
8144 }
8145 }
8146 if (operand.IsShiftedRegister()) {
8147 Register rn = operand.GetBaseRegister();
8148 Sign sign = operand.GetSign();
8149 Register rm = operand.GetOffsetRegister();
8150 Shift shift = operand.GetShift();
8151 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008152 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008153 // PLD{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008154 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008155 ((rn.GetCode() & 0xf) != 0xf) &&
8156 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008157 EmitT32_32(0xf810f000U | (rn.GetCode() << 16) | rm.GetCode() |
8158 (amount << 4));
8159 AdvanceIT();
8160 return;
8161 }
8162 } else {
8163 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008164 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8165 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008166 if (cond.Is(al)) {
8167 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8168 uint32_t amount_ = amount % 32;
8169 EmitA32(0xf750f000U | (rn.GetCode() << 16) | rm.GetCode() |
8170 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8171 return;
8172 }
8173 }
8174 // PLD{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008175 if (shift.IsRRX() && operand.IsOffset() &&
8176 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008177 if (cond.Is(al)) {
8178 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8179 EmitA32(0xf750f060U | (rn.GetCode() << 16) | rm.GetCode() |
8180 (sign_ << 23));
8181 return;
8182 }
8183 }
8184 }
8185 }
8186 Delegate(kPld, &Assembler::pld, cond, operand);
8187}
8188
8189void Assembler::pldw(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008190 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008191 CheckIT(cond);
8192 if (operand.IsImmediate()) {
8193 Register rn = operand.GetBaseRegister();
8194 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008195 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008196 // PLDW{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008197 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8198 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008199 EmitT32_32(0xf8b0f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8200 AdvanceIT();
8201 return;
8202 }
8203 // PLDW{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008204 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8205 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008206 EmitT32_32(0xf830fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8207 AdvanceIT();
8208 return;
8209 }
8210 } else {
8211 // PLDW{<c>}{<q>} [<Rn>{, #{+/-}<imm_2>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008212 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008213 ((rn.GetCode() & 0xf) != 0xf)) {
8214 if (cond.Is(al)) {
8215 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8216 uint32_t offset_ = abs(offset);
8217 EmitA32(0xf510f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8218 return;
8219 }
8220 }
8221 }
8222 }
8223 if (operand.IsShiftedRegister()) {
8224 Register rn = operand.GetBaseRegister();
8225 Sign sign = operand.GetSign();
8226 Register rm = operand.GetOffsetRegister();
8227 Shift shift = operand.GetShift();
8228 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008229 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008230 // PLDW{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008231 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008232 ((rn.GetCode() & 0xf) != 0xf) &&
8233 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008234 EmitT32_32(0xf830f000U | (rn.GetCode() << 16) | rm.GetCode() |
8235 (amount << 4));
8236 AdvanceIT();
8237 return;
8238 }
8239 } else {
8240 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008241 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8242 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008243 if (cond.Is(al)) {
8244 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8245 uint32_t amount_ = amount % 32;
8246 EmitA32(0xf710f000U | (rn.GetCode() << 16) | rm.GetCode() |
8247 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8248 return;
8249 }
8250 }
8251 // PLDW{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008252 if (shift.IsRRX() && operand.IsOffset() &&
8253 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008254 if (cond.Is(al)) {
8255 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8256 EmitA32(0xf710f060U | (rn.GetCode() << 16) | rm.GetCode() |
8257 (sign_ << 23));
8258 return;
8259 }
8260 }
8261 }
8262 }
8263 Delegate(kPldw, &Assembler::pldw, cond, operand);
8264}
8265
8266void Assembler::pli(Condition cond, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008267 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008268 CheckIT(cond);
8269 if (operand.IsImmediate()) {
8270 Register rn = operand.GetBaseRegister();
8271 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008272 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008273 // PLI{<c>}{<q>} [<Rn>{, #{+}<imm>}] ; T1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008274 if ((offset >= 0) && (offset <= 4095) && operand.IsOffset() &&
8275 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008276 EmitT32_32(0xf990f000U | (rn.GetCode() << 16) | (offset & 0xfff));
8277 AdvanceIT();
8278 return;
8279 }
8280 // PLI{<c>}{<q>} [<Rn>{, #-<imm_1>}] ; T2
Vincent Belliard39b5e602016-11-18 12:13:55 -08008281 if ((-offset >= 0) && (-offset <= 255) && operand.IsOffset() &&
8282 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008283 EmitT32_32(0xf910fc00U | (rn.GetCode() << 16) | (-offset & 0xff));
8284 AdvanceIT();
8285 return;
8286 }
8287 } else {
8288 // PLI{<c>}{<q>} [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliard39b5e602016-11-18 12:13:55 -08008289 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +01008290 ((rn.GetCode() & 0xf) != 0xf)) {
8291 if (cond.Is(al)) {
8292 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8293 uint32_t offset_ = abs(offset);
8294 EmitA32(0xf450f000U | (rn.GetCode() << 16) | offset_ | (sign << 23));
8295 return;
8296 }
8297 }
8298 }
8299 }
8300 if (operand.IsImmediate()) {
8301 Register rn = operand.GetBaseRegister();
8302 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008303 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008304 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_2>] ; T3
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008305 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8306 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008307 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8308 uint32_t offset_ = abs(offset);
8309 EmitT32_32(0xf91ff000U | offset_ | (sign << 23));
8310 AdvanceIT();
8311 return;
8312 }
8313 } else {
8314 // PLI{<c>}{<q>} [PC, #<_plusminus_><imm_3>] ; A1
Vincent Belliard9fcf6d62016-11-17 11:13:19 -08008315 if ((offset >= -4095) && (offset <= 4095) && rn.Is(pc) &&
8316 operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008317 if (cond.Is(al)) {
8318 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
8319 uint32_t offset_ = abs(offset);
8320 EmitA32(0xf45ff000U | offset_ | (sign << 23));
8321 return;
8322 }
8323 }
8324 }
8325 }
8326 if (operand.IsShiftedRegister()) {
8327 Register rn = operand.GetBaseRegister();
8328 Sign sign = operand.GetSign();
8329 Register rm = operand.GetOffsetRegister();
8330 Shift shift = operand.GetShift();
8331 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008332 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008333 // PLI{<c>}{<q>} [<Rn>, {+}<Rm>{, LSL #<amount>}] ; T1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -08008334 if (sign.IsPlus() && shift.IsLSL() && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00008335 ((rn.GetCode() & 0xf) != 0xf) &&
8336 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008337 EmitT32_32(0xf910f000U | (rn.GetCode() << 16) | rm.GetCode() |
8338 (amount << 4));
8339 AdvanceIT();
8340 return;
8341 }
8342 } else {
8343 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>, RRX] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008344 if (shift.IsRRX() && operand.IsOffset() &&
8345 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008346 if (cond.Is(al)) {
8347 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8348 EmitA32(0xf650f060U | (rn.GetCode() << 16) | rm.GetCode() |
8349 (sign_ << 23));
8350 return;
8351 }
8352 }
8353 // PLI{<c>}{<q>} [<Rn>, {+/-}<Rm>{, <shift> #<amount_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008354 if (!shift.IsRRX() && shift.IsValidAmount(amount) && operand.IsOffset() &&
8355 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008356 if (cond.Is(al)) {
8357 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
8358 uint32_t amount_ = amount % 32;
8359 EmitA32(0xf650f000U | (rn.GetCode() << 16) | rm.GetCode() |
8360 (sign_ << 23) | (shift.GetType() << 5) | (amount_ << 7));
8361 return;
8362 }
8363 }
8364 }
8365 }
8366 Delegate(kPli, &Assembler::pli, cond, operand);
8367}
8368
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008369void Assembler::pli(Condition cond, Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008370 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008371 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008372 Location::Offset offset =
8373 location->IsBound()
8374 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +01008375 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
8376 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008377 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008378 // PLI{<c>}{<q>} <label> ; T3
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008379 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8380 !location->IsBound())) {
8381 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008382 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008383 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008384 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008385 Location::Offset pc,
8386 const Location* location) const VIXL_OVERRIDE {
8387 pc += kT32PcDelta;
8388 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008389 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008390 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008391 int32_t target = abs(offset) | (U << 12);
8392 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8393 }
8394 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008395 EmitT32_32(Link(0xf91ff000U, location, immop, &kT32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008396 AdvanceIT();
8397 return;
8398 }
8399 } else {
8400 // PLI{<c>}{<q>} <label> ; A1
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008401 if (((location->IsBound() && (offset >= -4095) && (offset <= 4095)) ||
8402 !location->IsBound())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008403 if (cond.Is(al)) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008404 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008405 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008406 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +00008407 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008408 Location::Offset pc,
8409 const Location* location) const
8410 VIXL_OVERRIDE {
8411 pc += kA32PcDelta;
8412 Location::Offset offset =
8413 location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008414 VIXL_ASSERT((offset >= -4095) && (offset <= 4095));
Georgia Kouvelifc61fb62017-01-12 13:40:38 +00008415 uint32_t U = (offset >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008416 int32_t target = abs(offset) | (U << 12);
8417 return instr | (target & 0xfff) | ((target & 0x1000) << 11);
8418 }
8419 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -07008420 EmitA32(Link(0xf45ff000U, location, immop, &kA32FarDataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +01008421 return;
8422 }
8423 }
8424 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008425 Delegate(kPli, &Assembler::pli, cond, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +01008426}
8427
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008428bool Assembler::pli_info(Condition cond,
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008429 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008430 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +01008431 VIXL_ASSERT(!location->IsBound());
8432 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008433 USE(cond);
8434 if (IsUsingT32()) {
8435 // PLI{<c>}{<q>} <label> ; T3
8436 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008437 *info = &kT32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008438 return true;
8439 }
8440 } else {
8441 // PLI{<c>}{<q>} <label> ; A1
8442 if (true) {
Vincent Belliardac285442017-05-16 09:26:45 -07008443 *info = &kA32FarDataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +01008444 return true;
8445 }
8446 }
8447 return false;
8448}
8449
Alexandre Ramesd3832962016-07-04 15:03:43 +01008450void Assembler::pop(Condition cond, EncodingSize size, RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008451 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008452 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008453 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008454 // POP{<c>}{<q>} <registers> ; T1
8455 if (!size.IsWide() && ((registers.GetList() & ~0x80ff) == 0)) {
8456 EmitT32_16(0xbc00 | (GetRegisterListEncoding(registers, 15, 1) << 8) |
8457 GetRegisterListEncoding(registers, 0, 8));
8458 AdvanceIT();
8459 return;
8460 }
8461 // POP{<c>}{<q>} <registers> ; T2
8462 if (!size.IsNarrow() && ((registers.GetList() & ~0xdfff) == 0)) {
8463 EmitT32_32(0xe8bd0000U |
8464 (GetRegisterListEncoding(registers, 15, 1) << 15) |
8465 (GetRegisterListEncoding(registers, 14, 1) << 14) |
8466 GetRegisterListEncoding(registers, 0, 13));
8467 AdvanceIT();
8468 return;
8469 }
8470 } else {
8471 // POP{<c>}{<q>} <registers> ; A1
8472 if (cond.IsNotNever()) {
8473 EmitA32(0x08bd0000U | (cond.GetCondition() << 28) |
8474 GetRegisterListEncoding(registers, 0, 16));
8475 return;
8476 }
8477 }
8478 Delegate(kPop, &Assembler::pop, cond, size, registers);
8479}
8480
8481void Assembler::pop(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008482 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008483 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008484 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008485 // POP{<c>}{<q>} <single_register_list> ; T4
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008486 if (!size.IsNarrow() && ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) ||
8487 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008488 EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12));
8489 AdvanceIT();
8490 return;
8491 }
8492 } else {
8493 // POP{<c>}{<q>} <single_register_list> ; A1
8494 if (cond.IsNotNever()) {
8495 EmitA32(0x049d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8496 return;
8497 }
8498 }
8499 Delegate(kPop, &Assembler::pop, cond, size, rt);
8500}
8501
8502void Assembler::push(Condition cond,
8503 EncodingSize size,
8504 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008505 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008506 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008507 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008508 // PUSH{<c>}{<q>} <registers> ; T1
8509 if (!size.IsWide() && ((registers.GetList() & ~0x40ff) == 0)) {
8510 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
8511 GetRegisterListEncoding(registers, 0, 8));
8512 AdvanceIT();
8513 return;
8514 }
8515 // PUSH{<c>}{<q>} <registers> ; T1
8516 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0)) {
8517 EmitT32_32(0xe92d0000U |
8518 (GetRegisterListEncoding(registers, 14, 1) << 14) |
8519 GetRegisterListEncoding(registers, 0, 13));
8520 AdvanceIT();
8521 return;
8522 }
8523 } else {
8524 // PUSH{<c>}{<q>} <registers> ; A1
8525 if (cond.IsNotNever()) {
8526 EmitA32(0x092d0000U | (cond.GetCondition() << 28) |
8527 GetRegisterListEncoding(registers, 0, 16));
8528 return;
8529 }
8530 }
8531 Delegate(kPush, &Assembler::push, cond, size, registers);
8532}
8533
8534void Assembler::push(Condition cond, EncodingSize size, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008535 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008536 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008537 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008538 // PUSH{<c>}{<q>} <single_register_list> ; T4
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008539 if (!size.IsNarrow() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008540 EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12));
8541 AdvanceIT();
8542 return;
8543 }
8544 } else {
8545 // PUSH{<c>}{<q>} <single_register_list> ; A1
Vincent Belliard942e3b72016-11-29 15:50:14 -08008546 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008547 EmitA32(0x052d0004U | (cond.GetCondition() << 28) | (rt.GetCode() << 12));
8548 return;
8549 }
8550 }
8551 Delegate(kPush, &Assembler::push, cond, size, rt);
8552}
8553
8554void Assembler::qadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008555 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008556 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008557 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008558 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008559 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8560 EmitT32_32(0xfa80f080U | (rd.GetCode() << 8) | rm.GetCode() |
8561 (rn.GetCode() << 16));
8562 AdvanceIT();
8563 return;
8564 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008565 } else {
8566 // QADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008567 if (cond.IsNotNever() &&
8568 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008569 EmitA32(0x01000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8570 rm.GetCode() | (rn.GetCode() << 16));
8571 return;
8572 }
8573 }
8574 Delegate(kQadd, &Assembler::qadd, cond, rd, rm, rn);
8575}
8576
8577void Assembler::qadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008578 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008579 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008580 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008581 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008582 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8583 EmitT32_32(0xfa90f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8584 rm.GetCode());
8585 AdvanceIT();
8586 return;
8587 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008588 } else {
8589 // QADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008590 if (cond.IsNotNever() &&
8591 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008592 EmitA32(0x06200f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8593 (rn.GetCode() << 16) | rm.GetCode());
8594 return;
8595 }
8596 }
8597 Delegate(kQadd16, &Assembler::qadd16, cond, rd, rn, rm);
8598}
8599
8600void Assembler::qadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008601 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008602 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008603 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008604 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008605 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8606 EmitT32_32(0xfa80f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8607 rm.GetCode());
8608 AdvanceIT();
8609 return;
8610 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008611 } else {
8612 // QADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008613 if (cond.IsNotNever() &&
8614 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008615 EmitA32(0x06200f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8616 (rn.GetCode() << 16) | rm.GetCode());
8617 return;
8618 }
8619 }
8620 Delegate(kQadd8, &Assembler::qadd8, cond, rd, rn, rm);
8621}
8622
8623void Assembler::qasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008624 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008625 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008626 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008627 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008628 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8629 EmitT32_32(0xfaa0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8630 rm.GetCode());
8631 AdvanceIT();
8632 return;
8633 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008634 } else {
8635 // QASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008636 if (cond.IsNotNever() &&
8637 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008638 EmitA32(0x06200f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8639 (rn.GetCode() << 16) | rm.GetCode());
8640 return;
8641 }
8642 }
8643 Delegate(kQasx, &Assembler::qasx, cond, rd, rn, rm);
8644}
8645
8646void Assembler::qdadd(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008647 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008648 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008649 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008650 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008651 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8652 EmitT32_32(0xfa80f090U | (rd.GetCode() << 8) | rm.GetCode() |
8653 (rn.GetCode() << 16));
8654 AdvanceIT();
8655 return;
8656 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008657 } else {
8658 // QDADD{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008659 if (cond.IsNotNever() &&
8660 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008661 EmitA32(0x01400050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8662 rm.GetCode() | (rn.GetCode() << 16));
8663 return;
8664 }
8665 }
8666 Delegate(kQdadd, &Assembler::qdadd, cond, rd, rm, rn);
8667}
8668
8669void Assembler::qdsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008670 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008671 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008673 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008674 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8675 EmitT32_32(0xfa80f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8676 (rn.GetCode() << 16));
8677 AdvanceIT();
8678 return;
8679 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008680 } else {
8681 // QDSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008682 if (cond.IsNotNever() &&
8683 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008684 EmitA32(0x01600050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8685 rm.GetCode() | (rn.GetCode() << 16));
8686 return;
8687 }
8688 }
8689 Delegate(kQdsub, &Assembler::qdsub, cond, rd, rm, rn);
8690}
8691
8692void Assembler::qsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008693 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008694 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008695 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008696 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008697 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8698 EmitT32_32(0xfae0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8699 rm.GetCode());
8700 AdvanceIT();
8701 return;
8702 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008703 } else {
8704 // QSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008705 if (cond.IsNotNever() &&
8706 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008707 EmitA32(0x06200f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8708 (rn.GetCode() << 16) | rm.GetCode());
8709 return;
8710 }
8711 }
8712 Delegate(kQsax, &Assembler::qsax, cond, rd, rn, rm);
8713}
8714
8715void Assembler::qsub(Condition cond, Register rd, Register rm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008716 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008717 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008718 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008719 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008720 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8721 EmitT32_32(0xfa80f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8722 (rn.GetCode() << 16));
8723 AdvanceIT();
8724 return;
8725 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008726 } else {
8727 // QSUB{<c>}{<q>} {<Rd>}, <Rm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008728 if (cond.IsNotNever() &&
8729 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008730 EmitA32(0x01200050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8731 rm.GetCode() | (rn.GetCode() << 16));
8732 return;
8733 }
8734 }
8735 Delegate(kQsub, &Assembler::qsub, cond, rd, rm, rn);
8736}
8737
8738void Assembler::qsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008739 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008740 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008741 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008742 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008743 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8744 EmitT32_32(0xfad0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8745 rm.GetCode());
8746 AdvanceIT();
8747 return;
8748 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008749 } else {
8750 // QSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008751 if (cond.IsNotNever() &&
8752 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008753 EmitA32(0x06200f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8754 (rn.GetCode() << 16) | rm.GetCode());
8755 return;
8756 }
8757 }
8758 Delegate(kQsub16, &Assembler::qsub16, cond, rd, rn, rm);
8759}
8760
8761void Assembler::qsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008762 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008763 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008764 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008765 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008766 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8767 EmitT32_32(0xfac0f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
8768 rm.GetCode());
8769 AdvanceIT();
8770 return;
8771 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008772 } else {
8773 // QSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008774 if (cond.IsNotNever() &&
8775 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008776 EmitA32(0x06200ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8777 (rn.GetCode() << 16) | rm.GetCode());
8778 return;
8779 }
8780 }
8781 Delegate(kQsub8, &Assembler::qsub8, cond, rd, rn, rm);
8782}
8783
8784void Assembler::rbit(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008785 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008786 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008787 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008788 // RBIT{<c>}{<q>} <Rd>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008789 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
8790 EmitT32_32(0xfa90f0a0U | (rd.GetCode() << 8) | rm.GetCode() |
8791 (rm.GetCode() << 16));
8792 AdvanceIT();
8793 return;
8794 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01008795 } else {
8796 // RBIT{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008797 if (cond.IsNotNever() &&
8798 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008799 EmitA32(0x06ff0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8800 rm.GetCode());
8801 return;
8802 }
8803 }
8804 Delegate(kRbit, &Assembler::rbit, cond, rd, rm);
8805}
8806
8807void Assembler::rev(Condition cond,
8808 EncodingSize size,
8809 Register rd,
8810 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008811 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008812 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008813 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008814 // REV{<c>}{<q>} <Rd>, <Rm> ; T1
8815 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8816 EmitT32_16(0xba00 | rd.GetCode() | (rm.GetCode() << 3));
8817 AdvanceIT();
8818 return;
8819 }
8820 // REV{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008821 if (!size.IsNarrow() &&
8822 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008823 EmitT32_32(0xfa90f080U | (rd.GetCode() << 8) | rm.GetCode() |
8824 (rm.GetCode() << 16));
8825 AdvanceIT();
8826 return;
8827 }
8828 } else {
8829 // REV{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008830 if (cond.IsNotNever() &&
8831 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008832 EmitA32(0x06bf0f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8833 rm.GetCode());
8834 return;
8835 }
8836 }
8837 Delegate(kRev, &Assembler::rev, cond, size, rd, rm);
8838}
8839
8840void Assembler::rev16(Condition cond,
8841 EncodingSize size,
8842 Register rd,
8843 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008844 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008845 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008846 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008847 // REV16{<c>}{<q>} <Rd>, <Rm> ; T1
8848 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8849 EmitT32_16(0xba40 | rd.GetCode() | (rm.GetCode() << 3));
8850 AdvanceIT();
8851 return;
8852 }
8853 // REV16{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008854 if (!size.IsNarrow() &&
8855 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008856 EmitT32_32(0xfa90f090U | (rd.GetCode() << 8) | rm.GetCode() |
8857 (rm.GetCode() << 16));
8858 AdvanceIT();
8859 return;
8860 }
8861 } else {
8862 // REV16{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008863 if (cond.IsNotNever() &&
8864 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008865 EmitA32(0x06bf0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8866 rm.GetCode());
8867 return;
8868 }
8869 }
8870 Delegate(kRev16, &Assembler::rev16, cond, size, rd, rm);
8871}
8872
8873void Assembler::revsh(Condition cond,
8874 EncodingSize size,
8875 Register rd,
8876 Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008877 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008878 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008879 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008880 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T1
8881 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
8882 EmitT32_16(0xbac0 | rd.GetCode() | (rm.GetCode() << 3));
8883 AdvanceIT();
8884 return;
8885 }
8886 // REVSH{<c>}{<q>} <Rd>, <Rm> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00008887 if (!size.IsNarrow() &&
8888 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008889 EmitT32_32(0xfa90f0b0U | (rd.GetCode() << 8) | rm.GetCode() |
8890 (rm.GetCode() << 16));
8891 AdvanceIT();
8892 return;
8893 }
8894 } else {
8895 // REVSH{<c>}{<q>} <Rd>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00008896 if (cond.IsNotNever() &&
8897 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008898 EmitA32(0x06ff0fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
8899 rm.GetCode());
8900 return;
8901 }
8902 }
8903 Delegate(kRevsh, &Assembler::revsh, cond, size, rd, rm);
8904}
8905
8906void Assembler::ror(Condition cond,
8907 EncodingSize size,
8908 Register rd,
8909 Register rm,
8910 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008911 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008912 CheckIT(cond);
8913 if (operand.IsImmediate()) {
8914 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008915 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008916 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008917 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8918 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008919 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8920 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8921 AdvanceIT();
8922 return;
8923 }
8924 } else {
8925 // ROR{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8926 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8927 EmitA32(0x01a00060U | (cond.GetCondition() << 28) |
8928 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8929 return;
8930 }
8931 }
8932 }
8933 if (operand.IsPlainRegister()) {
8934 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008936 // ROR<c>{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8937 if (InITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8938 rs.IsLow()) {
8939 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8940 AdvanceIT();
8941 return;
8942 }
8943 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008944 if (!size.IsNarrow() &&
8945 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008946 EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
8947 rs.GetCode());
8948 AdvanceIT();
8949 return;
8950 }
8951 } else {
8952 // ROR{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008953 if (cond.IsNotNever() &&
8954 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008955 EmitA32(0x01a00070U | (cond.GetCondition() << 28) |
8956 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
8957 return;
8958 }
8959 }
8960 }
8961 Delegate(kRor, &Assembler::ror, cond, size, rd, rm, operand);
8962}
8963
8964void Assembler::rors(Condition cond,
8965 EncodingSize size,
8966 Register rd,
8967 Register rm,
8968 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07008969 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01008970 CheckIT(cond);
8971 if (operand.IsImmediate()) {
8972 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008973 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008974 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00008975 if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) &&
8976 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008977 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() |
8978 ((imm & 0x3) << 6) | ((imm & 0x1c) << 10));
8979 AdvanceIT();
8980 return;
8981 }
8982 } else {
8983 // RORS{<c>}{<q>} {<Rd>}, <Rm>, #<imm> ; A1
8984 if ((imm >= 1) && (imm <= 31) && cond.IsNotNever()) {
8985 EmitA32(0x01b00060U | (cond.GetCondition() << 28) |
8986 (rd.GetCode() << 12) | rm.GetCode() | (imm << 7));
8987 return;
8988 }
8989 }
8990 }
8991 if (operand.IsPlainRegister()) {
8992 Register rs = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01008993 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01008994 // RORS{<q>} {<Rdm>}, <Rdm>, <Rs> ; T1
8995 if (OutsideITBlock() && !size.IsWide() && rd.Is(rm) && rm.IsLow() &&
8996 rs.IsLow()) {
8997 EmitT32_16(0x41c0 | rd.GetCode() | (rs.GetCode() << 3));
8998 AdvanceIT();
8999 return;
9000 }
9001 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009002 if (!size.IsNarrow() &&
9003 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009004 EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) |
9005 rs.GetCode());
9006 AdvanceIT();
9007 return;
9008 }
9009 } else {
9010 // RORS{<c>}{<q>} {<Rd>}, <Rm>, <Rs> ; A1
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009011 if (cond.IsNotNever() &&
9012 ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009013 EmitA32(0x01b00070U | (cond.GetCondition() << 28) |
9014 (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8));
9015 return;
9016 }
9017 }
9018 }
9019 Delegate(kRors, &Assembler::rors, cond, size, rd, rm, operand);
9020}
9021
9022void Assembler::rrx(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009023 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009024 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009025 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009026 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009027 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9028 EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode());
9029 AdvanceIT();
9030 return;
9031 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009032 } else {
9033 // RRX{<c>}{<q>} {<Rd>}, <Rm> ; A1
9034 if (cond.IsNotNever()) {
9035 EmitA32(0x01a00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9036 rm.GetCode());
9037 return;
9038 }
9039 }
9040 Delegate(kRrx, &Assembler::rrx, cond, rd, rm);
9041}
9042
9043void Assembler::rrxs(Condition cond, Register rd, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009044 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009045 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009046 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009047 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; T3
Pierre Langlois6bf388d2017-02-15 13:34:38 +00009048 if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9049 EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode());
9050 AdvanceIT();
9051 return;
9052 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009053 } else {
9054 // RRXS{<c>}{<q>} {<Rd>}, <Rm> ; A1
9055 if (cond.IsNotNever()) {
9056 EmitA32(0x01b00060U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9057 rm.GetCode());
9058 return;
9059 }
9060 }
9061 Delegate(kRrxs, &Assembler::rrxs, cond, rd, rm);
9062}
9063
9064void Assembler::rsb(Condition cond,
9065 EncodingSize size,
9066 Register rd,
9067 Register rn,
9068 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009069 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009070 CheckIT(cond);
9071 if (operand.IsImmediate()) {
9072 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009073 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009074 ImmediateT32 immediate_t32(imm);
9075 // RSB<c>{<q>} {<Rd>}, <Rn>, #0 ; T1
9076 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9077 (imm == 0)) {
9078 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9079 AdvanceIT();
9080 return;
9081 }
9082 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009083 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9084 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009085 EmitT32_32(0xf1c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9086 (immediate_t32.GetEncodingValue() & 0xff) |
9087 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9088 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9089 AdvanceIT();
9090 return;
9091 }
9092 } else {
9093 ImmediateA32 immediate_a32(imm);
9094 // RSB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9095 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9096 EmitA32(0x02600000U | (cond.GetCondition() << 28) |
9097 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9098 immediate_a32.GetEncodingValue());
9099 return;
9100 }
9101 }
9102 }
9103 if (operand.IsImmediateShiftedRegister()) {
9104 Register rm = operand.GetBaseRegister();
9105 Shift shift = operand.GetShift();
9106 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009107 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009108 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009109 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9110 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009111 uint32_t amount_ = amount % 32;
9112 EmitT32_32(0xebc00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9113 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9114 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9115 AdvanceIT();
9116 return;
9117 }
9118 } else {
9119 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9120 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9121 uint32_t amount_ = amount % 32;
9122 EmitA32(0x00600000U | (cond.GetCondition() << 28) |
9123 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9124 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9125 return;
9126 }
9127 }
9128 }
9129 if (operand.IsRegisterShiftedRegister()) {
9130 Register rm = operand.GetBaseRegister();
9131 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009132 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009133 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009134 // RSB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009135 if (cond.IsNotNever() &&
9136 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9137 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009138 EmitA32(0x00600010U | (cond.GetCondition() << 28) |
9139 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009140 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009141 return;
9142 }
9143 }
9144 }
9145 Delegate(kRsb, &Assembler::rsb, cond, size, rd, rn, operand);
9146}
9147
9148void Assembler::rsbs(Condition cond,
9149 EncodingSize size,
9150 Register rd,
9151 Register rn,
9152 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009153 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009154 CheckIT(cond);
9155 if (operand.IsImmediate()) {
9156 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009157 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009158 ImmediateT32 immediate_t32(imm);
9159 // RSBS{<q>} {<Rd>}, <Rn>, #0 ; T1
9160 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
9161 (imm == 0)) {
9162 EmitT32_16(0x4240 | rd.GetCode() | (rn.GetCode() << 3));
9163 AdvanceIT();
9164 return;
9165 }
9166 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009167 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9168 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009169 EmitT32_32(0xf1d00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9170 (immediate_t32.GetEncodingValue() & 0xff) |
9171 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9172 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9173 AdvanceIT();
9174 return;
9175 }
9176 } else {
9177 ImmediateA32 immediate_a32(imm);
9178 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9179 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9180 EmitA32(0x02700000U | (cond.GetCondition() << 28) |
9181 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9182 immediate_a32.GetEncodingValue());
9183 return;
9184 }
9185 }
9186 }
9187 if (operand.IsImmediateShiftedRegister()) {
9188 Register rm = operand.GetBaseRegister();
9189 Shift shift = operand.GetShift();
9190 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009191 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009192 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009193 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9194 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009195 uint32_t amount_ = amount % 32;
9196 EmitT32_32(0xebd00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9197 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9198 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9199 AdvanceIT();
9200 return;
9201 }
9202 } else {
9203 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9204 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9205 uint32_t amount_ = amount % 32;
9206 EmitA32(0x00700000U | (cond.GetCondition() << 28) |
9207 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9208 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9209 return;
9210 }
9211 }
9212 }
9213 if (operand.IsRegisterShiftedRegister()) {
9214 Register rm = operand.GetBaseRegister();
9215 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009216 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009217 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009218 // RSBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009219 if (cond.IsNotNever() &&
9220 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9221 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009222 EmitA32(0x00700010U | (cond.GetCondition() << 28) |
9223 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009224 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009225 return;
9226 }
9227 }
9228 }
9229 Delegate(kRsbs, &Assembler::rsbs, cond, size, rd, rn, operand);
9230}
9231
9232void Assembler::rsc(Condition cond,
9233 Register rd,
9234 Register rn,
9235 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009236 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009237 CheckIT(cond);
9238 if (operand.IsImmediate()) {
9239 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009240 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009241 ImmediateA32 immediate_a32(imm);
9242 // RSC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9243 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9244 EmitA32(0x02e00000U | (cond.GetCondition() << 28) |
9245 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9246 immediate_a32.GetEncodingValue());
9247 return;
9248 }
9249 }
9250 }
9251 if (operand.IsImmediateShiftedRegister()) {
9252 Register rm = operand.GetBaseRegister();
9253 Shift shift = operand.GetShift();
9254 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009255 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009256 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9257 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9258 uint32_t amount_ = amount % 32;
9259 EmitA32(0x00e00000U | (cond.GetCondition() << 28) |
9260 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9261 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9262 return;
9263 }
9264 }
9265 }
9266 if (operand.IsRegisterShiftedRegister()) {
9267 Register rm = operand.GetBaseRegister();
9268 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009269 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009270 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009271 // RSC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009272 if (cond.IsNotNever() &&
9273 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9274 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009275 EmitA32(0x00e00010U | (cond.GetCondition() << 28) |
9276 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009277 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009278 return;
9279 }
9280 }
9281 }
9282 Delegate(kRsc, &Assembler::rsc, cond, rd, rn, operand);
9283}
9284
9285void Assembler::rscs(Condition cond,
9286 Register rd,
9287 Register rn,
9288 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009289 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009290 CheckIT(cond);
9291 if (operand.IsImmediate()) {
9292 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009293 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009294 ImmediateA32 immediate_a32(imm);
9295 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9296 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9297 EmitA32(0x02f00000U | (cond.GetCondition() << 28) |
9298 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9299 immediate_a32.GetEncodingValue());
9300 return;
9301 }
9302 }
9303 }
9304 if (operand.IsImmediateShiftedRegister()) {
9305 Register rm = operand.GetBaseRegister();
9306 Shift shift = operand.GetShift();
9307 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009308 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009309 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9310 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9311 uint32_t amount_ = amount % 32;
9312 EmitA32(0x00f00000U | (cond.GetCondition() << 28) |
9313 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9314 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9315 return;
9316 }
9317 }
9318 }
9319 if (operand.IsRegisterShiftedRegister()) {
9320 Register rm = operand.GetBaseRegister();
9321 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009322 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009323 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009324 // RSCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009325 if (cond.IsNotNever() &&
9326 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9327 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009328 EmitA32(0x00f00010U | (cond.GetCondition() << 28) |
9329 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009330 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009331 return;
9332 }
9333 }
9334 }
9335 Delegate(kRscs, &Assembler::rscs, cond, rd, rn, operand);
9336}
9337
9338void Assembler::sadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009339 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009340 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009341 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009342 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009343 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9344 EmitT32_32(0xfa90f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9345 rm.GetCode());
9346 AdvanceIT();
9347 return;
9348 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009349 } else {
9350 // SADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009351 if (cond.IsNotNever() &&
9352 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009353 EmitA32(0x06100f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9354 (rn.GetCode() << 16) | rm.GetCode());
9355 return;
9356 }
9357 }
9358 Delegate(kSadd16, &Assembler::sadd16, cond, rd, rn, rm);
9359}
9360
9361void Assembler::sadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009362 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009363 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009364 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009365 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009366 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9367 EmitT32_32(0xfa80f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9368 rm.GetCode());
9369 AdvanceIT();
9370 return;
9371 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009372 } else {
9373 // SADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009374 if (cond.IsNotNever() &&
9375 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009376 EmitA32(0x06100f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9377 (rn.GetCode() << 16) | rm.GetCode());
9378 return;
9379 }
9380 }
9381 Delegate(kSadd8, &Assembler::sadd8, cond, rd, rn, rm);
9382}
9383
9384void Assembler::sasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009385 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009386 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009387 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009388 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009389 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9390 EmitT32_32(0xfaa0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9391 rm.GetCode());
9392 AdvanceIT();
9393 return;
9394 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009395 } else {
9396 // SASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009397 if (cond.IsNotNever() &&
9398 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009399 EmitA32(0x06100f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9400 (rn.GetCode() << 16) | rm.GetCode());
9401 return;
9402 }
9403 }
9404 Delegate(kSasx, &Assembler::sasx, cond, rd, rn, rm);
9405}
9406
9407void Assembler::sbc(Condition cond,
9408 EncodingSize size,
9409 Register rd,
9410 Register rn,
9411 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009412 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009413 CheckIT(cond);
9414 if (operand.IsImmediate()) {
9415 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009416 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009417 ImmediateT32 immediate_t32(imm);
9418 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009419 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9420 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009421 EmitT32_32(0xf1600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9422 (immediate_t32.GetEncodingValue() & 0xff) |
9423 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9424 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9425 AdvanceIT();
9426 return;
9427 }
9428 } else {
9429 ImmediateA32 immediate_a32(imm);
9430 // SBC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9431 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9432 EmitA32(0x02c00000U | (cond.GetCondition() << 28) |
9433 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9434 immediate_a32.GetEncodingValue());
9435 return;
9436 }
9437 }
9438 }
9439 if (operand.IsImmediateShiftedRegister()) {
9440 Register rm = operand.GetBaseRegister();
9441 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009442 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009443 // SBC<c>{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9444 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9445 rm.IsLow()) {
9446 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9447 AdvanceIT();
9448 return;
9449 }
9450 }
9451 }
9452 Shift shift = operand.GetShift();
9453 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009454 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009455 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009456 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9457 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009458 uint32_t amount_ = amount % 32;
9459 EmitT32_32(0xeb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9460 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9461 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9462 AdvanceIT();
9463 return;
9464 }
9465 } else {
9466 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9467 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9468 uint32_t amount_ = amount % 32;
9469 EmitA32(0x00c00000U | (cond.GetCondition() << 28) |
9470 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9471 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9472 return;
9473 }
9474 }
9475 }
9476 if (operand.IsRegisterShiftedRegister()) {
9477 Register rm = operand.GetBaseRegister();
9478 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009479 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009480 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009481 // SBC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009482 if (cond.IsNotNever() &&
9483 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9484 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009485 EmitA32(0x00c00010U | (cond.GetCondition() << 28) |
9486 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009487 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009488 return;
9489 }
9490 }
9491 }
9492 Delegate(kSbc, &Assembler::sbc, cond, size, rd, rn, operand);
9493}
9494
9495void Assembler::sbcs(Condition cond,
9496 EncodingSize size,
9497 Register rd,
9498 Register rn,
9499 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009500 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009501 CheckIT(cond);
9502 if (operand.IsImmediate()) {
9503 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009504 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009505 ImmediateT32 immediate_t32(imm);
9506 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009507 if (!size.IsNarrow() && immediate_t32.IsValid() &&
9508 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009509 EmitT32_32(0xf1700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9510 (immediate_t32.GetEncodingValue() & 0xff) |
9511 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
9512 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
9513 AdvanceIT();
9514 return;
9515 }
9516 } else {
9517 ImmediateA32 immediate_a32(imm);
9518 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
9519 if (immediate_a32.IsValid() && cond.IsNotNever()) {
9520 EmitA32(0x02d00000U | (cond.GetCondition() << 28) |
9521 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
9522 immediate_a32.GetEncodingValue());
9523 return;
9524 }
9525 }
9526 }
9527 if (operand.IsImmediateShiftedRegister()) {
9528 Register rm = operand.GetBaseRegister();
9529 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009530 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009531 // SBCS{<q>} {<Rdn>}, <Rdn>, <Rm> ; T1
9532 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
9533 rm.IsLow()) {
9534 EmitT32_16(0x4180 | rd.GetCode() | (rm.GetCode() << 3));
9535 AdvanceIT();
9536 return;
9537 }
9538 }
9539 }
9540 Shift shift = operand.GetShift();
9541 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009542 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009543 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +00009544 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
9545 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009546 uint32_t amount_ = amount % 32;
9547 EmitT32_32(0xeb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9548 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
9549 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
9550 AdvanceIT();
9551 return;
9552 }
9553 } else {
9554 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
9555 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
9556 uint32_t amount_ = amount % 32;
9557 EmitA32(0x00d00000U | (cond.GetCondition() << 28) |
9558 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
9559 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
9560 return;
9561 }
9562 }
9563 }
9564 if (operand.IsRegisterShiftedRegister()) {
9565 Register rm = operand.GetBaseRegister();
9566 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +00009567 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009568 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009569 // SBCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +00009570 if (cond.IsNotNever() &&
9571 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
9572 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009573 EmitA32(0x00d00010U | (cond.GetCondition() << 28) |
9574 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +00009575 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +01009576 return;
9577 }
9578 }
9579 }
9580 Delegate(kSbcs, &Assembler::sbcs, cond, size, rd, rn, operand);
9581}
9582
Vincent Belliard609821f2017-02-08 14:17:25 -08009583void Assembler::sbfx(
9584 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009585 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009586 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -08009587 if (IsUsingT32()) {
9588 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
9589 if ((lsb <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00009590 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9591 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08009592 uint32_t widthm1 = width - 1;
9593 EmitT32_32(0xf3400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9594 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
9595 AdvanceIT();
9596 return;
9597 }
9598 } else {
9599 // SBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
9600 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +00009601 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
9602 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -08009603 uint32_t widthm1 = width - 1;
9604 EmitA32(0x07a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9605 rn.GetCode() | (lsb << 7) | (widthm1 << 16));
9606 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +01009607 }
9608 }
Vincent Belliard609821f2017-02-08 14:17:25 -08009609 Delegate(kSbfx, &Assembler::sbfx, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +01009610}
9611
9612void Assembler::sdiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009613 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009614 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009615 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009616 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009617 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9618 EmitT32_32(0xfb90f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9619 rm.GetCode());
9620 AdvanceIT();
9621 return;
9622 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009623 } else {
9624 // SDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009625 if (cond.IsNotNever() &&
9626 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009627 EmitA32(0x0710f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9628 rn.GetCode() | (rm.GetCode() << 8));
9629 return;
9630 }
9631 }
9632 Delegate(kSdiv, &Assembler::sdiv, cond, rd, rn, rm);
9633}
9634
9635void Assembler::sel(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009636 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009637 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009638 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009639 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009640 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9641 EmitT32_32(0xfaa0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9642 rm.GetCode());
9643 AdvanceIT();
9644 return;
9645 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009646 } else {
9647 // SEL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009648 if (cond.IsNotNever() &&
9649 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009650 EmitA32(0x06800fb0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9651 (rn.GetCode() << 16) | rm.GetCode());
9652 return;
9653 }
9654 }
9655 Delegate(kSel, &Assembler::sel, cond, rd, rn, rm);
9656}
9657
9658void Assembler::shadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009659 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009660 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009661 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009662 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009663 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9664 EmitT32_32(0xfa90f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9665 rm.GetCode());
9666 AdvanceIT();
9667 return;
9668 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009669 } else {
9670 // SHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009671 if (cond.IsNotNever() &&
9672 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009673 EmitA32(0x06300f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9674 (rn.GetCode() << 16) | rm.GetCode());
9675 return;
9676 }
9677 }
9678 Delegate(kShadd16, &Assembler::shadd16, cond, rd, rn, rm);
9679}
9680
9681void Assembler::shadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009682 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009683 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009684 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009685 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009686 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9687 EmitT32_32(0xfa80f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9688 rm.GetCode());
9689 AdvanceIT();
9690 return;
9691 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009692 } else {
9693 // SHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009694 if (cond.IsNotNever() &&
9695 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009696 EmitA32(0x06300f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9697 (rn.GetCode() << 16) | rm.GetCode());
9698 return;
9699 }
9700 }
9701 Delegate(kShadd8, &Assembler::shadd8, cond, rd, rn, rm);
9702}
9703
9704void Assembler::shasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009705 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009706 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009707 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009708 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009709 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9710 EmitT32_32(0xfaa0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9711 rm.GetCode());
9712 AdvanceIT();
9713 return;
9714 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009715 } else {
9716 // SHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009717 if (cond.IsNotNever() &&
9718 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009719 EmitA32(0x06300f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9720 (rn.GetCode() << 16) | rm.GetCode());
9721 return;
9722 }
9723 }
9724 Delegate(kShasx, &Assembler::shasx, cond, rd, rn, rm);
9725}
9726
9727void Assembler::shsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009728 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009729 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009730 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009731 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009732 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9733 EmitT32_32(0xfae0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9734 rm.GetCode());
9735 AdvanceIT();
9736 return;
9737 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009738 } else {
9739 // SHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009740 if (cond.IsNotNever() &&
9741 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009742 EmitA32(0x06300f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9743 (rn.GetCode() << 16) | rm.GetCode());
9744 return;
9745 }
9746 }
9747 Delegate(kShsax, &Assembler::shsax, cond, rd, rn, rm);
9748}
9749
9750void Assembler::shsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009751 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009752 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009754 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009755 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9756 EmitT32_32(0xfad0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9757 rm.GetCode());
9758 AdvanceIT();
9759 return;
9760 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009761 } else {
9762 // SHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009763 if (cond.IsNotNever() &&
9764 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009765 EmitA32(0x06300f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9766 (rn.GetCode() << 16) | rm.GetCode());
9767 return;
9768 }
9769 }
9770 Delegate(kShsub16, &Assembler::shsub16, cond, rd, rn, rm);
9771}
9772
9773void Assembler::shsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009774 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009775 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009776 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009777 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009778 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
9779 EmitT32_32(0xfac0f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9780 rm.GetCode());
9781 AdvanceIT();
9782 return;
9783 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009784 } else {
9785 // SHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009786 if (cond.IsNotNever() &&
9787 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009788 EmitA32(0x06300ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
9789 (rn.GetCode() << 16) | rm.GetCode());
9790 return;
9791 }
9792 }
9793 Delegate(kShsub8, &Assembler::shsub8, cond, rd, rn, rm);
9794}
9795
9796void Assembler::smlabb(
9797 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009798 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009799 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009800 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009801 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009802 if (!ra.Is(pc) &&
9803 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009804 EmitT32_32(0xfb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9805 rm.GetCode() | (ra.GetCode() << 12));
9806 AdvanceIT();
9807 return;
9808 }
9809 } else {
9810 // SMLABB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009811 if (cond.IsNotNever() &&
9812 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9813 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009814 EmitA32(0x01000080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9815 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9816 return;
9817 }
9818 }
9819 Delegate(kSmlabb, &Assembler::smlabb, cond, rd, rn, rm, ra);
9820}
9821
9822void Assembler::smlabt(
9823 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009824 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009825 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009826 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009827 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009828 if (!ra.Is(pc) &&
9829 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009830 EmitT32_32(0xfb100010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9831 rm.GetCode() | (ra.GetCode() << 12));
9832 AdvanceIT();
9833 return;
9834 }
9835 } else {
9836 // SMLABT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009837 if (cond.IsNotNever() &&
9838 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
9839 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009840 EmitA32(0x010000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9841 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9842 return;
9843 }
9844 }
9845 Delegate(kSmlabt, &Assembler::smlabt, cond, rd, rn, rm, ra);
9846}
9847
9848void Assembler::smlad(
9849 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009850 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009851 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009852 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009853 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009854 if (!ra.Is(pc) &&
9855 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009856 EmitT32_32(0xfb200000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9857 rm.GetCode() | (ra.GetCode() << 12));
9858 AdvanceIT();
9859 return;
9860 }
9861 } else {
9862 // SMLAD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009863 if (cond.IsNotNever() && !ra.Is(pc) &&
9864 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009865 EmitA32(0x07000010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9866 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9867 return;
9868 }
9869 }
9870 Delegate(kSmlad, &Assembler::smlad, cond, rd, rn, rm, ra);
9871}
9872
9873void Assembler::smladx(
9874 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009875 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009876 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009877 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009878 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009879 if (!ra.Is(pc) &&
9880 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009881 EmitT32_32(0xfb200010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
9882 rm.GetCode() | (ra.GetCode() << 12));
9883 AdvanceIT();
9884 return;
9885 }
9886 } else {
9887 // SMLADX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009888 if (cond.IsNotNever() && !ra.Is(pc) &&
9889 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009890 EmitA32(0x07000030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
9891 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
9892 return;
9893 }
9894 }
9895 Delegate(kSmladx, &Assembler::smladx, cond, rd, rn, rm, ra);
9896}
9897
9898void Assembler::smlal(
9899 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009900 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009901 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009902 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009903 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009904 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9905 AllowUnpredictable())) {
9906 EmitT32_32(0xfbc00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9907 (rn.GetCode() << 16) | rm.GetCode());
9908 AdvanceIT();
9909 return;
9910 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009911 } else {
9912 // SMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009913 if (cond.IsNotNever() &&
9914 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9915 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009916 EmitA32(0x00e00090U | (cond.GetCondition() << 28) |
9917 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9918 (rm.GetCode() << 8));
9919 return;
9920 }
9921 }
9922 Delegate(kSmlal, &Assembler::smlal, cond, rdlo, rdhi, rn, rm);
9923}
9924
9925void Assembler::smlalbb(
9926 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009927 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009928 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009929 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009930 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009931 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9932 AllowUnpredictable())) {
9933 EmitT32_32(0xfbc00080U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9934 (rn.GetCode() << 16) | rm.GetCode());
9935 AdvanceIT();
9936 return;
9937 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009938 } else {
9939 // SMLALBB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009940 if (cond.IsNotNever() &&
9941 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9942 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009943 EmitA32(0x01400080U | (cond.GetCondition() << 28) |
9944 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9945 (rm.GetCode() << 8));
9946 return;
9947 }
9948 }
9949 Delegate(kSmlalbb, &Assembler::smlalbb, cond, rdlo, rdhi, rn, rm);
9950}
9951
9952void Assembler::smlalbt(
9953 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009954 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009955 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009956 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009957 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009958 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9959 AllowUnpredictable())) {
9960 EmitT32_32(0xfbc00090U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9961 (rn.GetCode() << 16) | rm.GetCode());
9962 AdvanceIT();
9963 return;
9964 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009965 } else {
9966 // SMLALBT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009967 if (cond.IsNotNever() &&
9968 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9969 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009970 EmitA32(0x014000c0U | (cond.GetCondition() << 28) |
9971 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9972 (rm.GetCode() << 8));
9973 return;
9974 }
9975 }
9976 Delegate(kSmlalbt, &Assembler::smlalbt, cond, rdlo, rdhi, rn, rm);
9977}
9978
9979void Assembler::smlald(
9980 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -07009981 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +01009982 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +01009983 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009984 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009985 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9986 AllowUnpredictable())) {
9987 EmitT32_32(0xfbc000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
9988 (rn.GetCode() << 16) | rm.GetCode());
9989 AdvanceIT();
9990 return;
9991 }
Alexandre Ramesd3832962016-07-04 15:03:43 +01009992 } else {
9993 // SMLALD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +00009994 if (cond.IsNotNever() &&
9995 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
9996 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +01009997 EmitA32(0x07400010U | (cond.GetCondition() << 28) |
9998 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
9999 (rm.GetCode() << 8));
10000 return;
10001 }
10002 }
10003 Delegate(kSmlald, &Assembler::smlald, cond, rdlo, rdhi, rn, rm);
10004}
10005
10006void Assembler::smlaldx(
10007 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010008 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010009 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010010 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010011 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010012 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10013 AllowUnpredictable())) {
10014 EmitT32_32(0xfbc000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10015 (rn.GetCode() << 16) | rm.GetCode());
10016 AdvanceIT();
10017 return;
10018 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010019 } else {
10020 // SMLALDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010021 if (cond.IsNotNever() &&
10022 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10023 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010024 EmitA32(0x07400030U | (cond.GetCondition() << 28) |
10025 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10026 (rm.GetCode() << 8));
10027 return;
10028 }
10029 }
10030 Delegate(kSmlaldx, &Assembler::smlaldx, cond, rdlo, rdhi, rn, rm);
10031}
10032
10033void Assembler::smlals(
10034 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010035 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010036 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010037 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010038 // SMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010039 if (cond.IsNotNever() &&
10040 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10041 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010042 EmitA32(0x00f00090U | (cond.GetCondition() << 28) |
10043 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10044 (rm.GetCode() << 8));
10045 return;
10046 }
10047 }
10048 Delegate(kSmlals, &Assembler::smlals, cond, rdlo, rdhi, rn, rm);
10049}
10050
10051void Assembler::smlaltb(
10052 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010053 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010054 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010055 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010056 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010057 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10058 AllowUnpredictable())) {
10059 EmitT32_32(0xfbc000a0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10060 (rn.GetCode() << 16) | rm.GetCode());
10061 AdvanceIT();
10062 return;
10063 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010064 } else {
10065 // SMLALTB{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010066 if (cond.IsNotNever() &&
10067 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10068 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010069 EmitA32(0x014000a0U | (cond.GetCondition() << 28) |
10070 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10071 (rm.GetCode() << 8));
10072 return;
10073 }
10074 }
10075 Delegate(kSmlaltb, &Assembler::smlaltb, cond, rdlo, rdhi, rn, rm);
10076}
10077
10078void Assembler::smlaltt(
10079 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010080 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010081 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010082 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010083 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010084 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10085 AllowUnpredictable())) {
10086 EmitT32_32(0xfbc000b0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10087 (rn.GetCode() << 16) | rm.GetCode());
10088 AdvanceIT();
10089 return;
10090 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010091 } else {
10092 // SMLALTT{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010093 if (cond.IsNotNever() &&
10094 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10095 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010096 EmitA32(0x014000e0U | (cond.GetCondition() << 28) |
10097 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10098 (rm.GetCode() << 8));
10099 return;
10100 }
10101 }
10102 Delegate(kSmlaltt, &Assembler::smlaltt, cond, rdlo, rdhi, rn, rm);
10103}
10104
10105void Assembler::smlatb(
10106 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010107 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010108 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010109 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010110 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010111 if (!ra.Is(pc) &&
10112 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010113 EmitT32_32(0xfb100020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10114 rm.GetCode() | (ra.GetCode() << 12));
10115 AdvanceIT();
10116 return;
10117 }
10118 } else {
10119 // SMLATB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010120 if (cond.IsNotNever() &&
10121 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10122 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010123 EmitA32(0x010000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10124 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10125 return;
10126 }
10127 }
10128 Delegate(kSmlatb, &Assembler::smlatb, cond, rd, rn, rm, ra);
10129}
10130
10131void Assembler::smlatt(
10132 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010133 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010134 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010135 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010136 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010137 if (!ra.Is(pc) &&
10138 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010139 EmitT32_32(0xfb100030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10140 rm.GetCode() | (ra.GetCode() << 12));
10141 AdvanceIT();
10142 return;
10143 }
10144 } else {
10145 // SMLATT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010146 if (cond.IsNotNever() &&
10147 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10148 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010149 EmitA32(0x010000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10150 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10151 return;
10152 }
10153 }
10154 Delegate(kSmlatt, &Assembler::smlatt, cond, rd, rn, rm, ra);
10155}
10156
10157void Assembler::smlawb(
10158 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010159 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010160 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010161 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010162 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010163 if (!ra.Is(pc) &&
10164 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010165 EmitT32_32(0xfb300000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10166 rm.GetCode() | (ra.GetCode() << 12));
10167 AdvanceIT();
10168 return;
10169 }
10170 } else {
10171 // SMLAWB{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010172 if (cond.IsNotNever() &&
10173 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10174 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010175 EmitA32(0x01200080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10176 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10177 return;
10178 }
10179 }
10180 Delegate(kSmlawb, &Assembler::smlawb, cond, rd, rn, rm, ra);
10181}
10182
10183void Assembler::smlawt(
10184 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010186 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010187 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010188 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010189 if (!ra.Is(pc) &&
10190 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010191 EmitT32_32(0xfb300010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10192 rm.GetCode() | (ra.GetCode() << 12));
10193 AdvanceIT();
10194 return;
10195 }
10196 } else {
10197 // SMLAWT{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010198 if (cond.IsNotNever() &&
10199 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10200 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010201 EmitA32(0x012000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10202 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10203 return;
10204 }
10205 }
10206 Delegate(kSmlawt, &Assembler::smlawt, cond, rd, rn, rm, ra);
10207}
10208
10209void Assembler::smlsd(
10210 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010211 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010212 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010213 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010214 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010215 if (!ra.Is(pc) &&
10216 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010217 EmitT32_32(0xfb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10218 rm.GetCode() | (ra.GetCode() << 12));
10219 AdvanceIT();
10220 return;
10221 }
10222 } else {
10223 // SMLSD{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010224 if (cond.IsNotNever() && !ra.Is(pc) &&
10225 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010226 EmitA32(0x07000050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10227 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10228 return;
10229 }
10230 }
10231 Delegate(kSmlsd, &Assembler::smlsd, cond, rd, rn, rm, ra);
10232}
10233
10234void Assembler::smlsdx(
10235 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010236 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010237 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010238 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010239 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010240 if (!ra.Is(pc) &&
10241 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010242 EmitT32_32(0xfb400010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10243 rm.GetCode() | (ra.GetCode() << 12));
10244 AdvanceIT();
10245 return;
10246 }
10247 } else {
10248 // SMLSDX{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010249 if (cond.IsNotNever() && !ra.Is(pc) &&
10250 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010251 EmitA32(0x07000070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10252 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10253 return;
10254 }
10255 }
10256 Delegate(kSmlsdx, &Assembler::smlsdx, cond, rd, rn, rm, ra);
10257}
10258
10259void Assembler::smlsld(
10260 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010261 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010262 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010263 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010264 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010265 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10266 AllowUnpredictable())) {
10267 EmitT32_32(0xfbd000c0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10268 (rn.GetCode() << 16) | rm.GetCode());
10269 AdvanceIT();
10270 return;
10271 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010272 } else {
10273 // SMLSLD{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010274 if (cond.IsNotNever() &&
10275 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10276 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010277 EmitA32(0x07400050U | (cond.GetCondition() << 28) |
10278 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10279 (rm.GetCode() << 8));
10280 return;
10281 }
10282 }
10283 Delegate(kSmlsld, &Assembler::smlsld, cond, rdlo, rdhi, rn, rm);
10284}
10285
10286void Assembler::smlsldx(
10287 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010288 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010289 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010290 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010291 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010292 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10293 AllowUnpredictable())) {
10294 EmitT32_32(0xfbd000d0U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10295 (rn.GetCode() << 16) | rm.GetCode());
10296 AdvanceIT();
10297 return;
10298 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010299 } else {
10300 // SMLSLDX{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010301 if (cond.IsNotNever() &&
10302 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10303 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010304 EmitA32(0x07400070U | (cond.GetCondition() << 28) |
10305 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10306 (rm.GetCode() << 8));
10307 return;
10308 }
10309 }
10310 Delegate(kSmlsldx, &Assembler::smlsldx, cond, rdlo, rdhi, rn, rm);
10311}
10312
10313void Assembler::smmla(
10314 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010315 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010316 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010317 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010318 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010319 if (!ra.Is(pc) &&
10320 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010321 EmitT32_32(0xfb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10322 rm.GetCode() | (ra.GetCode() << 12));
10323 AdvanceIT();
10324 return;
10325 }
10326 } else {
10327 // SMMLA{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010328 if (cond.IsNotNever() && !ra.Is(pc) &&
10329 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010330 EmitA32(0x07500010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10331 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10332 return;
10333 }
10334 }
10335 Delegate(kSmmla, &Assembler::smmla, cond, rd, rn, rm, ra);
10336}
10337
10338void Assembler::smmlar(
10339 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010340 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010341 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010342 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010343 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010344 if (!ra.Is(pc) &&
10345 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010346 EmitT32_32(0xfb500010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10347 rm.GetCode() | (ra.GetCode() << 12));
10348 AdvanceIT();
10349 return;
10350 }
10351 } else {
10352 // SMMLAR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010353 if (cond.IsNotNever() && !ra.Is(pc) &&
10354 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010355 EmitA32(0x07500030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10356 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10357 return;
10358 }
10359 }
10360 Delegate(kSmmlar, &Assembler::smmlar, cond, rd, rn, rm, ra);
10361}
10362
10363void Assembler::smmls(
10364 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010365 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010366 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010367 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010368 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010369 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10370 AllowUnpredictable())) {
10371 EmitT32_32(0xfb600000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10372 rm.GetCode() | (ra.GetCode() << 12));
10373 AdvanceIT();
10374 return;
10375 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010376 } else {
10377 // SMMLS{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010378 if (cond.IsNotNever() &&
10379 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10380 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010381 EmitA32(0x075000d0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10382 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10383 return;
10384 }
10385 }
10386 Delegate(kSmmls, &Assembler::smmls, cond, rd, rn, rm, ra);
10387}
10388
10389void Assembler::smmlsr(
10390 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010391 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010392 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010393 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010394 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010395 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10396 AllowUnpredictable())) {
10397 EmitT32_32(0xfb600010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10398 rm.GetCode() | (ra.GetCode() << 12));
10399 AdvanceIT();
10400 return;
10401 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010402 } else {
10403 // SMMLSR{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010404 if (cond.IsNotNever() &&
10405 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !ra.IsPC()) ||
10406 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010407 EmitA32(0x075000f0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10408 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
10409 return;
10410 }
10411 }
10412 Delegate(kSmmlsr, &Assembler::smmlsr, cond, rd, rn, rm, ra);
10413}
10414
10415void Assembler::smmul(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010416 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010417 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010418 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010419 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010420 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10421 EmitT32_32(0xfb50f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10422 rm.GetCode());
10423 AdvanceIT();
10424 return;
10425 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010426 } else {
10427 // SMMUL{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010428 if (cond.IsNotNever() &&
10429 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010430 EmitA32(0x0750f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10431 rn.GetCode() | (rm.GetCode() << 8));
10432 return;
10433 }
10434 }
10435 Delegate(kSmmul, &Assembler::smmul, cond, rd, rn, rm);
10436}
10437
10438void Assembler::smmulr(Condition cond, Register rd, Register rn, Register rm) {
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 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010443 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10444 EmitT32_32(0xfb50f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10445 rm.GetCode());
10446 AdvanceIT();
10447 return;
10448 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010449 } else {
10450 // SMMULR{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010451 if (cond.IsNotNever() &&
10452 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010453 EmitA32(0x0750f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10454 rn.GetCode() | (rm.GetCode() << 8));
10455 return;
10456 }
10457 }
10458 Delegate(kSmmulr, &Assembler::smmulr, cond, rd, rn, rm);
10459}
10460
10461void Assembler::smuad(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010462 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010463 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010465 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010466 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10467 EmitT32_32(0xfb20f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10468 rm.GetCode());
10469 AdvanceIT();
10470 return;
10471 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010472 } else {
10473 // SMUAD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010474 if (cond.IsNotNever() &&
10475 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010476 EmitA32(0x0700f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10477 rn.GetCode() | (rm.GetCode() << 8));
10478 return;
10479 }
10480 }
10481 Delegate(kSmuad, &Assembler::smuad, cond, rd, rn, rm);
10482}
10483
10484void Assembler::smuadx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010485 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010486 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010487 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010488 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010489 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10490 EmitT32_32(0xfb20f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10491 rm.GetCode());
10492 AdvanceIT();
10493 return;
10494 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010495 } else {
10496 // SMUADX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010497 if (cond.IsNotNever() &&
10498 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010499 EmitA32(0x0700f030U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10500 rn.GetCode() | (rm.GetCode() << 8));
10501 return;
10502 }
10503 }
10504 Delegate(kSmuadx, &Assembler::smuadx, cond, rd, rn, rm);
10505}
10506
10507void Assembler::smulbb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010508 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010509 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010510 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010511 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010512 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10513 EmitT32_32(0xfb10f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10514 rm.GetCode());
10515 AdvanceIT();
10516 return;
10517 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010518 } else {
10519 // SMULBB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010520 if (cond.IsNotNever() &&
10521 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010522 EmitA32(0x01600080U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10523 rn.GetCode() | (rm.GetCode() << 8));
10524 return;
10525 }
10526 }
10527 Delegate(kSmulbb, &Assembler::smulbb, cond, rd, rn, rm);
10528}
10529
10530void Assembler::smulbt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010531 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010532 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010533 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010534 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010535 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10536 EmitT32_32(0xfb10f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10537 rm.GetCode());
10538 AdvanceIT();
10539 return;
10540 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010541 } else {
10542 // SMULBT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010543 if (cond.IsNotNever() &&
10544 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010545 EmitA32(0x016000c0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10546 rn.GetCode() | (rm.GetCode() << 8));
10547 return;
10548 }
10549 }
10550 Delegate(kSmulbt, &Assembler::smulbt, cond, rd, rn, rm);
10551}
10552
10553void Assembler::smull(
10554 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010555 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010556 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010557 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010558 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010559 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10560 AllowUnpredictable())) {
10561 EmitT32_32(0xfb800000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
10562 (rn.GetCode() << 16) | rm.GetCode());
10563 AdvanceIT();
10564 return;
10565 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010566 } else {
10567 // SMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010568 if (cond.IsNotNever() &&
10569 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10570 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010571 EmitA32(0x00c00090U | (cond.GetCondition() << 28) |
10572 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10573 (rm.GetCode() << 8));
10574 return;
10575 }
10576 }
10577 Delegate(kSmull, &Assembler::smull, cond, rdlo, rdhi, rn, rm);
10578}
10579
10580void Assembler::smulls(
10581 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010582 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010583 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010584 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010585 // SMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010586 if (cond.IsNotNever() &&
10587 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
10588 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010589 EmitA32(0x00d00090U | (cond.GetCondition() << 28) |
10590 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
10591 (rm.GetCode() << 8));
10592 return;
10593 }
10594 }
10595 Delegate(kSmulls, &Assembler::smulls, cond, rdlo, rdhi, rn, rm);
10596}
10597
10598void Assembler::smultb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010599 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010600 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010601 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010602 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010603 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10604 EmitT32_32(0xfb10f020U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10605 rm.GetCode());
10606 AdvanceIT();
10607 return;
10608 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010609 } else {
10610 // SMULTB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010611 if (cond.IsNotNever() &&
10612 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010613 EmitA32(0x016000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10614 rn.GetCode() | (rm.GetCode() << 8));
10615 return;
10616 }
10617 }
10618 Delegate(kSmultb, &Assembler::smultb, cond, rd, rn, rm);
10619}
10620
10621void Assembler::smultt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010622 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010623 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010624 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010625 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010626 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10627 EmitT32_32(0xfb10f030U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10628 rm.GetCode());
10629 AdvanceIT();
10630 return;
10631 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010632 } else {
10633 // SMULTT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010634 if (cond.IsNotNever() &&
10635 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010636 EmitA32(0x016000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10637 rn.GetCode() | (rm.GetCode() << 8));
10638 return;
10639 }
10640 }
10641 Delegate(kSmultt, &Assembler::smultt, cond, rd, rn, rm);
10642}
10643
10644void Assembler::smulwb(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010645 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010646 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010647 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010648 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010649 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10650 EmitT32_32(0xfb30f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10651 rm.GetCode());
10652 AdvanceIT();
10653 return;
10654 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010655 } else {
10656 // SMULWB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010657 if (cond.IsNotNever() &&
10658 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010659 EmitA32(0x012000a0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10660 rn.GetCode() | (rm.GetCode() << 8));
10661 return;
10662 }
10663 }
10664 Delegate(kSmulwb, &Assembler::smulwb, cond, rd, rn, rm);
10665}
10666
10667void Assembler::smulwt(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010668 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010669 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010670 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010671 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010672 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10673 EmitT32_32(0xfb30f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10674 rm.GetCode());
10675 AdvanceIT();
10676 return;
10677 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010678 } else {
10679 // SMULWT{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010680 if (cond.IsNotNever() &&
10681 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010682 EmitA32(0x012000e0U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10683 rn.GetCode() | (rm.GetCode() << 8));
10684 return;
10685 }
10686 }
10687 Delegate(kSmulwt, &Assembler::smulwt, cond, rd, rn, rm);
10688}
10689
10690void Assembler::smusd(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010691 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010692 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010693 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010694 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010695 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10696 EmitT32_32(0xfb40f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10697 rm.GetCode());
10698 AdvanceIT();
10699 return;
10700 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010701 } else {
10702 // SMUSD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010703 if (cond.IsNotNever() &&
10704 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010705 EmitA32(0x0700f050U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10706 rn.GetCode() | (rm.GetCode() << 8));
10707 return;
10708 }
10709 }
10710 Delegate(kSmusd, &Assembler::smusd, cond, rd, rn, rm);
10711}
10712
10713void Assembler::smusdx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010714 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010715 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010716 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010717 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010718 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10719 EmitT32_32(0xfb40f010U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10720 rm.GetCode());
10721 AdvanceIT();
10722 return;
10723 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010724 } else {
10725 // SMUSDX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010726 if (cond.IsNotNever() &&
10727 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010728 EmitA32(0x0700f070U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
10729 rn.GetCode() | (rm.GetCode() << 8));
10730 return;
10731 }
10732 }
10733 Delegate(kSmusdx, &Assembler::smusdx, cond, rd, rn, rm);
10734}
10735
10736void Assembler::ssat(Condition cond,
10737 Register rd,
10738 uint32_t imm,
10739 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010740 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010741 CheckIT(cond);
10742 if (operand.IsImmediateShiftedRegister()) {
10743 Register rn = operand.GetBaseRegister();
10744 Shift shift = operand.GetShift();
10745 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010746 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010747 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
10748 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010749 (amount <= 31) &&
10750 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010751 uint32_t imm_ = imm - 1;
10752 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10753 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10754 ((amount & 0x1c) << 10));
10755 AdvanceIT();
10756 return;
10757 }
10758 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010759 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
10760 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010761 uint32_t imm_ = imm - 1;
10762 EmitT32_32(0xf3000000U | (rd.GetCode() << 8) | imm_ |
10763 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
10764 ((amount & 0x1c) << 10));
10765 AdvanceIT();
10766 return;
10767 }
10768 } else {
10769 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
10770 if ((imm >= 1) && (imm <= 32) && shift.IsASR() && (amount >= 1) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010771 (amount <= 32) && cond.IsNotNever() &&
10772 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010773 uint32_t imm_ = imm - 1;
10774 uint32_t amount_ = amount % 32;
10775 EmitA32(0x06a00050U | (cond.GetCondition() << 28) |
10776 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10777 (amount_ << 7));
10778 return;
10779 }
10780 // SSAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
10781 if ((imm >= 1) && (imm <= 32) && shift.IsLSL() && (amount <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010782 cond.IsNotNever() &&
10783 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010784 uint32_t imm_ = imm - 1;
10785 EmitA32(0x06a00010U | (cond.GetCondition() << 28) |
10786 (rd.GetCode() << 12) | (imm_ << 16) | rn.GetCode() |
10787 (amount << 7));
10788 return;
10789 }
10790 }
10791 }
10792 Delegate(kSsat, &Assembler::ssat, cond, rd, imm, operand);
10793}
10794
10795void Assembler::ssat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010796 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010797 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010798 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010799 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010800 if ((imm >= 1) && (imm <= 16) &&
10801 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010802 uint32_t imm_ = imm - 1;
10803 EmitT32_32(0xf3200000U | (rd.GetCode() << 8) | imm_ |
10804 (rn.GetCode() << 16));
10805 AdvanceIT();
10806 return;
10807 }
10808 } else {
10809 // SSAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010810 if ((imm >= 1) && (imm <= 16) && cond.IsNotNever() &&
10811 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010812 uint32_t imm_ = imm - 1;
10813 EmitA32(0x06a00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10814 (imm_ << 16) | rn.GetCode());
10815 return;
10816 }
10817 }
10818 Delegate(kSsat16, &Assembler::ssat16, cond, rd, imm, rn);
10819}
10820
10821void Assembler::ssax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010822 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010823 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010824 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010825 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010826 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10827 EmitT32_32(0xfae0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10828 rm.GetCode());
10829 AdvanceIT();
10830 return;
10831 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010832 } else {
10833 // SSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010834 if (cond.IsNotNever() &&
10835 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010836 EmitA32(0x06100f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10837 (rn.GetCode() << 16) | rm.GetCode());
10838 return;
10839 }
10840 }
10841 Delegate(kSsax, &Assembler::ssax, cond, rd, rn, rm);
10842}
10843
10844void Assembler::ssub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010845 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010846 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010847 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010848 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010849 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10850 EmitT32_32(0xfad0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10851 rm.GetCode());
10852 AdvanceIT();
10853 return;
10854 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010855 } else {
10856 // SSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010857 if (cond.IsNotNever() &&
10858 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010859 EmitA32(0x06100f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10860 (rn.GetCode() << 16) | rm.GetCode());
10861 return;
10862 }
10863 }
10864 Delegate(kSsub16, &Assembler::ssub16, cond, rd, rn, rm);
10865}
10866
10867void Assembler::ssub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010868 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010869 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010870 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010871 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010872 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
10873 EmitT32_32(0xfac0f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
10874 rm.GetCode());
10875 AdvanceIT();
10876 return;
10877 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010010878 } else {
10879 // SSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010880 if (cond.IsNotNever() &&
10881 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010882 EmitA32(0x06100ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
10883 (rn.GetCode() << 16) | rm.GetCode());
10884 return;
10885 }
10886 }
10887 Delegate(kSsub8, &Assembler::ssub8, cond, rd, rn, rm);
10888}
10889
10890void Assembler::stl(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010891 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010892 CheckIT(cond);
10893 if (operand.IsImmediateZero()) {
10894 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010895 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010896 // STL{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010897 if (operand.IsOffset() &&
10898 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010899 EmitT32_32(0xe8c00fafU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10900 AdvanceIT();
10901 return;
10902 }
10903 } else {
10904 // STL{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010905 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010906 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010907 EmitA32(0x0180fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10908 (rn.GetCode() << 16));
10909 return;
10910 }
10911 }
10912 }
10913 Delegate(kStl, &Assembler::stl, cond, rt, operand);
10914}
10915
10916void Assembler::stlb(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010917 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010918 CheckIT(cond);
10919 if (operand.IsImmediateZero()) {
10920 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010921 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010922 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010923 if (operand.IsOffset() &&
10924 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010925 EmitT32_32(0xe8c00f8fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
10926 AdvanceIT();
10927 return;
10928 }
10929 } else {
10930 // STLB{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010931 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010932 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010933 EmitA32(0x01c0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
10934 (rn.GetCode() << 16));
10935 return;
10936 }
10937 }
10938 }
10939 Delegate(kStlb, &Assembler::stlb, cond, rt, operand);
10940}
10941
10942void Assembler::stlex(Condition cond,
10943 Register rd,
10944 Register rt,
10945 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010946 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010947 CheckIT(cond);
10948 if (operand.IsImmediateZero()) {
10949 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010950 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010951 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010952 if (operand.IsOffset() &&
10953 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010954 EmitT32_32(0xe8c00fe0U | rd.GetCode() | (rt.GetCode() << 12) |
10955 (rn.GetCode() << 16));
10956 AdvanceIT();
10957 return;
10958 }
10959 } else {
10960 // STLEX{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010961 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010962 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010963 EmitA32(0x01800e90U | (cond.GetCondition() << 28) |
10964 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10965 return;
10966 }
10967 }
10968 }
10969 Delegate(kStlex, &Assembler::stlex, cond, rd, rt, operand);
10970}
10971
10972void Assembler::stlexb(Condition cond,
10973 Register rd,
10974 Register rt,
10975 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070010976 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010010977 CheckIT(cond);
10978 if (operand.IsImmediateZero()) {
10979 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010010980 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010981 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000010982 if (operand.IsOffset() &&
10983 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010984 EmitT32_32(0xe8c00fc0U | rd.GetCode() | (rt.GetCode() << 12) |
10985 (rn.GetCode() << 16));
10986 AdvanceIT();
10987 return;
10988 }
10989 } else {
10990 // STLEXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080010991 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000010992 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010010993 EmitA32(0x01c00e90U | (cond.GetCondition() << 28) |
10994 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
10995 return;
10996 }
10997 }
10998 }
10999 Delegate(kStlexb, &Assembler::stlexb, cond, rd, rt, operand);
11000}
11001
11002void Assembler::stlexd(Condition cond,
11003 Register rd,
11004 Register rt,
11005 Register rt2,
11006 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011007 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011008 CheckIT(cond);
11009 if (operand.IsImmediateZero()) {
11010 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011011 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011012 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011013 if (operand.IsOffset() &&
11014 ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11015 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011016 EmitT32_32(0xe8c000f0U | rd.GetCode() | (rt.GetCode() << 12) |
11017 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11018 AdvanceIT();
11019 return;
11020 }
11021 } else {
11022 // STLEXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11023 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011024 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011025 ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11026 !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +010011027 AllowUnpredictable())) {
11028 EmitA32(0x01a00e90U | (cond.GetCondition() << 28) |
11029 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11030 return;
11031 }
11032 }
11033 }
11034 Delegate(kStlexd, &Assembler::stlexd, cond, rd, rt, rt2, operand);
11035}
11036
11037void Assembler::stlexh(Condition cond,
11038 Register rd,
11039 Register rt,
11040 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011041 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011042 CheckIT(cond);
11043 if (operand.IsImmediateZero()) {
11044 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011045 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011046 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011047 if (operand.IsOffset() &&
11048 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011049 EmitT32_32(0xe8c00fd0U | rd.GetCode() | (rt.GetCode() << 12) |
11050 (rn.GetCode() << 16));
11051 AdvanceIT();
11052 return;
11053 }
11054 } else {
11055 // STLEXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011056 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011057 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011058 EmitA32(0x01e00e90U | (cond.GetCondition() << 28) |
11059 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11060 return;
11061 }
11062 }
11063 }
11064 Delegate(kStlexh, &Assembler::stlexh, cond, rd, rt, operand);
11065}
11066
11067void Assembler::stlh(Condition cond, Register rt, const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011068 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011069 CheckIT(cond);
11070 if (operand.IsImmediateZero()) {
11071 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011072 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011073 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011074 if (operand.IsOffset() &&
11075 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011076 EmitT32_32(0xe8c00f9fU | (rt.GetCode() << 12) | (rn.GetCode() << 16));
11077 AdvanceIT();
11078 return;
11079 }
11080 } else {
11081 // STLH{<c>}{<q>} <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011082 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011083 ((!rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011084 EmitA32(0x01e0fc90U | (cond.GetCondition() << 28) | rt.GetCode() |
11085 (rn.GetCode() << 16));
11086 return;
11087 }
11088 }
11089 }
11090 Delegate(kStlh, &Assembler::stlh, cond, rt, operand);
11091}
11092
11093void Assembler::stm(Condition cond,
11094 EncodingSize size,
11095 Register rn,
11096 WriteBack write_back,
11097 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011098 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011099 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011100 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011101 // STM{<c>}{<q>} <Rn>!, <registers> ; T1
11102 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11103 ((registers.GetList() & ~0xff) == 0)) {
11104 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11105 GetRegisterListEncoding(registers, 0, 8));
11106 AdvanceIT();
11107 return;
11108 }
11109 // STM{<c>}{<q>} <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011110 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11111 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011112 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11113 (write_back.GetWriteBackUint32() << 21) |
11114 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11115 GetRegisterListEncoding(registers, 0, 13));
11116 AdvanceIT();
11117 return;
11118 }
11119 } else {
11120 // STM{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011121 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011122 EmitA32(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11123 (write_back.GetWriteBackUint32() << 21) |
11124 GetRegisterListEncoding(registers, 0, 16));
11125 return;
11126 }
11127 }
11128 Delegate(kStm, &Assembler::stm, cond, size, rn, write_back, registers);
11129}
11130
11131void Assembler::stmda(Condition cond,
11132 Register rn,
11133 WriteBack write_back,
11134 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011135 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011136 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011137 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011138 // STMDA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011139 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011140 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11141 (write_back.GetWriteBackUint32() << 21) |
11142 GetRegisterListEncoding(registers, 0, 16));
11143 return;
11144 }
11145 }
11146 Delegate(kStmda, &Assembler::stmda, cond, rn, write_back, registers);
11147}
11148
11149void Assembler::stmdb(Condition cond,
11150 EncodingSize size,
11151 Register rn,
11152 WriteBack write_back,
11153 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011154 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011155 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011156 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011157 // STMDB{<c>}{<q>} SP!, <registers> ; T1
11158 if (!size.IsWide() && rn.Is(sp) && write_back.DoesWriteBack() &&
11159 ((registers.GetList() & ~0x40ff) == 0)) {
11160 EmitT32_16(0xb400 | (GetRegisterListEncoding(registers, 14, 1) << 8) |
11161 GetRegisterListEncoding(registers, 0, 8));
11162 AdvanceIT();
11163 return;
11164 }
11165 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011166 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11167 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011168 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11169 (write_back.GetWriteBackUint32() << 21) |
11170 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11171 GetRegisterListEncoding(registers, 0, 13));
11172 AdvanceIT();
11173 return;
11174 }
11175 } else {
11176 // STMDB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011177 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011178 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11179 (write_back.GetWriteBackUint32() << 21) |
11180 GetRegisterListEncoding(registers, 0, 16));
11181 return;
11182 }
11183 }
11184 Delegate(kStmdb, &Assembler::stmdb, cond, size, rn, write_back, registers);
11185}
11186
11187void Assembler::stmea(Condition cond,
11188 EncodingSize size,
11189 Register rn,
11190 WriteBack write_back,
11191 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011192 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011193 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011194 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011195 // STMEA{<c>}{<q>} <Rn>!, <registers> ; T1
11196 if (!size.IsWide() && rn.IsLow() && write_back.DoesWriteBack() &&
11197 ((registers.GetList() & ~0xff) == 0)) {
11198 EmitT32_16(0xc000 | (rn.GetCode() << 8) |
11199 GetRegisterListEncoding(registers, 0, 8));
11200 AdvanceIT();
11201 return;
11202 }
11203 // STMEA{<c>}.W <Rn>{!}, <registers> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000011204 if (!size.IsNarrow() && ((registers.GetList() & ~0x5fff) == 0) &&
11205 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011206 EmitT32_32(0xe8800000U | (rn.GetCode() << 16) |
11207 (write_back.GetWriteBackUint32() << 21) |
11208 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11209 GetRegisterListEncoding(registers, 0, 13));
11210 AdvanceIT();
11211 return;
11212 }
11213 // STMEA{<c>}{<q>} <Rn>{!}, <registers> ; T2
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(0xe8800000U | (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 // STMEA{<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(0x08800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11227 (write_back.GetWriteBackUint32() << 21) |
11228 GetRegisterListEncoding(registers, 0, 16));
11229 return;
11230 }
11231 }
11232 Delegate(kStmea, &Assembler::stmea, cond, size, rn, write_back, registers);
11233}
11234
11235void Assembler::stmed(Condition cond,
11236 Register rn,
11237 WriteBack write_back,
11238 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011239 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011240 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011241 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011242 // STMED{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011243 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011244 EmitA32(0x08000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11245 (write_back.GetWriteBackUint32() << 21) |
11246 GetRegisterListEncoding(registers, 0, 16));
11247 return;
11248 }
11249 }
11250 Delegate(kStmed, &Assembler::stmed, cond, rn, write_back, registers);
11251}
11252
11253void Assembler::stmfa(Condition cond,
11254 Register rn,
11255 WriteBack write_back,
11256 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011257 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011258 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011259 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011260 // STMFA{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011261 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011262 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11263 (write_back.GetWriteBackUint32() << 21) |
11264 GetRegisterListEncoding(registers, 0, 16));
11265 return;
11266 }
11267 }
11268 Delegate(kStmfa, &Assembler::stmfa, cond, rn, write_back, registers);
11269}
11270
11271void Assembler::stmfd(Condition cond,
11272 Register rn,
11273 WriteBack write_back,
11274 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011275 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011276 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011277 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011278 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011279 if (((registers.GetList() & ~0x5fff) == 0) &&
11280 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011281 EmitT32_32(0xe9000000U | (rn.GetCode() << 16) |
11282 (write_back.GetWriteBackUint32() << 21) |
11283 (GetRegisterListEncoding(registers, 14, 1) << 14) |
11284 GetRegisterListEncoding(registers, 0, 13));
11285 AdvanceIT();
11286 return;
11287 }
11288 } else {
11289 // STMFD{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011290 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011291 EmitA32(0x09000000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11292 (write_back.GetWriteBackUint32() << 21) |
11293 GetRegisterListEncoding(registers, 0, 16));
11294 return;
11295 }
11296 }
11297 Delegate(kStmfd, &Assembler::stmfd, cond, rn, write_back, registers);
11298}
11299
11300void Assembler::stmib(Condition cond,
11301 Register rn,
11302 WriteBack write_back,
11303 RegisterList registers) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011304 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011305 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011306 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011307 // STMIB{<c>}{<q>} <Rn>{!}, <registers> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011308 if (cond.IsNotNever() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011309 EmitA32(0x09800000U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
11310 (write_back.GetWriteBackUint32() << 21) |
11311 GetRegisterListEncoding(registers, 0, 16));
11312 return;
11313 }
11314 }
11315 Delegate(kStmib, &Assembler::stmib, cond, rn, write_back, registers);
11316}
11317
11318void Assembler::str(Condition cond,
11319 EncodingSize size,
11320 Register rt,
11321 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011322 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011323 CheckIT(cond);
11324 if (operand.IsImmediate()) {
11325 Register rn = operand.GetBaseRegister();
11326 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011327 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011328 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11329 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011330 (offset <= 124) && ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011331 int32_t offset_ = offset >> 2;
11332 EmitT32_16(0x6000 | rt.GetCode() | (rn.GetCode() << 3) |
11333 ((offset_ & 0x1f) << 6));
11334 AdvanceIT();
11335 return;
11336 }
11337 // STR{<c>}{<q>} <Rt>, [SP{, #{+}<imm>}] ; T2
11338 if (!size.IsWide() && rt.IsLow() && (offset >= 0) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011339 ((offset % 4) == 0) && rn.Is(sp) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011340 int32_t offset_ = offset >> 2;
11341 EmitT32_16(0x9000 | (rt.GetCode() << 8) | (offset_ & 0xff));
11342 AdvanceIT();
11343 return;
11344 }
11345 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T3
11346 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011347 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11348 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011349 EmitT32_32(0xf8c00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11350 (offset & 0xfff));
11351 AdvanceIT();
11352 return;
11353 }
11354 // STR{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T4
11355 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011356 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11357 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011358 EmitT32_32(0xf8400c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11359 (-offset & 0xff));
11360 AdvanceIT();
11361 return;
11362 }
11363 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T4
11364 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011365 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11366 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011367 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11368 uint32_t offset_ = abs(offset);
11369 EmitT32_32(0xf8400900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11370 offset_ | (sign << 9));
11371 AdvanceIT();
11372 return;
11373 }
11374 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T4
11375 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011376 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11377 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011378 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11379 uint32_t offset_ = abs(offset);
11380 EmitT32_32(0xf8400d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11381 offset_ | (sign << 9));
11382 AdvanceIT();
11383 return;
11384 }
11385 } else {
11386 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011387 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
11388 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011389 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11390 uint32_t offset_ = abs(offset);
11391 EmitA32(0x05000000U | (cond.GetCondition() << 28) |
11392 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11393 (sign << 23));
11394 return;
11395 }
11396 // STR{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011397 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
11398 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011399 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11400 uint32_t offset_ = abs(offset);
11401 EmitA32(0x04000000U | (cond.GetCondition() << 28) |
11402 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11403 (sign << 23));
11404 return;
11405 }
11406 // STR{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011407 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
11408 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011409 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11410 uint32_t offset_ = abs(offset);
11411 EmitA32(0x05200000U | (cond.GetCondition() << 28) |
11412 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11413 (sign << 23));
11414 return;
11415 }
11416 }
11417 }
11418 if (operand.IsPlainRegister()) {
11419 Register rn = operand.GetBaseRegister();
11420 Sign sign = operand.GetSign();
11421 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011422 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011423 // STR{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11424 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011425 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011426 EmitT32_16(0x5000 | rt.GetCode() | (rn.GetCode() << 3) |
11427 (rm.GetCode() << 6));
11428 AdvanceIT();
11429 return;
11430 }
11431 }
11432 }
11433 if (operand.IsShiftedRegister()) {
11434 Register rn = operand.GetBaseRegister();
11435 Sign sign = operand.GetSign();
11436 Register rm = operand.GetOffsetRegister();
11437 Shift shift = operand.GetShift();
11438 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011439 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011440 // STR{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11441 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011442 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11443 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011444 EmitT32_32(0xf8400000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11445 rm.GetCode() | (amount << 4));
11446 AdvanceIT();
11447 return;
11448 }
11449 } else {
11450 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011451 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11452 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011453 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11454 uint32_t shift_ = TypeEncodingValue(shift);
11455 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11456 EmitA32(0x07000000U | (cond.GetCondition() << 28) |
11457 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11458 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11459 return;
11460 }
11461 // STR{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011462 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011463 cond.IsNotNever() && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011464 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11465 uint32_t shift_ = TypeEncodingValue(shift);
11466 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11467 EmitA32(0x06000000U | (cond.GetCondition() << 28) |
11468 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11469 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11470 return;
11471 }
11472 // STR{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011473 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11474 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011475 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11476 uint32_t shift_ = TypeEncodingValue(shift);
11477 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11478 EmitA32(0x07200000U | (cond.GetCondition() << 28) |
11479 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11480 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11481 return;
11482 }
11483 }
11484 }
11485 Delegate(kStr, &Assembler::str, cond, size, rt, operand);
11486}
11487
11488void Assembler::strb(Condition cond,
11489 EncodingSize size,
11490 Register rt,
11491 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011492 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011493 CheckIT(cond);
11494 if (operand.IsImmediate()) {
11495 Register rn = operand.GetBaseRegister();
11496 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011497 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011498 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11499 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011500 (offset <= 31) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011501 EmitT32_16(0x7000 | rt.GetCode() | (rn.GetCode() << 3) |
11502 ((offset & 0x1f) << 6));
11503 AdvanceIT();
11504 return;
11505 }
11506 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11507 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011508 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11509 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011510 EmitT32_32(0xf8800000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11511 (offset & 0xfff));
11512 AdvanceIT();
11513 return;
11514 }
11515 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11516 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011517 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11518 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011519 EmitT32_32(0xf8000c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11520 (-offset & 0xff));
11521 AdvanceIT();
11522 return;
11523 }
11524 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11525 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011526 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11527 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011528 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11529 uint32_t offset_ = abs(offset);
11530 EmitT32_32(0xf8000900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11531 offset_ | (sign << 9));
11532 AdvanceIT();
11533 return;
11534 }
11535 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11536 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011537 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11538 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011539 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11540 uint32_t offset_ = abs(offset);
11541 EmitT32_32(0xf8000d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11542 offset_ | (sign << 9));
11543 AdvanceIT();
11544 return;
11545 }
11546 } else {
11547 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011548 if ((offset >= -4095) && (offset <= 4095) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011549 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011550 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11551 uint32_t offset_ = abs(offset);
11552 EmitA32(0x05400000U | (cond.GetCondition() << 28) |
11553 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11554 (sign << 23));
11555 return;
11556 }
11557 // STRB{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011558 if ((offset >= -4095) && (offset <= 4095) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011559 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011560 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11561 uint32_t offset_ = abs(offset);
11562 EmitA32(0x04400000U | (cond.GetCondition() << 28) |
11563 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11564 (sign << 23));
11565 return;
11566 }
11567 // STRB{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011568 if ((offset >= -4095) && (offset <= 4095) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011569 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011570 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11571 uint32_t offset_ = abs(offset);
11572 EmitA32(0x05600000U | (cond.GetCondition() << 28) |
11573 (rt.GetCode() << 12) | (rn.GetCode() << 16) | offset_ |
11574 (sign << 23));
11575 return;
11576 }
11577 }
11578 }
11579 if (operand.IsPlainRegister()) {
11580 Register rn = operand.GetBaseRegister();
11581 Sign sign = operand.GetSign();
11582 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011583 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011584 // STRB{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
11585 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011586 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011587 EmitT32_16(0x5400 | rt.GetCode() | (rn.GetCode() << 3) |
11588 (rm.GetCode() << 6));
11589 AdvanceIT();
11590 return;
11591 }
11592 }
11593 }
11594 if (operand.IsShiftedRegister()) {
11595 Register rn = operand.GetBaseRegister();
11596 Sign sign = operand.GetSign();
11597 Register rm = operand.GetOffsetRegister();
11598 Shift shift = operand.GetShift();
11599 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011600 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011601 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
11602 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011603 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11604 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011605 EmitT32_32(0xf8000000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11606 rm.GetCode() | (amount << 4));
11607 AdvanceIT();
11608 return;
11609 }
11610 } else {
11611 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011612 if (operand.IsShiftValid() && operand.IsOffset() && cond.IsNotNever() &&
11613 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011614 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11615 uint32_t shift_ = TypeEncodingValue(shift);
11616 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11617 EmitA32(0x07400000U | (cond.GetCondition() << 28) |
11618 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11619 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11620 return;
11621 }
11622 // STRB{<c>}{<q>} <Rt>, [<Rn>], {+/-}<Rm>{, <shift>} ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011623 if (operand.IsShiftValid() && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011624 cond.IsNotNever() &&
11625 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011626 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11627 uint32_t shift_ = TypeEncodingValue(shift);
11628 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11629 EmitA32(0x06400000U | (cond.GetCondition() << 28) |
11630 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11631 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11632 return;
11633 }
11634 // STRB{<c>}{<q>} <Rt>, [<Rn>, {+/-}<Rm>{, <shift>}]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011635 if (operand.IsShiftValid() && operand.IsPreIndex() && cond.IsNotNever() &&
11636 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011637 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11638 uint32_t shift_ = TypeEncodingValue(shift);
11639 uint32_t imm_and_type_ = (((amount % 32) << 2) | shift_);
11640 EmitA32(0x07600000U | (cond.GetCondition() << 28) |
11641 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11642 (sign_ << 23) | ((imm_and_type_ & 0x7f) << 5));
11643 return;
11644 }
11645 }
11646 }
11647 Delegate(kStrb, &Assembler::strb, cond, size, rt, operand);
11648}
11649
11650void Assembler::strd(Condition cond,
11651 Register rt,
11652 Register rt2,
11653 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011654 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011655 CheckIT(cond);
11656 if (operand.IsImmediate()) {
11657 Register rn = operand.GetBaseRegister();
11658 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011659 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011660 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}] ; T1
11661 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011662 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11663 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011664 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11665 uint32_t offset_ = abs(offset) >> 2;
11666 EmitT32_32(0xe9400000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11667 (rn.GetCode() << 16) | offset_ | (sign << 23));
11668 AdvanceIT();
11669 return;
11670 }
11671 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm> ; T1
11672 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011673 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11674 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011675 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11676 uint32_t offset_ = abs(offset) >> 2;
11677 EmitT32_32(0xe8600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11678 (rn.GetCode() << 16) | offset_ | (sign << 23));
11679 AdvanceIT();
11680 return;
11681 }
11682 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm>}]! ; T1
11683 if ((offset >= -1020) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011684 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11685 ((!rn.IsPC() && !rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011686 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11687 uint32_t offset_ = abs(offset) >> 2;
11688 EmitT32_32(0xe9600000U | (rt.GetCode() << 12) | (rt2.GetCode() << 8) |
11689 (rn.GetCode() << 16) | offset_ | (sign << 23));
11690 AdvanceIT();
11691 return;
11692 }
11693 } else {
11694 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}] ; A1
11695 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011696 (offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011697 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11698 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011699 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11700 uint32_t offset_ = abs(offset);
11701 EmitA32(0x014000f0U | (cond.GetCondition() << 28) |
11702 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11703 ((offset_ & 0xf0) << 4) | (sign << 23));
11704 return;
11705 }
11706 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<imm_1> ; A1
11707 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011708 (offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011709 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11710 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011711 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11712 uint32_t offset_ = abs(offset);
11713 EmitA32(0x004000f0U | (cond.GetCondition() << 28) |
11714 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11715 ((offset_ & 0xf0) << 4) | (sign << 23));
11716 return;
11717 }
11718 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>{, #{+/-}<imm_1>}]! ; A1
11719 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011720 (offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011721 cond.IsNotNever() && ((((rt.GetCode() & 1) == 0) && !rt2.IsPC()) ||
11722 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011723 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11724 uint32_t offset_ = abs(offset);
11725 EmitA32(0x016000f0U | (cond.GetCondition() << 28) |
11726 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11727 ((offset_ & 0xf0) << 4) | (sign << 23));
11728 return;
11729 }
11730 }
11731 }
11732 if (operand.IsPlainRegister()) {
11733 Register rn = operand.GetBaseRegister();
11734 Sign sign = operand.GetSign();
11735 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011736 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011737 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>] ; A1
11738 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011739 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011740 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011741 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011742 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11743 EmitA32(0x010000f0U | (cond.GetCondition() << 28) |
11744 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11745 (sign_ << 23));
11746 return;
11747 }
11748 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>], #{+/-}<Rm> ; A1
11749 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011750 operand.IsPostIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011751 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011752 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011753 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11754 EmitA32(0x000000f0U | (cond.GetCondition() << 28) |
11755 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11756 (sign_ << 23));
11757 return;
11758 }
11759 // STRD{<c>}{<q>} <Rt>, <Rt2>, [<Rn>, #{+/-}<Rm>]! ; A1
11760 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011761 operand.IsPreIndex() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011762 ((((rt.GetCode() & 1) == 0) && !rt2.IsPC() && !rm.IsPC()) ||
Pierre Langlois960d28b2017-02-15 13:06:01 +000011763 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011764 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
11765 EmitA32(0x012000f0U | (cond.GetCondition() << 28) |
11766 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
11767 (sign_ << 23));
11768 return;
11769 }
11770 }
11771 }
11772 Delegate(kStrd, &Assembler::strd, cond, rt, rt2, operand);
11773}
11774
11775void Assembler::strex(Condition cond,
11776 Register rd,
11777 Register rt,
11778 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011779 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011780 CheckIT(cond);
11781 if (operand.IsImmediate()) {
11782 Register rn = operand.GetBaseRegister();
11783 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011784 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011785 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm>}] ; T1
11786 if ((offset >= 0) && (offset <= 1020) && ((offset % 4) == 0) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011787 operand.IsOffset() &&
11788 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011789 int32_t offset_ = offset >> 2;
11790 EmitT32_32(0xe8400000U | (rd.GetCode() << 8) | (rt.GetCode() << 12) |
11791 (rn.GetCode() << 16) | (offset_ & 0xff));
11792 AdvanceIT();
11793 return;
11794 }
11795 } else {
11796 // STREX{<c>}{<q>} <Rd>, <Rt>, [<Rn>{, #<imm_1>}] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011797 if ((offset == 0) && operand.IsOffset() && cond.IsNotNever() &&
11798 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011799 EmitA32(0x01800f90U | (cond.GetCondition() << 28) |
11800 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11801 return;
11802 }
11803 }
11804 }
11805 Delegate(kStrex, &Assembler::strex, cond, rd, rt, operand);
11806}
11807
11808void Assembler::strexb(Condition cond,
11809 Register rd,
11810 Register rt,
11811 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011812 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011813 CheckIT(cond);
11814 if (operand.IsImmediateZero()) {
11815 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011816 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011817 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011818 if (operand.IsOffset() &&
11819 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011820 EmitT32_32(0xe8c00f40U | rd.GetCode() | (rt.GetCode() << 12) |
11821 (rn.GetCode() << 16));
11822 AdvanceIT();
11823 return;
11824 }
11825 } else {
11826 // STREXB{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011827 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011828 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011829 EmitA32(0x01c00f90U | (cond.GetCondition() << 28) |
11830 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11831 return;
11832 }
11833 }
11834 }
11835 Delegate(kStrexb, &Assembler::strexb, cond, rd, rt, operand);
11836}
11837
11838void Assembler::strexd(Condition cond,
11839 Register rd,
11840 Register rt,
11841 Register rt2,
11842 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011843 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011844 CheckIT(cond);
11845 if (operand.IsImmediateZero()) {
11846 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011847 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011848 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011849 if (operand.IsOffset() &&
11850 ((!rd.IsPC() && !rt.IsPC() && !rt2.IsPC() && !rn.IsPC()) ||
11851 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011852 EmitT32_32(0xe8c00070U | rd.GetCode() | (rt.GetCode() << 12) |
11853 (rt2.GetCode() << 8) | (rn.GetCode() << 16));
11854 AdvanceIT();
11855 return;
11856 }
11857 } else {
11858 // STREXD{<c>}{<q>} <Rd>, <Rt>, <Rt2>, [<Rn>] ; A1
11859 if ((((rt.GetCode() + 1) % kNumberOfRegisters) == rt2.GetCode()) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011860 operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois94ce7a92017-02-20 11:07:50 +000011861 ((!rd.IsPC() && ((rt.GetCode() & 1) == 0) && !rt2.IsPC() &&
11862 !rn.IsPC()) ||
Alexandre Ramesd3832962016-07-04 15:03:43 +010011863 AllowUnpredictable())) {
11864 EmitA32(0x01a00f90U | (cond.GetCondition() << 28) |
11865 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11866 return;
11867 }
11868 }
11869 }
11870 Delegate(kStrexd, &Assembler::strexd, cond, rd, rt, rt2, operand);
11871}
11872
11873void Assembler::strexh(Condition cond,
11874 Register rd,
11875 Register rt,
11876 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011877 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011878 CheckIT(cond);
11879 if (operand.IsImmediateZero()) {
11880 Register rn = operand.GetBaseRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011881 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011882 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000011883 if (operand.IsOffset() &&
11884 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011885 EmitT32_32(0xe8c00f50U | rd.GetCode() | (rt.GetCode() << 12) |
11886 (rn.GetCode() << 16));
11887 AdvanceIT();
11888 return;
11889 }
11890 } else {
11891 // STREXH{<c>}{<q>} <Rd>, <Rt>, [<Rn>] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011892 if (operand.IsOffset() && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011893 ((!rd.IsPC() && !rt.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011894 EmitA32(0x01e00f90U | (cond.GetCondition() << 28) |
11895 (rd.GetCode() << 12) | rt.GetCode() | (rn.GetCode() << 16));
11896 return;
11897 }
11898 }
11899 }
11900 Delegate(kStrexh, &Assembler::strexh, cond, rd, rt, operand);
11901}
11902
11903void Assembler::strh(Condition cond,
11904 EncodingSize size,
11905 Register rt,
11906 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070011907 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010011908 CheckIT(cond);
11909 if (operand.IsImmediate()) {
11910 Register rn = operand.GetBaseRegister();
11911 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011912 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011913 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm>}] ; T1
11914 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && (offset >= 0) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011915 (offset <= 62) && ((offset % 2) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011916 int32_t offset_ = offset >> 1;
11917 EmitT32_16(0x8000 | rt.GetCode() | (rn.GetCode() << 3) |
11918 ((offset_ & 0x1f) << 6));
11919 AdvanceIT();
11920 return;
11921 }
11922 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+}<imm_1>}] ; T2
11923 if (!size.IsNarrow() && (offset >= 0) && (offset <= 4095) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011924 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11925 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011926 EmitT32_32(0xf8a00000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11927 (offset & 0xfff));
11928 AdvanceIT();
11929 return;
11930 }
11931 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #-<imm_2>}] ; T3
11932 if (!size.IsNarrow() && (-offset >= 0) && (-offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011933 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
11934 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011935 EmitT32_32(0xf8200c00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11936 (-offset & 0xff));
11937 AdvanceIT();
11938 return;
11939 }
11940 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_2> ; T3
11941 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011942 operand.IsPostIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11943 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011944 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11945 uint32_t offset_ = abs(offset);
11946 EmitT32_32(0xf8200900U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11947 offset_ | (sign << 9));
11948 AdvanceIT();
11949 return;
11950 }
11951 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_2>}]! ; T3
11952 if (!size.IsNarrow() && (offset >= -255) && (offset <= 255) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011953 operand.IsPreIndex() && ((rn.GetCode() & 0xf) != 0xf) &&
11954 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011955 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11956 uint32_t offset_ = abs(offset);
11957 EmitT32_32(0xf8200d00U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
11958 offset_ | (sign << 9));
11959 AdvanceIT();
11960 return;
11961 }
11962 } else {
11963 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}] ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011964 if ((offset >= -255) && (offset <= 255) && operand.IsOffset() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011965 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011966 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11967 uint32_t offset_ = abs(offset);
11968 EmitA32(0x014000b0U | (cond.GetCondition() << 28) |
11969 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11970 ((offset_ & 0xf0) << 4) | (sign << 23));
11971 return;
11972 }
11973 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<imm_3> ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011974 if ((offset >= -255) && (offset <= 255) && operand.IsPostIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011975 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011976 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11977 uint32_t offset_ = abs(offset);
11978 EmitA32(0x004000b0U | (cond.GetCondition() << 28) |
11979 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11980 ((offset_ & 0xf0) << 4) | (sign << 23));
11981 return;
11982 }
11983 // STRH{<c>}{<q>} <Rt>, [<Rn>{, #{+/-}<imm_3>}]! ; A1
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080011984 if ((offset >= -255) && (offset <= 255) && operand.IsPreIndex() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000011985 cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010011986 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
11987 uint32_t offset_ = abs(offset);
11988 EmitA32(0x016000b0U | (cond.GetCondition() << 28) |
11989 (rt.GetCode() << 12) | (rn.GetCode() << 16) | (offset_ & 0xf) |
11990 ((offset_ & 0xf0) << 4) | (sign << 23));
11991 return;
11992 }
11993 }
11994 }
11995 if (operand.IsPlainRegister()) {
11996 Register rn = operand.GetBaseRegister();
11997 Sign sign = operand.GetSign();
11998 Register rm = operand.GetOffsetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010011999 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012000 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+}<Rm>] ; T1
12001 if (!size.IsWide() && rt.IsLow() && rn.IsLow() && rm.IsLow() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080012002 sign.IsPlus() && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012003 EmitT32_16(0x5200 | rt.GetCode() | (rn.GetCode() << 3) |
12004 (rm.GetCode() << 6));
12005 AdvanceIT();
12006 return;
12007 }
12008 } else {
12009 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>] ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012010 if (operand.IsOffset() && cond.IsNotNever() &&
12011 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012012 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12013 EmitA32(0x010000b0U | (cond.GetCondition() << 28) |
12014 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12015 (sign_ << 23));
12016 return;
12017 }
12018 // STRH{<c>}{<q>} <Rt>, [<Rn>], #{+/-}<Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012019 if (operand.IsPostIndex() && cond.IsNotNever() &&
12020 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012021 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12022 EmitA32(0x000000b0U | (cond.GetCondition() << 28) |
12023 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12024 (sign_ << 23));
12025 return;
12026 }
12027 // STRH{<c>}{<q>} <Rt>, [<Rn>, #{+/-}<Rm>]! ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012028 if (operand.IsPreIndex() && cond.IsNotNever() &&
12029 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012030 uint32_t sign_ = sign.IsPlus() ? 1 : 0;
12031 EmitA32(0x012000b0U | (cond.GetCondition() << 28) |
12032 (rt.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12033 (sign_ << 23));
12034 return;
12035 }
12036 }
12037 }
12038 if (operand.IsShiftedRegister()) {
12039 Register rn = operand.GetBaseRegister();
12040 Sign sign = operand.GetSign();
12041 Register rm = operand.GetOffsetRegister();
12042 Shift shift = operand.GetShift();
12043 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012044 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012045 // STRH{<c>}{<q>} <Rt>, [<Rn>, {+}<Rm>{, LSL #<imm>}] ; T2
12046 if (!size.IsNarrow() && sign.IsPlus() && shift.IsLSL() && (amount <= 3) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012047 operand.IsOffset() && ((rn.GetCode() & 0xf) != 0xf) &&
12048 ((!rt.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012049 EmitT32_32(0xf8200000U | (rt.GetCode() << 12) | (rn.GetCode() << 16) |
12050 rm.GetCode() | (amount << 4));
12051 AdvanceIT();
12052 return;
12053 }
12054 }
12055 }
12056 Delegate(kStrh, &Assembler::strh, cond, size, rt, operand);
12057}
12058
12059void Assembler::sub(Condition cond,
12060 EncodingSize size,
12061 Register rd,
12062 Register rn,
12063 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012064 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012065 CheckIT(cond);
12066 if (operand.IsImmediate()) {
12067 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012068 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012069 ImmediateT32 immediate_t32(imm);
12070 // SUB<c>{<q>} <Rd>, <Rn>, #<imm3> ; T1
12071 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12072 (imm <= 7)) {
12073 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12074 AdvanceIT();
12075 return;
12076 }
12077 // SUB<c>{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12078 if (InITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12079 (imm <= 255)) {
12080 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12081 AdvanceIT();
12082 return;
12083 }
12084 // SUB{<c>}{<q>} {SP}, SP, #<imm7> ; T1
12085 if (!size.IsWide() && rd.Is(sp) && rn.Is(sp) && (imm <= 508) &&
12086 ((imm % 4) == 0)) {
12087 uint32_t imm_ = imm >> 2;
12088 EmitT32_16(0xb080 | imm_);
12089 AdvanceIT();
12090 return;
12091 }
12092 // SUB{<c>}{<q>} <Rd>, PC, #<imm12> ; T2
Pierre Langlois6bf388d2017-02-15 13:34:38 +000012093 if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
12094 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012095 EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12096 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12097 AdvanceIT();
12098 return;
12099 }
12100 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012101 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
12102 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012103 EmitT32_32(0xf1a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12104 (immediate_t32.GetEncodingValue() & 0xff) |
12105 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12106 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12107 AdvanceIT();
12108 return;
12109 }
12110 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Pierre Langlois960d28b2017-02-15 13:06:01 +000012111 if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12112 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012113 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12114 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12115 AdvanceIT();
12116 return;
12117 }
12118 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012119 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12120 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012121 EmitT32_32(0xf1ad0000U | (rd.GetCode() << 8) |
12122 (immediate_t32.GetEncodingValue() & 0xff) |
12123 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12124 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12125 AdvanceIT();
12126 return;
12127 }
12128 // SUB{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012129 if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
12130 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012131 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12132 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12133 AdvanceIT();
12134 return;
12135 }
12136 } else {
12137 ImmediateA32 immediate_a32(imm);
12138 // SUB{<c>}{<q>} <Rd>, PC, #<const> ; A2
12139 if (rn.Is(pc) && immediate_a32.IsValid() && cond.IsNotNever()) {
12140 EmitA32(0x024f0000U | (cond.GetCondition() << 28) |
12141 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12142 return;
12143 }
12144 // SUB{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12145 if (immediate_a32.IsValid() && cond.IsNotNever() &&
12146 ((rn.GetCode() & 0xd) != 0xd)) {
12147 EmitA32(0x02400000U | (cond.GetCondition() << 28) |
12148 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12149 immediate_a32.GetEncodingValue());
12150 return;
12151 }
12152 // SUB{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12153 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12154 EmitA32(0x024d0000U | (cond.GetCondition() << 28) |
12155 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12156 return;
12157 }
12158 }
12159 }
12160 if (operand.IsImmediateShiftedRegister()) {
12161 Register rm = operand.GetBaseRegister();
12162 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012163 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012164 // SUB<c>{<q>} <Rd>, <Rn>, <Rm> ; T1
12165 if (InITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12166 rm.IsLow()) {
12167 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12168 (rm.GetCode() << 6));
12169 AdvanceIT();
12170 return;
12171 }
12172 // SUB{<c>} {<Rd>}, SP, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012173 if (rn.Is(sp) && ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012174 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode());
12175 AdvanceIT();
12176 return;
12177 }
12178 }
12179 }
12180 Shift shift = operand.GetShift();
12181 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012182 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012183 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012184 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
12185 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012186 uint32_t amount_ = amount % 32;
12187 EmitT32_32(0xeba00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12188 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12189 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12190 AdvanceIT();
12191 return;
12192 }
12193 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012194 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
12195 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012196 uint32_t amount_ = amount % 32;
12197 EmitT32_32(0xebad0000U | (rd.GetCode() << 8) | rm.GetCode() |
12198 (operand.GetTypeEncodingValue() << 4) |
12199 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12200 AdvanceIT();
12201 return;
12202 }
12203 } else {
12204 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12205 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12206 uint32_t amount_ = amount % 32;
12207 EmitA32(0x00400000U | (cond.GetCondition() << 28) |
12208 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12209 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12210 return;
12211 }
12212 // SUB{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12213 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12214 uint32_t amount_ = amount % 32;
12215 EmitA32(0x004d0000U | (cond.GetCondition() << 28) |
12216 (rd.GetCode() << 12) | rm.GetCode() |
12217 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12218 return;
12219 }
12220 }
12221 }
12222 if (operand.IsRegisterShiftedRegister()) {
12223 Register rm = operand.GetBaseRegister();
12224 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012225 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012226 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012227 // SUB{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +000012228 if (cond.IsNotNever() &&
12229 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12230 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012231 EmitA32(0x00400010U | (cond.GetCondition() << 28) |
12232 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012233 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012234 return;
12235 }
12236 }
12237 }
12238 Delegate(kSub, &Assembler::sub, cond, size, rd, rn, operand);
12239}
12240
12241void Assembler::sub(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012242 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012243 CheckIT(cond);
12244 if (operand.IsImmediate()) {
12245 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012246 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012247 // SUB<c>{<q>} <Rdn>, #<imm8> ; T2
12248 if (InITBlock() && rd.IsLow() && (imm <= 255)) {
12249 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12250 AdvanceIT();
12251 return;
12252 }
12253 }
12254 }
12255 Delegate(kSub, &Assembler::sub, cond, rd, operand);
12256}
12257
12258void Assembler::subs(Condition cond,
12259 EncodingSize size,
12260 Register rd,
12261 Register rn,
12262 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012263 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012264 CheckIT(cond);
12265 if (operand.IsImmediate()) {
12266 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012267 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012268 ImmediateT32 immediate_t32(imm);
12269 // SUBS{<q>} <Rd>, <Rn>, #<imm3> ; T1
12270 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12271 (imm <= 7)) {
12272 EmitT32_16(0x1e00 | rd.GetCode() | (rn.GetCode() << 3) | (imm << 6));
12273 AdvanceIT();
12274 return;
12275 }
12276 // SUBS{<q>} {<Rdn>}, <Rdn>, #<imm8> ; T2
12277 if (OutsideITBlock() && !size.IsWide() && rd.Is(rn) && rn.IsLow() &&
12278 (imm <= 255)) {
12279 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12280 AdvanceIT();
12281 return;
12282 }
12283 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
12284 if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012285 !rd.Is(pc) && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012286 EmitT32_32(0xf1b00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12287 (immediate_t32.GetEncodingValue() & 0xff) |
12288 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12289 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12290 AdvanceIT();
12291 return;
12292 }
12293 // SUBS{<c>}{<q>} PC, LR, #<imm8> ; T5
Pierre Langloisdc626f32017-02-15 13:31:28 +000012294 if (!size.IsNarrow() && rd.Is(pc) && rn.Is(lr) && (imm <= 255) &&
12295 (OutsideITBlockAndAlOrLast(cond) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012296 EmitT32_32(0xf3de8f00U | imm);
12297 AdvanceIT();
12298 return;
12299 }
12300 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; T2
12301 if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
12302 !rd.Is(pc)) {
12303 EmitT32_32(0xf1bd0000U | (rd.GetCode() << 8) |
12304 (immediate_t32.GetEncodingValue() & 0xff) |
12305 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12306 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12307 AdvanceIT();
12308 return;
12309 }
12310 } else {
12311 ImmediateA32 immediate_a32(imm);
12312 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; A1
12313 if (immediate_a32.IsValid() && cond.IsNotNever() && !rn.Is(sp)) {
12314 EmitA32(0x02500000U | (cond.GetCondition() << 28) |
12315 (rd.GetCode() << 12) | (rn.GetCode() << 16) |
12316 immediate_a32.GetEncodingValue());
12317 return;
12318 }
12319 // SUBS{<c>}{<q>} {<Rd>}, SP, #<const> ; A1
12320 if (rn.Is(sp) && immediate_a32.IsValid() && cond.IsNotNever()) {
12321 EmitA32(0x025d0000U | (cond.GetCondition() << 28) |
12322 (rd.GetCode() << 12) | immediate_a32.GetEncodingValue());
12323 return;
12324 }
12325 }
12326 }
12327 if (operand.IsImmediateShiftedRegister()) {
12328 Register rm = operand.GetBaseRegister();
12329 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012330 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012331 // SUBS{<q>} {<Rd>}, <Rn>, <Rm> ; T1
12332 if (OutsideITBlock() && !size.IsWide() && rd.IsLow() && rn.IsLow() &&
12333 rm.IsLow()) {
12334 EmitT32_16(0x1a00 | rd.GetCode() | (rn.GetCode() << 3) |
12335 (rm.GetCode() << 6));
12336 AdvanceIT();
12337 return;
12338 }
12339 }
12340 }
12341 Shift shift = operand.GetShift();
12342 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012343 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012344 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
12345 if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012346 !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012347 uint32_t amount_ = amount % 32;
12348 EmitT32_32(0xebb00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12349 rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
12350 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12351 AdvanceIT();
12352 return;
12353 }
12354 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T1
12355 if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012356 !rd.Is(pc) && (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012357 uint32_t amount_ = amount % 32;
12358 EmitT32_32(0xebbd0000U | (rd.GetCode() << 8) | rm.GetCode() |
12359 (operand.GetTypeEncodingValue() << 4) |
12360 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12361 AdvanceIT();
12362 return;
12363 }
12364 } else {
12365 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; A1
12366 if (shift.IsValidAmount(amount) && cond.IsNotNever() && !rn.Is(sp)) {
12367 uint32_t amount_ = amount % 32;
12368 EmitA32(0x00500000U | (cond.GetCondition() << 28) |
12369 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12370 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12371 return;
12372 }
12373 // SUBS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; A1
12374 if (rn.Is(sp) && shift.IsValidAmount(amount) && cond.IsNotNever()) {
12375 uint32_t amount_ = amount % 32;
12376 EmitA32(0x005d0000U | (cond.GetCondition() << 28) |
12377 (rd.GetCode() << 12) | rm.GetCode() |
12378 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12379 return;
12380 }
12381 }
12382 }
12383 if (operand.IsRegisterShiftedRegister()) {
12384 Register rm = operand.GetBaseRegister();
12385 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012386 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012387 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012388 // SUBS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langloisfcd33732017-02-15 13:33:32 +000012389 if (cond.IsNotNever() &&
12390 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && !rs.IsPC()) ||
12391 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012392 EmitA32(0x00500010U | (cond.GetCondition() << 28) |
12393 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012394 (shift.GetType() << 5) | (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012395 return;
12396 }
12397 }
12398 }
12399 Delegate(kSubs, &Assembler::subs, cond, size, rd, rn, operand);
12400}
12401
12402void Assembler::subs(Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012403 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012404 CheckIT(al);
12405 if (operand.IsImmediate()) {
12406 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012407 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012408 // SUBS{<q>} <Rdn>, #<imm8> ; T2
12409 if (OutsideITBlock() && rd.IsLow() && (imm <= 255)) {
12410 EmitT32_16(0x3800 | (rd.GetCode() << 8) | imm);
12411 AdvanceIT();
12412 return;
12413 }
12414 }
12415 }
12416 Delegate(kSubs, &Assembler::subs, rd, operand);
12417}
12418
12419void Assembler::subw(Condition cond,
12420 Register rd,
12421 Register rn,
12422 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012423 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012424 CheckIT(cond);
12425 if (operand.IsImmediate()) {
12426 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012427 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012428 // SUBW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
Pierre Langlois960d28b2017-02-15 13:06:01 +000012429 if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
12430 (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012431 EmitT32_32(0xf2a00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12432 (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12433 AdvanceIT();
12434 return;
12435 }
12436 // SUBW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T3
Pierre Langlois960d28b2017-02-15 13:06:01 +000012437 if (rn.Is(sp) && (imm <= 4095) && (!rd.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012438 EmitT32_32(0xf2ad0000U | (rd.GetCode() << 8) | (imm & 0xff) |
12439 ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
12440 AdvanceIT();
12441 return;
12442 }
12443 }
12444 }
12445 Delegate(kSubw, &Assembler::subw, cond, rd, rn, operand);
12446}
12447
12448void Assembler::svc(Condition cond, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012449 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012450 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012451 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012452 // SVC{<c>}{<q>} {#}<imm> ; T1
12453 if ((imm <= 255)) {
12454 EmitT32_16(0xdf00 | imm);
12455 AdvanceIT();
12456 return;
12457 }
12458 } else {
12459 // SVC{<c>}{<q>} {#}<imm> ; A1
12460 if ((imm <= 16777215) && cond.IsNotNever()) {
12461 EmitA32(0x0f000000U | (cond.GetCondition() << 28) | imm);
12462 return;
12463 }
12464 }
12465 Delegate(kSvc, &Assembler::svc, cond, imm);
12466}
12467
12468void Assembler::sxtab(Condition cond,
12469 Register rd,
12470 Register rn,
12471 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012472 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012473 CheckIT(cond);
12474 if (operand.IsImmediateShiftedRegister()) {
12475 Register rm = operand.GetBaseRegister();
12476 Shift shift = operand.GetShift();
12477 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012478 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012479 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12480 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012481 ((amount % 8) == 0) && !rn.Is(pc) &&
12482 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012483 uint32_t amount_ = amount / 8;
12484 EmitT32_32(0xfa40f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12485 rm.GetCode() | (amount_ << 4));
12486 AdvanceIT();
12487 return;
12488 }
12489 } else {
12490 // SXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12491 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012492 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12493 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012494 uint32_t amount_ = amount / 8;
12495 EmitA32(0x06a00070U | (cond.GetCondition() << 28) |
12496 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12497 (amount_ << 10));
12498 return;
12499 }
12500 }
12501 }
12502 Delegate(kSxtab, &Assembler::sxtab, cond, rd, rn, operand);
12503}
12504
12505void Assembler::sxtab16(Condition cond,
12506 Register rd,
12507 Register rn,
12508 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012509 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012510 CheckIT(cond);
12511 if (operand.IsImmediateShiftedRegister()) {
12512 Register rm = operand.GetBaseRegister();
12513 Shift shift = operand.GetShift();
12514 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012515 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012516 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12517 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012518 ((amount % 8) == 0) && !rn.Is(pc) &&
12519 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012520 uint32_t amount_ = amount / 8;
12521 EmitT32_32(0xfa20f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12522 rm.GetCode() | (amount_ << 4));
12523 AdvanceIT();
12524 return;
12525 }
12526 } else {
12527 // SXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12528 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012529 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12530 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012531 uint32_t amount_ = amount / 8;
12532 EmitA32(0x06800070U | (cond.GetCondition() << 28) |
12533 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12534 (amount_ << 10));
12535 return;
12536 }
12537 }
12538 }
12539 Delegate(kSxtab16, &Assembler::sxtab16, cond, rd, rn, operand);
12540}
12541
12542void Assembler::sxtah(Condition cond,
12543 Register rd,
12544 Register rn,
12545 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012546 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012547 CheckIT(cond);
12548 if (operand.IsImmediateShiftedRegister()) {
12549 Register rm = operand.GetBaseRegister();
12550 Shift shift = operand.GetShift();
12551 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012552 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012553 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
12554 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012555 ((amount % 8) == 0) && !rn.Is(pc) &&
12556 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012557 uint32_t amount_ = amount / 8;
12558 EmitT32_32(0xfa00f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12559 rm.GetCode() | (amount_ << 4));
12560 AdvanceIT();
12561 return;
12562 }
12563 } else {
12564 // SXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
12565 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012566 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
12567 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012568 uint32_t amount_ = amount / 8;
12569 EmitA32(0x06b00070U | (cond.GetCondition() << 28) |
12570 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
12571 (amount_ << 10));
12572 return;
12573 }
12574 }
12575 }
12576 Delegate(kSxtah, &Assembler::sxtah, cond, rd, rn, operand);
12577}
12578
12579void Assembler::sxtb(Condition cond,
12580 EncodingSize size,
12581 Register rd,
12582 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012583 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012584 CheckIT(cond);
12585 if (operand.IsImmediateShiftedRegister()) {
12586 Register rm = operand.GetBaseRegister();
12587 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012588 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012589 // SXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
12590 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12591 EmitT32_16(0xb240 | rd.GetCode() | (rm.GetCode() << 3));
12592 AdvanceIT();
12593 return;
12594 }
12595 }
12596 }
12597 Shift shift = operand.GetShift();
12598 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012599 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012600 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12601 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012602 (amount <= 24) && ((amount % 8) == 0) &&
12603 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012604 uint32_t amount_ = amount / 8;
12605 EmitT32_32(0xfa4ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12606 (amount_ << 4));
12607 AdvanceIT();
12608 return;
12609 }
12610 } else {
12611 // SXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12612 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012613 ((amount % 8) == 0) && cond.IsNotNever() &&
12614 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012615 uint32_t amount_ = amount / 8;
12616 EmitA32(0x06af0070U | (cond.GetCondition() << 28) |
12617 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12618 return;
12619 }
12620 }
12621 }
12622 Delegate(kSxtb, &Assembler::sxtb, cond, size, rd, operand);
12623}
12624
12625void Assembler::sxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012626 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012627 CheckIT(cond);
12628 if (operand.IsImmediateShiftedRegister()) {
12629 Register rm = operand.GetBaseRegister();
12630 Shift shift = operand.GetShift();
12631 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012632 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012633 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
12634 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012635 ((amount % 8) == 0) &&
12636 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012637 uint32_t amount_ = amount / 8;
12638 EmitT32_32(0xfa2ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12639 (amount_ << 4));
12640 AdvanceIT();
12641 return;
12642 }
12643 } else {
12644 // SXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12645 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012646 ((amount % 8) == 0) && cond.IsNotNever() &&
12647 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012648 uint32_t amount_ = amount / 8;
12649 EmitA32(0x068f0070U | (cond.GetCondition() << 28) |
12650 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12651 return;
12652 }
12653 }
12654 }
12655 Delegate(kSxtb16, &Assembler::sxtb16, cond, rd, operand);
12656}
12657
12658void Assembler::sxth(Condition cond,
12659 EncodingSize size,
12660 Register rd,
12661 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012662 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012663 CheckIT(cond);
12664 if (operand.IsImmediateShiftedRegister()) {
12665 Register rm = operand.GetBaseRegister();
12666 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012667 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012668 // SXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
12669 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
12670 EmitT32_16(0xb200 | rd.GetCode() | (rm.GetCode() << 3));
12671 AdvanceIT();
12672 return;
12673 }
12674 }
12675 }
12676 Shift shift = operand.GetShift();
12677 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012678 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012679 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
12680 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012681 (amount <= 24) && ((amount % 8) == 0) &&
12682 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012683 uint32_t amount_ = amount / 8;
12684 EmitT32_32(0xfa0ff080U | (rd.GetCode() << 8) | rm.GetCode() |
12685 (amount_ << 4));
12686 AdvanceIT();
12687 return;
12688 }
12689 } else {
12690 // SXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
12691 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012692 ((amount % 8) == 0) && cond.IsNotNever() &&
12693 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012694 uint32_t amount_ = amount / 8;
12695 EmitA32(0x06bf0070U | (cond.GetCondition() << 28) |
12696 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
12697 return;
12698 }
12699 }
12700 }
12701 Delegate(kSxth, &Assembler::sxth, cond, size, rd, operand);
12702}
12703
12704void Assembler::tbb(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012705 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012706 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012707 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012708 // TBB{<c>}{<q>} [<Rn>, <Rm>] ; T1
12709 if (OutsideITBlockAndAlOrLast(cond) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080012710 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012711 EmitT32_32(0xe8d0f000U | (rn.GetCode() << 16) | rm.GetCode());
12712 AdvanceIT();
12713 return;
12714 }
12715 }
12716 Delegate(kTbb, &Assembler::tbb, cond, rn, rm);
12717}
12718
12719void Assembler::tbh(Condition cond, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012721 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012722 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012723 // TBH{<c>}{<q>} [<Rn>, <Rm>, LSL #1] ; T1
12724 if (OutsideITBlockAndAlOrLast(cond) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080012725 (!rm.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012726 EmitT32_32(0xe8d0f010U | (rn.GetCode() << 16) | rm.GetCode());
12727 AdvanceIT();
12728 return;
12729 }
12730 }
12731 Delegate(kTbh, &Assembler::tbh, cond, rn, rm);
12732}
12733
12734void Assembler::teq(Condition cond, Register rn, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012735 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012736 CheckIT(cond);
12737 if (operand.IsImmediate()) {
12738 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012739 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012740 ImmediateT32 immediate_t32(imm);
12741 // TEQ{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012742 if (immediate_t32.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012743 EmitT32_32(0xf0900f00U | (rn.GetCode() << 16) |
12744 (immediate_t32.GetEncodingValue() & 0xff) |
12745 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12746 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12747 AdvanceIT();
12748 return;
12749 }
12750 } else {
12751 ImmediateA32 immediate_a32(imm);
12752 // TEQ{<c>}{<q>} <Rn>, #<const> ; A1
12753 if (immediate_a32.IsValid() && cond.IsNotNever()) {
12754 EmitA32(0x03300000U | (cond.GetCondition() << 28) |
12755 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12756 return;
12757 }
12758 }
12759 }
12760 if (operand.IsImmediateShiftedRegister()) {
12761 Register rm = operand.GetBaseRegister();
12762 Shift shift = operand.GetShift();
12763 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012764 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012765 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012766 if (shift.IsValidAmount(amount) &&
12767 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012768 uint32_t amount_ = amount % 32;
12769 EmitT32_32(0xea900f00U | (rn.GetCode() << 16) | rm.GetCode() |
12770 (operand.GetTypeEncodingValue() << 4) |
12771 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12772 AdvanceIT();
12773 return;
12774 }
12775 } else {
12776 // TEQ{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12777 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12778 uint32_t amount_ = amount % 32;
12779 EmitA32(0x01300000U | (cond.GetCondition() << 28) |
12780 (rn.GetCode() << 16) | rm.GetCode() |
12781 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12782 return;
12783 }
12784 }
12785 }
12786 if (operand.IsRegisterShiftedRegister()) {
12787 Register rm = operand.GetBaseRegister();
12788 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012789 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012790 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012791 // TEQ{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012792 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +000012793 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012794 EmitA32(0x01300010U | (cond.GetCondition() << 28) |
12795 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012796 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012797 return;
12798 }
12799 }
12800 }
12801 Delegate(kTeq, &Assembler::teq, cond, rn, operand);
12802}
12803
12804void Assembler::tst(Condition cond,
12805 EncodingSize size,
12806 Register rn,
12807 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012808 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012809 CheckIT(cond);
12810 if (operand.IsImmediate()) {
12811 uint32_t imm = operand.GetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012812 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012813 ImmediateT32 immediate_t32(imm);
12814 // TST{<c>}{<q>} <Rn>, #<const> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012815 if (!size.IsNarrow() && immediate_t32.IsValid() &&
12816 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012817 EmitT32_32(0xf0100f00U | (rn.GetCode() << 16) |
12818 (immediate_t32.GetEncodingValue() & 0xff) |
12819 ((immediate_t32.GetEncodingValue() & 0x700) << 4) |
12820 ((immediate_t32.GetEncodingValue() & 0x800) << 15));
12821 AdvanceIT();
12822 return;
12823 }
12824 } else {
12825 ImmediateA32 immediate_a32(imm);
12826 // TST{<c>}{<q>} <Rn>, #<const> ; A1
12827 if (immediate_a32.IsValid() && cond.IsNotNever()) {
12828 EmitA32(0x03100000U | (cond.GetCondition() << 28) |
12829 (rn.GetCode() << 16) | immediate_a32.GetEncodingValue());
12830 return;
12831 }
12832 }
12833 }
12834 if (operand.IsImmediateShiftedRegister()) {
12835 Register rm = operand.GetBaseRegister();
12836 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012837 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012838 // TST{<c>}{<q>} <Rn>, <Rm> ; T1
12839 if (!size.IsWide() && rn.IsLow() && rm.IsLow()) {
12840 EmitT32_16(0x4200 | rn.GetCode() | (rm.GetCode() << 3));
12841 AdvanceIT();
12842 return;
12843 }
12844 }
12845 }
12846 Shift shift = operand.GetShift();
12847 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012848 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012849 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; T2
Pierre Langlois960d28b2017-02-15 13:06:01 +000012850 if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
12851 ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012852 uint32_t amount_ = amount % 32;
12853 EmitT32_32(0xea100f00U | (rn.GetCode() << 16) | rm.GetCode() |
12854 (operand.GetTypeEncodingValue() << 4) |
12855 ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10));
12856 AdvanceIT();
12857 return;
12858 }
12859 } else {
12860 // TST{<c>}{<q>} <Rn>, <Rm> {, <shift> #<amount> } ; A1
12861 if (shift.IsValidAmount(amount) && cond.IsNotNever()) {
12862 uint32_t amount_ = amount % 32;
12863 EmitA32(0x01100000U | (cond.GetCondition() << 28) |
12864 (rn.GetCode() << 16) | rm.GetCode() |
12865 (operand.GetTypeEncodingValue() << 5) | (amount_ << 7));
12866 return;
12867 }
12868 }
12869 }
12870 if (operand.IsRegisterShiftedRegister()) {
12871 Register rm = operand.GetBaseRegister();
12872 Shift shift = operand.GetShift();
Pierre Langloisfcd33732017-02-15 13:33:32 +000012873 Register rs = operand.GetShiftRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012874 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012875 // TST{<c>}{<q>} <Rn>, <Rm>, <shift> <Rs> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012876 if (cond.IsNotNever() &&
Pierre Langloisfcd33732017-02-15 13:33:32 +000012877 ((!rn.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012878 EmitA32(0x01100010U | (cond.GetCondition() << 28) |
12879 (rn.GetCode() << 16) | rm.GetCode() | (shift.GetType() << 5) |
Pierre Langloisfcd33732017-02-15 13:33:32 +000012880 (rs.GetCode() << 8));
Alexandre Ramesd3832962016-07-04 15:03:43 +010012881 return;
12882 }
12883 }
12884 }
12885 Delegate(kTst, &Assembler::tst, cond, size, rn, operand);
12886}
12887
12888void Assembler::uadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012889 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012890 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012891 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012892 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012893 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12894 EmitT32_32(0xfa90f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12895 rm.GetCode());
12896 AdvanceIT();
12897 return;
12898 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012899 } else {
12900 // UADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012901 if (cond.IsNotNever() &&
12902 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012903 EmitA32(0x06500f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12904 (rn.GetCode() << 16) | rm.GetCode());
12905 return;
12906 }
12907 }
12908 Delegate(kUadd16, &Assembler::uadd16, cond, rd, rn, rm);
12909}
12910
12911void Assembler::uadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012912 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012913 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012914 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012915 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012916 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12917 EmitT32_32(0xfa80f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12918 rm.GetCode());
12919 AdvanceIT();
12920 return;
12921 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012922 } else {
12923 // UADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012924 if (cond.IsNotNever() &&
12925 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012926 EmitA32(0x06500f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12927 (rn.GetCode() << 16) | rm.GetCode());
12928 return;
12929 }
12930 }
12931 Delegate(kUadd8, &Assembler::uadd8, cond, rd, rn, rm);
12932}
12933
12934void Assembler::uasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012935 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012936 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012937 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012938 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012939 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
12940 EmitT32_32(0xfaa0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12941 rm.GetCode());
12942 AdvanceIT();
12943 return;
12944 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010012945 } else {
12946 // UASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000012947 if (cond.IsNotNever() &&
12948 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012949 EmitA32(0x06500f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12950 (rn.GetCode() << 16) | rm.GetCode());
12951 return;
12952 }
12953 }
12954 Delegate(kUasx, &Assembler::uasx, cond, rd, rn, rm);
12955}
12956
Vincent Belliard609821f2017-02-08 14:17:25 -080012957void Assembler::ubfx(
12958 Condition cond, Register rd, Register rn, uint32_t lsb, uint32_t width) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012959 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012960 CheckIT(cond);
Vincent Belliard609821f2017-02-08 14:17:25 -080012961 if (IsUsingT32()) {
12962 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; T1
12963 if ((lsb <= 31) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012964 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
12965 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -080012966 uint32_t widthm1 = width - 1;
12967 EmitT32_32(0xf3c00000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
12968 ((lsb & 0x3) << 6) | ((lsb & 0x1c) << 10) | widthm1);
12969 AdvanceIT();
12970 return;
12971 }
12972 } else {
12973 // UBFX{<c>}{<q>} <Rd>, <Rn>, #<lsb>, #<width> ; A1
12974 if ((lsb <= 31) && cond.IsNotNever() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000012975 (((width >= 1) && (width <= 32 - lsb) && !rd.IsPC() && !rn.IsPC()) ||
12976 AllowUnpredictable())) {
Vincent Belliard609821f2017-02-08 14:17:25 -080012977 uint32_t widthm1 = width - 1;
12978 EmitA32(0x07e00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
12979 rn.GetCode() | (lsb << 7) | (widthm1 << 16));
12980 return;
Alexandre Ramesd3832962016-07-04 15:03:43 +010012981 }
12982 }
Vincent Belliard609821f2017-02-08 14:17:25 -080012983 Delegate(kUbfx, &Assembler::ubfx, cond, rd, rn, lsb, width);
Alexandre Ramesd3832962016-07-04 15:03:43 +010012984}
12985
12986void Assembler::udf(Condition cond, EncodingSize size, uint32_t imm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070012987 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010012988 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010012989 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010012990 // UDF{<c>}{<q>} {#}<imm> ; T1
12991 if (!size.IsWide() && (imm <= 255)) {
12992 if (cond.Is(al) || AllowStronglyDiscouraged()) {
12993 EmitT32_16(0xde00 | imm);
12994 AdvanceIT();
12995 return;
12996 }
12997 }
12998 // UDF{<c>}{<q>} {#}<imm> ; T2
12999 if (!size.IsNarrow() && (imm <= 65535)) {
13000 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13001 EmitT32_32(0xf7f0a000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
13002 AdvanceIT();
13003 return;
13004 }
13005 }
13006 } else {
13007 // UDF{<c>}{<q>} {#}<imm> ; A1
13008 if ((imm <= 65535)) {
13009 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13010 EmitA32(0xe7f000f0U | (imm & 0xf) | ((imm & 0xfff0) << 4));
13011 return;
13012 }
13013 }
13014 }
13015 Delegate(kUdf, &Assembler::udf, cond, size, imm);
13016}
13017
13018void Assembler::udiv(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013019 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013020 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013021 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013022 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013023 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13024 EmitT32_32(0xfbb0f0f0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13025 rm.GetCode());
13026 AdvanceIT();
13027 return;
13028 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013029 } else {
13030 // UDIV{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013031 if (cond.IsNotNever() &&
13032 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013033 EmitA32(0x0730f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13034 rn.GetCode() | (rm.GetCode() << 8));
13035 return;
13036 }
13037 }
13038 Delegate(kUdiv, &Assembler::udiv, cond, rd, rn, rm);
13039}
13040
13041void Assembler::uhadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013042 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013043 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013044 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013045 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013046 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13047 EmitT32_32(0xfa90f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13048 rm.GetCode());
13049 AdvanceIT();
13050 return;
13051 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013052 } else {
13053 // UHADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013054 if (cond.IsNotNever() &&
13055 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013056 EmitA32(0x06700f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13057 (rn.GetCode() << 16) | rm.GetCode());
13058 return;
13059 }
13060 }
13061 Delegate(kUhadd16, &Assembler::uhadd16, cond, rd, rn, rm);
13062}
13063
13064void Assembler::uhadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013065 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013066 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013067 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013068 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013069 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13070 EmitT32_32(0xfa80f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13071 rm.GetCode());
13072 AdvanceIT();
13073 return;
13074 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013075 } else {
13076 // UHADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013077 if (cond.IsNotNever() &&
13078 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013079 EmitA32(0x06700f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13080 (rn.GetCode() << 16) | rm.GetCode());
13081 return;
13082 }
13083 }
13084 Delegate(kUhadd8, &Assembler::uhadd8, cond, rd, rn, rm);
13085}
13086
13087void Assembler::uhasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013088 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013089 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013090 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013091 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013092 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13093 EmitT32_32(0xfaa0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13094 rm.GetCode());
13095 AdvanceIT();
13096 return;
13097 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013098 } else {
13099 // UHASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013100 if (cond.IsNotNever() &&
13101 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013102 EmitA32(0x06700f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13103 (rn.GetCode() << 16) | rm.GetCode());
13104 return;
13105 }
13106 }
13107 Delegate(kUhasx, &Assembler::uhasx, cond, rd, rn, rm);
13108}
13109
13110void Assembler::uhsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013111 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013112 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013113 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013114 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013115 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13116 EmitT32_32(0xfae0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13117 rm.GetCode());
13118 AdvanceIT();
13119 return;
13120 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013121 } else {
13122 // UHSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013123 if (cond.IsNotNever() &&
13124 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013125 EmitA32(0x06700f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13126 (rn.GetCode() << 16) | rm.GetCode());
13127 return;
13128 }
13129 }
13130 Delegate(kUhsax, &Assembler::uhsax, cond, rd, rn, rm);
13131}
13132
13133void Assembler::uhsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013134 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013135 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013136 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013137 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013138 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13139 EmitT32_32(0xfad0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13140 rm.GetCode());
13141 AdvanceIT();
13142 return;
13143 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013144 } else {
13145 // UHSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013146 if (cond.IsNotNever() &&
13147 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013148 EmitA32(0x06700f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13149 (rn.GetCode() << 16) | rm.GetCode());
13150 return;
13151 }
13152 }
13153 Delegate(kUhsub16, &Assembler::uhsub16, cond, rd, rn, rm);
13154}
13155
13156void Assembler::uhsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013157 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013158 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013159 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013160 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013161 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13162 EmitT32_32(0xfac0f060U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13163 rm.GetCode());
13164 AdvanceIT();
13165 return;
13166 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013167 } else {
13168 // UHSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013169 if (cond.IsNotNever() &&
13170 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013171 EmitA32(0x06700ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13172 (rn.GetCode() << 16) | rm.GetCode());
13173 return;
13174 }
13175 }
13176 Delegate(kUhsub8, &Assembler::uhsub8, cond, rd, rn, rm);
13177}
13178
13179void Assembler::umaal(
13180 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013181 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013182 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013183 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013184 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013185 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13186 AllowUnpredictable())) {
13187 EmitT32_32(0xfbe00060U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13188 (rn.GetCode() << 16) | rm.GetCode());
13189 AdvanceIT();
13190 return;
13191 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013192 } else {
13193 // UMAAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013194 if (cond.IsNotNever() &&
13195 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13196 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013197 EmitA32(0x00400090U | (cond.GetCondition() << 28) |
13198 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13199 (rm.GetCode() << 8));
13200 return;
13201 }
13202 }
13203 Delegate(kUmaal, &Assembler::umaal, cond, rdlo, rdhi, rn, rm);
13204}
13205
13206void Assembler::umlal(
13207 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013208 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013209 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013210 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013211 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013212 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13213 AllowUnpredictable())) {
13214 EmitT32_32(0xfbe00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13215 (rn.GetCode() << 16) | rm.GetCode());
13216 AdvanceIT();
13217 return;
13218 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013219 } else {
13220 // UMLAL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013221 if (cond.IsNotNever() &&
13222 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13223 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013224 EmitA32(0x00a00090U | (cond.GetCondition() << 28) |
13225 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13226 (rm.GetCode() << 8));
13227 return;
13228 }
13229 }
13230 Delegate(kUmlal, &Assembler::umlal, cond, rdlo, rdhi, rn, rm);
13231}
13232
13233void Assembler::umlals(
13234 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013235 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013236 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013237 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013238 // UMLALS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013239 if (cond.IsNotNever() &&
13240 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13241 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013242 EmitA32(0x00b00090U | (cond.GetCondition() << 28) |
13243 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13244 (rm.GetCode() << 8));
13245 return;
13246 }
13247 }
13248 Delegate(kUmlals, &Assembler::umlals, cond, rdlo, rdhi, rn, rm);
13249}
13250
13251void Assembler::umull(
13252 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013253 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013254 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013255 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013256 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013257 if (((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13258 AllowUnpredictable())) {
13259 EmitT32_32(0xfba00000U | (rdlo.GetCode() << 12) | (rdhi.GetCode() << 8) |
13260 (rn.GetCode() << 16) | rm.GetCode());
13261 AdvanceIT();
13262 return;
13263 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013264 } else {
13265 // UMULL{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013266 if (cond.IsNotNever() &&
13267 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13268 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013269 EmitA32(0x00800090U | (cond.GetCondition() << 28) |
13270 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13271 (rm.GetCode() << 8));
13272 return;
13273 }
13274 }
13275 Delegate(kUmull, &Assembler::umull, cond, rdlo, rdhi, rn, rm);
13276}
13277
13278void Assembler::umulls(
13279 Condition cond, Register rdlo, Register rdhi, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013280 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013281 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013282 if (IsUsingA32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013283 // UMULLS{<c>}{<q>} <Rd>, <Rd>, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013284 if (cond.IsNotNever() &&
13285 ((!rdlo.IsPC() && !rdhi.IsPC() && !rn.IsPC() && !rm.IsPC()) ||
13286 AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013287 EmitA32(0x00900090U | (cond.GetCondition() << 28) |
13288 (rdlo.GetCode() << 12) | (rdhi.GetCode() << 16) | rn.GetCode() |
13289 (rm.GetCode() << 8));
13290 return;
13291 }
13292 }
13293 Delegate(kUmulls, &Assembler::umulls, cond, rdlo, rdhi, rn, rm);
13294}
13295
13296void Assembler::uqadd16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013297 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013298 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013299 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013300 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013301 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13302 EmitT32_32(0xfa90f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13303 rm.GetCode());
13304 AdvanceIT();
13305 return;
13306 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013307 } else {
13308 // UQADD16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013309 if (cond.IsNotNever() &&
13310 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013311 EmitA32(0x06600f10U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13312 (rn.GetCode() << 16) | rm.GetCode());
13313 return;
13314 }
13315 }
13316 Delegate(kUqadd16, &Assembler::uqadd16, cond, rd, rn, rm);
13317}
13318
13319void Assembler::uqadd8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013320 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013321 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013322 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013323 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013324 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13325 EmitT32_32(0xfa80f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13326 rm.GetCode());
13327 AdvanceIT();
13328 return;
13329 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013330 } else {
13331 // UQADD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013332 if (cond.IsNotNever() &&
13333 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013334 EmitA32(0x06600f90U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13335 (rn.GetCode() << 16) | rm.GetCode());
13336 return;
13337 }
13338 }
13339 Delegate(kUqadd8, &Assembler::uqadd8, cond, rd, rn, rm);
13340}
13341
13342void Assembler::uqasx(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013343 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013344 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013345 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013346 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013347 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13348 EmitT32_32(0xfaa0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13349 rm.GetCode());
13350 AdvanceIT();
13351 return;
13352 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013353 } else {
13354 // UQASX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013355 if (cond.IsNotNever() &&
13356 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013357 EmitA32(0x06600f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13358 (rn.GetCode() << 16) | rm.GetCode());
13359 return;
13360 }
13361 }
13362 Delegate(kUqasx, &Assembler::uqasx, cond, rd, rn, rm);
13363}
13364
13365void Assembler::uqsax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013366 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013367 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013368 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013369 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013370 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13371 EmitT32_32(0xfae0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13372 rm.GetCode());
13373 AdvanceIT();
13374 return;
13375 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013376 } else {
13377 // UQSAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013378 if (cond.IsNotNever() &&
13379 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013380 EmitA32(0x06600f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13381 (rn.GetCode() << 16) | rm.GetCode());
13382 return;
13383 }
13384 }
13385 Delegate(kUqsax, &Assembler::uqsax, cond, rd, rn, rm);
13386}
13387
13388void Assembler::uqsub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013389 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013390 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013391 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013392 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013393 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13394 EmitT32_32(0xfad0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13395 rm.GetCode());
13396 AdvanceIT();
13397 return;
13398 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013399 } else {
13400 // UQSUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013401 if (cond.IsNotNever() &&
13402 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013403 EmitA32(0x06600f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13404 (rn.GetCode() << 16) | rm.GetCode());
13405 return;
13406 }
13407 }
13408 Delegate(kUqsub16, &Assembler::uqsub16, cond, rd, rn, rm);
13409}
13410
13411void Assembler::uqsub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013412 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013413 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013414 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013415 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013416 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13417 EmitT32_32(0xfac0f050U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13418 rm.GetCode());
13419 AdvanceIT();
13420 return;
13421 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013422 } else {
13423 // UQSUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013424 if (cond.IsNotNever() &&
13425 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013426 EmitA32(0x06600ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13427 (rn.GetCode() << 16) | rm.GetCode());
13428 return;
13429 }
13430 }
13431 Delegate(kUqsub8, &Assembler::uqsub8, cond, rd, rn, rm);
13432}
13433
13434void Assembler::usad8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013435 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013436 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013437 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013438 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013439 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13440 EmitT32_32(0xfb70f000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13441 rm.GetCode());
13442 AdvanceIT();
13443 return;
13444 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013445 } else {
13446 // USAD8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013447 if (cond.IsNotNever() &&
13448 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013449 EmitA32(0x0780f010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13450 rn.GetCode() | (rm.GetCode() << 8));
13451 return;
13452 }
13453 }
13454 Delegate(kUsad8, &Assembler::usad8, cond, rd, rn, rm);
13455}
13456
13457void Assembler::usada8(
13458 Condition cond, Register rd, Register rn, Register rm, Register ra) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013459 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013460 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013461 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013462 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013463 if (!ra.Is(pc) &&
13464 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013465 EmitT32_32(0xfb700000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13466 rm.GetCode() | (ra.GetCode() << 12));
13467 AdvanceIT();
13468 return;
13469 }
13470 } else {
13471 // USADA8{<c>}{<q>} <Rd>, <Rn>, <Rm>, <Ra> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013472 if (cond.IsNotNever() && !ra.Is(pc) &&
13473 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013474 EmitA32(0x07800010U | (cond.GetCondition() << 28) | (rd.GetCode() << 16) |
13475 rn.GetCode() | (rm.GetCode() << 8) | (ra.GetCode() << 12));
13476 return;
13477 }
13478 }
13479 Delegate(kUsada8, &Assembler::usada8, cond, rd, rn, rm, ra);
13480}
13481
13482void Assembler::usat(Condition cond,
13483 Register rd,
13484 uint32_t imm,
13485 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013486 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013487 CheckIT(cond);
13488 if (operand.IsImmediateShiftedRegister()) {
13489 Register rn = operand.GetBaseRegister();
13490 Shift shift = operand.GetShift();
13491 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013492 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013493 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013494 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 31) &&
13495 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013496 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13497 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13498 ((amount & 0x1c) << 10));
13499 AdvanceIT();
13500 return;
13501 }
13502 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013503 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) &&
13504 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013505 EmitT32_32(0xf3800000U | (rd.GetCode() << 8) | imm |
13506 (rn.GetCode() << 16) | ((amount & 0x3) << 6) |
13507 ((amount & 0x1c) << 10));
13508 AdvanceIT();
13509 return;
13510 }
13511 } else {
13512 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn>, ASR #<amount> ; A1
13513 if ((imm <= 31) && shift.IsASR() && (amount >= 1) && (amount <= 32) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013514 cond.IsNotNever() &&
13515 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013516 uint32_t amount_ = amount % 32;
13517 EmitA32(0x06e00050U | (cond.GetCondition() << 28) |
13518 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13519 (amount_ << 7));
13520 return;
13521 }
13522 // USAT{<c>}{<q>} <Rd>, #<imm>, <Rn> {, LSL #<amount> } ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013523 if ((imm <= 31) && shift.IsLSL() && (amount <= 31) && cond.IsNotNever() &&
13524 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013525 EmitA32(0x06e00010U | (cond.GetCondition() << 28) |
13526 (rd.GetCode() << 12) | (imm << 16) | rn.GetCode() |
13527 (amount << 7));
13528 return;
13529 }
13530 }
13531 }
13532 Delegate(kUsat, &Assembler::usat, cond, rd, imm, operand);
13533}
13534
13535void Assembler::usat16(Condition cond, Register rd, uint32_t imm, Register rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013536 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013537 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013538 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013539 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013540 if ((imm <= 15) && ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013541 EmitT32_32(0xf3a00000U | (rd.GetCode() << 8) | imm |
13542 (rn.GetCode() << 16));
13543 AdvanceIT();
13544 return;
13545 }
13546 } else {
13547 // USAT16{<c>}{<q>} <Rd>, #<imm>, <Rn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013548 if ((imm <= 15) && cond.IsNotNever() &&
13549 ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013550 EmitA32(0x06e00f30U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13551 (imm << 16) | rn.GetCode());
13552 return;
13553 }
13554 }
13555 Delegate(kUsat16, &Assembler::usat16, cond, rd, imm, rn);
13556}
13557
13558void Assembler::usax(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013559 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013560 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013561 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013562 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013563 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13564 EmitT32_32(0xfae0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13565 rm.GetCode());
13566 AdvanceIT();
13567 return;
13568 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013569 } else {
13570 // USAX{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013571 if (cond.IsNotNever() &&
13572 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013573 EmitA32(0x06500f50U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13574 (rn.GetCode() << 16) | rm.GetCode());
13575 return;
13576 }
13577 }
13578 Delegate(kUsax, &Assembler::usax, cond, rd, rn, rm);
13579}
13580
13581void Assembler::usub16(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013582 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013583 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013584 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013585 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013586 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13587 EmitT32_32(0xfad0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13588 rm.GetCode());
13589 AdvanceIT();
13590 return;
13591 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013592 } else {
13593 // USUB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013594 if (cond.IsNotNever() &&
13595 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013596 EmitA32(0x06500f70U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13597 (rn.GetCode() << 16) | rm.GetCode());
13598 return;
13599 }
13600 }
13601 Delegate(kUsub16, &Assembler::usub16, cond, rd, rn, rm);
13602}
13603
13604void Assembler::usub8(Condition cond, Register rd, Register rn, Register rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013605 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013606 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013607 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013608 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013609 if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
13610 EmitT32_32(0xfac0f040U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13611 rm.GetCode());
13612 AdvanceIT();
13613 return;
13614 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010013615 } else {
13616 // USUB8{<c>}{<q>} {<Rd>}, <Rn>, <Rm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000013617 if (cond.IsNotNever() &&
13618 ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013619 EmitA32(0x06500ff0U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) |
13620 (rn.GetCode() << 16) | rm.GetCode());
13621 return;
13622 }
13623 }
13624 Delegate(kUsub8, &Assembler::usub8, cond, rd, rn, rm);
13625}
13626
13627void Assembler::uxtab(Condition cond,
13628 Register rd,
13629 Register rn,
13630 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013631 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013632 CheckIT(cond);
13633 if (operand.IsImmediateShiftedRegister()) {
13634 Register rm = operand.GetBaseRegister();
13635 Shift shift = operand.GetShift();
13636 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013637 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013638 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13639 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013640 ((amount % 8) == 0) && !rn.Is(pc) &&
13641 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013642 uint32_t amount_ = amount / 8;
13643 EmitT32_32(0xfa50f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13644 rm.GetCode() | (amount_ << 4));
13645 AdvanceIT();
13646 return;
13647 }
13648 } else {
13649 // UXTAB{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13650 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013651 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13652 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013653 uint32_t amount_ = amount / 8;
13654 EmitA32(0x06e00070U | (cond.GetCondition() << 28) |
13655 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13656 (amount_ << 10));
13657 return;
13658 }
13659 }
13660 }
13661 Delegate(kUxtab, &Assembler::uxtab, cond, rd, rn, operand);
13662}
13663
13664void Assembler::uxtab16(Condition cond,
13665 Register rd,
13666 Register rn,
13667 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013668 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013669 CheckIT(cond);
13670 if (operand.IsImmediateShiftedRegister()) {
13671 Register rm = operand.GetBaseRegister();
13672 Shift shift = operand.GetShift();
13673 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013674 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013675 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13676 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013677 ((amount % 8) == 0) && !rn.Is(pc) &&
13678 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013679 uint32_t amount_ = amount / 8;
13680 EmitT32_32(0xfa30f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13681 rm.GetCode() | (amount_ << 4));
13682 AdvanceIT();
13683 return;
13684 }
13685 } else {
13686 // UXTAB16{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13687 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013688 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13689 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013690 uint32_t amount_ = amount / 8;
13691 EmitA32(0x06c00070U | (cond.GetCondition() << 28) |
13692 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13693 (amount_ << 10));
13694 return;
13695 }
13696 }
13697 }
13698 Delegate(kUxtab16, &Assembler::uxtab16, cond, rd, rn, operand);
13699}
13700
13701void Assembler::uxtah(Condition cond,
13702 Register rd,
13703 Register rn,
13704 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013705 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013706 CheckIT(cond);
13707 if (operand.IsImmediateShiftedRegister()) {
13708 Register rm = operand.GetBaseRegister();
13709 Shift shift = operand.GetShift();
13710 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013711 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013712 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; T1
13713 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013714 ((amount % 8) == 0) && !rn.Is(pc) &&
13715 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013716 uint32_t amount_ = amount / 8;
13717 EmitT32_32(0xfa10f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
13718 rm.GetCode() | (amount_ << 4));
13719 AdvanceIT();
13720 return;
13721 }
13722 } else {
13723 // UXTAH{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, ROR #<amount> } ; A1
13724 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013725 ((amount % 8) == 0) && cond.IsNotNever() && !rn.Is(pc) &&
13726 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013727 uint32_t amount_ = amount / 8;
13728 EmitA32(0x06f00070U | (cond.GetCondition() << 28) |
13729 (rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
13730 (amount_ << 10));
13731 return;
13732 }
13733 }
13734 }
13735 Delegate(kUxtah, &Assembler::uxtah, cond, rd, rn, operand);
13736}
13737
13738void Assembler::uxtb(Condition cond,
13739 EncodingSize size,
13740 Register rd,
13741 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013742 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013743 CheckIT(cond);
13744 if (operand.IsImmediateShiftedRegister()) {
13745 Register rm = operand.GetBaseRegister();
13746 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013747 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013748 // UXTB{<c>}{<q>} {<Rd>}, <Rm> ; T1
13749 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13750 EmitT32_16(0xb2c0 | rd.GetCode() | (rm.GetCode() << 3));
13751 AdvanceIT();
13752 return;
13753 }
13754 }
13755 }
13756 Shift shift = operand.GetShift();
13757 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013758 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013759 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13760 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013761 (amount <= 24) && ((amount % 8) == 0) &&
13762 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013763 uint32_t amount_ = amount / 8;
13764 EmitT32_32(0xfa5ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13765 (amount_ << 4));
13766 AdvanceIT();
13767 return;
13768 }
13769 } else {
13770 // UXTB{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13771 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013772 ((amount % 8) == 0) && cond.IsNotNever() &&
13773 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013774 uint32_t amount_ = amount / 8;
13775 EmitA32(0x06ef0070U | (cond.GetCondition() << 28) |
13776 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13777 return;
13778 }
13779 }
13780 }
13781 Delegate(kUxtb, &Assembler::uxtb, cond, size, rd, operand);
13782}
13783
13784void Assembler::uxtb16(Condition cond, Register rd, const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013785 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013786 CheckIT(cond);
13787 if (operand.IsImmediateShiftedRegister()) {
13788 Register rm = operand.GetBaseRegister();
13789 Shift shift = operand.GetShift();
13790 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013791 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013792 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T1
13793 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013794 ((amount % 8) == 0) &&
13795 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013796 uint32_t amount_ = amount / 8;
13797 EmitT32_32(0xfa3ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13798 (amount_ << 4));
13799 AdvanceIT();
13800 return;
13801 }
13802 } else {
13803 // UXTB16{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13804 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013805 ((amount % 8) == 0) && cond.IsNotNever() &&
13806 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013807 uint32_t amount_ = amount / 8;
13808 EmitA32(0x06cf0070U | (cond.GetCondition() << 28) |
13809 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13810 return;
13811 }
13812 }
13813 }
13814 Delegate(kUxtb16, &Assembler::uxtb16, cond, rd, operand);
13815}
13816
13817void Assembler::uxth(Condition cond,
13818 EncodingSize size,
13819 Register rd,
13820 const Operand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013821 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013822 CheckIT(cond);
13823 if (operand.IsImmediateShiftedRegister()) {
13824 Register rm = operand.GetBaseRegister();
13825 if (operand.IsPlainRegister()) {
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013826 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013827 // UXTH{<c>}{<q>} {<Rd>}, <Rm> ; T1
13828 if (!size.IsWide() && rd.IsLow() && rm.IsLow()) {
13829 EmitT32_16(0xb280 | rd.GetCode() | (rm.GetCode() << 3));
13830 AdvanceIT();
13831 return;
13832 }
13833 }
13834 }
13835 Shift shift = operand.GetShift();
13836 uint32_t amount = operand.GetShiftAmount();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013837 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013838 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; T2
13839 if (!size.IsNarrow() && (shift.IsROR() || (amount == 0)) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013840 (amount <= 24) && ((amount % 8) == 0) &&
13841 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013842 uint32_t amount_ = amount / 8;
13843 EmitT32_32(0xfa1ff080U | (rd.GetCode() << 8) | rm.GetCode() |
13844 (amount_ << 4));
13845 AdvanceIT();
13846 return;
13847 }
13848 } else {
13849 // UXTH{<c>}{<q>} {<Rd>}, <Rm> {, ROR #<amount> } ; A1
13850 if ((shift.IsROR() || (amount == 0)) && (amount <= 24) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000013851 ((amount % 8) == 0) && cond.IsNotNever() &&
13852 ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013853 uint32_t amount_ = amount / 8;
13854 EmitA32(0x06ff0070U | (cond.GetCondition() << 28) |
13855 (rd.GetCode() << 12) | rm.GetCode() | (amount_ << 10));
13856 return;
13857 }
13858 }
13859 }
13860 Delegate(kUxth, &Assembler::uxth, cond, size, rd, operand);
13861}
13862
13863void Assembler::vaba(
13864 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013865 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013866 CheckIT(cond);
13867 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013868 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013869 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; T1
13870 if (encoded_dt.IsValid()) {
13871 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13872 EmitT32_32(0xef000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13873 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13874 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13875 AdvanceIT();
13876 return;
13877 }
13878 }
13879 } else {
13880 // VABA{<c>}{<q>}.<dt> <Dd>, <Dn>, <Dm> ; A1
13881 if (encoded_dt.IsValid()) {
13882 if (cond.Is(al)) {
13883 EmitA32(0xf2000710U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13884 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13885 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13886 return;
13887 }
13888 }
13889 }
13890 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13891}
13892
13893void Assembler::vaba(
13894 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013895 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013896 CheckIT(cond);
13897 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013898 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013899 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; T1
13900 if (encoded_dt.IsValid()) {
13901 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13902 EmitT32_32(0xef000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13903 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13904 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13905 AdvanceIT();
13906 return;
13907 }
13908 }
13909 } else {
13910 // VABA{<c>}{<q>}.<dt> <Qd>, <Qn>, <Qm> ; A1
13911 if (encoded_dt.IsValid()) {
13912 if (cond.Is(al)) {
13913 EmitA32(0xf2000750U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13914 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13915 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13916 return;
13917 }
13918 }
13919 }
13920 Delegate(kVaba, &Assembler::vaba, cond, dt, rd, rn, rm);
13921}
13922
13923void Assembler::vabal(
13924 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013925 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013926 CheckIT(cond);
13927 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013928 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013929 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
13930 if (encoded_dt.IsValid()) {
13931 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13932 EmitT32_32(0xef800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13933 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13934 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13935 AdvanceIT();
13936 return;
13937 }
13938 }
13939 } else {
13940 // VABAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
13941 if (encoded_dt.IsValid()) {
13942 if (cond.Is(al)) {
13943 EmitA32(0xf2800500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13944 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13945 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13946 return;
13947 }
13948 }
13949 }
13950 Delegate(kVabal, &Assembler::vabal, cond, dt, rd, rn, rm);
13951}
13952
13953void Assembler::vabd(
13954 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070013955 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010013956 CheckIT(cond);
13957 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010013958 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010013959 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
13960 if (dt.Is(F32)) {
13961 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13962 EmitT32_32(0xff200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13963 rm.Encode(5, 0));
13964 AdvanceIT();
13965 return;
13966 }
13967 }
13968 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
13969 if (encoded_dt.IsValid()) {
13970 if (cond.Is(al) || AllowStronglyDiscouraged()) {
13971 EmitT32_32(0xef000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13972 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
13973 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13974 AdvanceIT();
13975 return;
13976 }
13977 }
13978 } else {
13979 // VABD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
13980 if (dt.Is(F32)) {
13981 if (cond.Is(al)) {
13982 EmitA32(0xf3200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
13983 rm.Encode(5, 0));
13984 return;
13985 }
13986 }
13987 // VABD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
13988 if (encoded_dt.IsValid()) {
13989 if (cond.Is(al)) {
13990 EmitA32(0xf2000700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
13991 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
13992 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
13993 return;
13994 }
13995 }
13996 }
13997 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
13998}
13999
14000void Assembler::vabd(
14001 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014002 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014003 CheckIT(cond);
14004 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014005 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014006 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14007 if (dt.Is(F32)) {
14008 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14009 EmitT32_32(0xff200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14010 rm.Encode(5, 0));
14011 AdvanceIT();
14012 return;
14013 }
14014 }
14015 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14016 if (encoded_dt.IsValid()) {
14017 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14018 EmitT32_32(0xef000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14019 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14020 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14021 AdvanceIT();
14022 return;
14023 }
14024 }
14025 } else {
14026 // VABD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14027 if (dt.Is(F32)) {
14028 if (cond.Is(al)) {
14029 EmitA32(0xf3200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14030 rm.Encode(5, 0));
14031 return;
14032 }
14033 }
14034 // VABD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14035 if (encoded_dt.IsValid()) {
14036 if (cond.Is(al)) {
14037 EmitA32(0xf2000740U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14038 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14039 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14040 return;
14041 }
14042 }
14043 }
14044 Delegate(kVabd, &Assembler::vabd, cond, dt, rd, rn, rm);
14045}
14046
14047void Assembler::vabdl(
14048 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014049 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014050 CheckIT(cond);
14051 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014052 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014053 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14054 if (encoded_dt.IsValid()) {
14055 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14056 EmitT32_32(0xef800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14057 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14058 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14059 AdvanceIT();
14060 return;
14061 }
14062 }
14063 } else {
14064 // VABDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14065 if (encoded_dt.IsValid()) {
14066 if (cond.Is(al)) {
14067 EmitA32(0xf2800700U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14068 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14069 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14070 return;
14071 }
14072 }
14073 }
14074 Delegate(kVabdl, &Assembler::vabdl, cond, dt, rd, rn, rm);
14075}
14076
14077void Assembler::vabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014078 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014079 CheckIT(cond);
14080 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014081 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014082 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
14083 if (encoded_dt.IsValid()) {
14084 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14085 EmitT32_32(0xffb10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14086 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14087 rd.Encode(22, 12) | rm.Encode(5, 0));
14088 AdvanceIT();
14089 return;
14090 }
14091 }
14092 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
14093 if (dt.Is(F64)) {
14094 EmitT32_32(0xeeb00bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14095 AdvanceIT();
14096 return;
14097 }
14098 } else {
14099 // VABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
14100 if (encoded_dt.IsValid()) {
14101 if (cond.Is(al)) {
14102 EmitA32(0xf3b10300U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14103 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14104 rd.Encode(22, 12) | rm.Encode(5, 0));
14105 return;
14106 }
14107 }
14108 // VABS{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
14109 if (dt.Is(F64) && cond.IsNotNever()) {
14110 EmitA32(0x0eb00bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14111 rm.Encode(5, 0));
14112 return;
14113 }
14114 }
14115 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14116}
14117
14118void Assembler::vabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014119 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014120 CheckIT(cond);
14121 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014122 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014123 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
14124 if (encoded_dt.IsValid()) {
14125 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14126 EmitT32_32(0xffb10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14127 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14128 rd.Encode(22, 12) | rm.Encode(5, 0));
14129 AdvanceIT();
14130 return;
14131 }
14132 }
14133 } else {
14134 // VABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
14135 if (encoded_dt.IsValid()) {
14136 if (cond.Is(al)) {
14137 EmitA32(0xf3b10340U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14138 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14139 rd.Encode(22, 12) | rm.Encode(5, 0));
14140 return;
14141 }
14142 }
14143 }
14144 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14145}
14146
14147void Assembler::vabs(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014148 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014149 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014150 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014151 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
14152 if (dt.Is(F32)) {
14153 EmitT32_32(0xeeb00ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
14154 AdvanceIT();
14155 return;
14156 }
14157 } else {
14158 // VABS{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
14159 if (dt.Is(F32) && cond.IsNotNever()) {
14160 EmitA32(0x0eb00ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14161 rm.Encode(5, 0));
14162 return;
14163 }
14164 }
14165 Delegate(kVabs, &Assembler::vabs, cond, dt, rd, rm);
14166}
14167
14168void Assembler::vacge(
14169 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014170 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014171 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014172 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014173 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14174 if (dt.Is(F32)) {
14175 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14176 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14177 rm.Encode(5, 0));
14178 AdvanceIT();
14179 return;
14180 }
14181 }
14182 } else {
14183 // VACGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14184 if (dt.Is(F32)) {
14185 if (cond.Is(al)) {
14186 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14187 rm.Encode(5, 0));
14188 return;
14189 }
14190 }
14191 }
14192 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14193}
14194
14195void Assembler::vacge(
14196 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014197 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014198 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014199 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014200 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14201 if (dt.Is(F32)) {
14202 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14203 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14204 rm.Encode(5, 0));
14205 AdvanceIT();
14206 return;
14207 }
14208 }
14209 } else {
14210 // VACGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14211 if (dt.Is(F32)) {
14212 if (cond.Is(al)) {
14213 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14214 rm.Encode(5, 0));
14215 return;
14216 }
14217 }
14218 }
14219 Delegate(kVacge, &Assembler::vacge, cond, dt, rd, rn, rm);
14220}
14221
14222void Assembler::vacgt(
14223 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014224 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014225 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014226 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014227 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14228 if (dt.Is(F32)) {
14229 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14230 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14231 rm.Encode(5, 0));
14232 AdvanceIT();
14233 return;
14234 }
14235 }
14236 } else {
14237 // VACGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14238 if (dt.Is(F32)) {
14239 if (cond.Is(al)) {
14240 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14241 rm.Encode(5, 0));
14242 return;
14243 }
14244 }
14245 }
14246 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14247}
14248
14249void Assembler::vacgt(
14250 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014251 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014252 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014253 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014254 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14255 if (dt.Is(F32)) {
14256 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14257 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14258 rm.Encode(5, 0));
14259 AdvanceIT();
14260 return;
14261 }
14262 }
14263 } else {
14264 // VACGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14265 if (dt.Is(F32)) {
14266 if (cond.Is(al)) {
14267 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14268 rm.Encode(5, 0));
14269 return;
14270 }
14271 }
14272 }
14273 Delegate(kVacgt, &Assembler::vacgt, cond, dt, rd, rn, rm);
14274}
14275
14276void Assembler::vacle(
14277 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014278 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014279 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014280 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014281 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14282 if (dt.Is(F32)) {
14283 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14284 EmitT32_32(0xff000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14285 rm.Encode(5, 0));
14286 AdvanceIT();
14287 return;
14288 }
14289 }
14290 } else {
14291 // VACLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14292 if (dt.Is(F32)) {
14293 if (cond.Is(al)) {
14294 EmitA32(0xf3000e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14295 rm.Encode(5, 0));
14296 return;
14297 }
14298 }
14299 }
14300 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14301}
14302
14303void Assembler::vacle(
14304 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014305 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014306 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014307 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014308 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14309 if (dt.Is(F32)) {
14310 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14311 EmitT32_32(0xff000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14312 rm.Encode(5, 0));
14313 AdvanceIT();
14314 return;
14315 }
14316 }
14317 } else {
14318 // VACLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14319 if (dt.Is(F32)) {
14320 if (cond.Is(al)) {
14321 EmitA32(0xf3000e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14322 rm.Encode(5, 0));
14323 return;
14324 }
14325 }
14326 }
14327 Delegate(kVacle, &Assembler::vacle, cond, dt, rd, rn, rm);
14328}
14329
14330void Assembler::vaclt(
14331 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014332 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014333 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014334 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014335 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14336 if (dt.Is(F32)) {
14337 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14338 EmitT32_32(0xff200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14339 rm.Encode(5, 0));
14340 AdvanceIT();
14341 return;
14342 }
14343 }
14344 } else {
14345 // VACLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14346 if (dt.Is(F32)) {
14347 if (cond.Is(al)) {
14348 EmitA32(0xf3200e10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14349 rm.Encode(5, 0));
14350 return;
14351 }
14352 }
14353 }
14354 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14355}
14356
14357void Assembler::vaclt(
14358 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014359 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014360 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014361 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014362 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14363 if (dt.Is(F32)) {
14364 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14365 EmitT32_32(0xff200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14366 rm.Encode(5, 0));
14367 AdvanceIT();
14368 return;
14369 }
14370 }
14371 } else {
14372 // VACLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14373 if (dt.Is(F32)) {
14374 if (cond.Is(al)) {
14375 EmitA32(0xf3200e50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14376 rm.Encode(5, 0));
14377 return;
14378 }
14379 }
14380 }
14381 Delegate(kVaclt, &Assembler::vaclt, cond, dt, rd, rn, rm);
14382}
14383
14384void Assembler::vadd(
14385 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014386 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014387 CheckIT(cond);
14388 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014389 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014390 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
14391 if (dt.Is(F32)) {
14392 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14393 EmitT32_32(0xef000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14394 rm.Encode(5, 0));
14395 AdvanceIT();
14396 return;
14397 }
14398 }
14399 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
14400 if (dt.Is(F64)) {
14401 EmitT32_32(0xee300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14402 rm.Encode(5, 0));
14403 AdvanceIT();
14404 return;
14405 }
14406 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
14407 if (encoded_dt.IsValid()) {
14408 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14409 EmitT32_32(0xef000800U | (encoded_dt.GetEncodingValue() << 20) |
14410 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14411 AdvanceIT();
14412 return;
14413 }
14414 }
14415 } else {
14416 // VADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
14417 if (dt.Is(F32)) {
14418 if (cond.Is(al)) {
14419 EmitA32(0xf2000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14420 rm.Encode(5, 0));
14421 return;
14422 }
14423 }
14424 // VADD{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
14425 if (dt.Is(F64) && cond.IsNotNever()) {
14426 EmitA32(0x0e300b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14427 rn.Encode(7, 16) | rm.Encode(5, 0));
14428 return;
14429 }
14430 // VADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
14431 if (encoded_dt.IsValid()) {
14432 if (cond.Is(al)) {
14433 EmitA32(0xf2000800U | (encoded_dt.GetEncodingValue() << 20) |
14434 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14435 return;
14436 }
14437 }
14438 }
14439 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14440}
14441
14442void Assembler::vadd(
14443 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014444 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014445 CheckIT(cond);
14446 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014447 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014448 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
14449 if (dt.Is(F32)) {
14450 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14451 EmitT32_32(0xef000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14452 rm.Encode(5, 0));
14453 AdvanceIT();
14454 return;
14455 }
14456 }
14457 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
14458 if (encoded_dt.IsValid()) {
14459 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14460 EmitT32_32(0xef000840U | (encoded_dt.GetEncodingValue() << 20) |
14461 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14462 AdvanceIT();
14463 return;
14464 }
14465 }
14466 } else {
14467 // VADD{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
14468 if (dt.Is(F32)) {
14469 if (cond.Is(al)) {
14470 EmitA32(0xf2000d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14471 rm.Encode(5, 0));
14472 return;
14473 }
14474 }
14475 // VADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
14476 if (encoded_dt.IsValid()) {
14477 if (cond.Is(al)) {
14478 EmitA32(0xf2000840U | (encoded_dt.GetEncodingValue() << 20) |
14479 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14480 return;
14481 }
14482 }
14483 }
14484 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14485}
14486
14487void Assembler::vadd(
14488 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014489 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014490 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014491 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014492 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
14493 if (dt.Is(F32)) {
14494 EmitT32_32(0xee300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14495 rm.Encode(5, 0));
14496 AdvanceIT();
14497 return;
14498 }
14499 } else {
14500 // VADD{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
14501 if (dt.Is(F32) && cond.IsNotNever()) {
14502 EmitA32(0x0e300a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
14503 rn.Encode(7, 16) | rm.Encode(5, 0));
14504 return;
14505 }
14506 }
14507 Delegate(kVadd, &Assembler::vadd, cond, dt, rd, rn, rm);
14508}
14509
14510void Assembler::vaddhn(
14511 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014512 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014513 CheckIT(cond);
14514 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014515 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014516 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
14517 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14518 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14519 EmitT32_32(0xef800400U | (encoded_dt.GetEncodingValue() << 20) |
14520 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14521 AdvanceIT();
14522 return;
14523 }
14524 }
14525 } else {
14526 // VADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
14527 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
14528 if (cond.Is(al)) {
14529 EmitA32(0xf2800400U | (encoded_dt.GetEncodingValue() << 20) |
14530 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14531 return;
14532 }
14533 }
14534 }
14535 Delegate(kVaddhn, &Assembler::vaddhn, cond, dt, rd, rn, rm);
14536}
14537
14538void Assembler::vaddl(
14539 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014540 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014541 CheckIT(cond);
14542 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014543 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014544 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
14545 if (encoded_dt.IsValid()) {
14546 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14547 EmitT32_32(0xef800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14548 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14549 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14550 AdvanceIT();
14551 return;
14552 }
14553 }
14554 } else {
14555 // VADDL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
14556 if (encoded_dt.IsValid()) {
14557 if (cond.Is(al)) {
14558 EmitA32(0xf2800000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14559 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14560 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14561 return;
14562 }
14563 }
14564 }
14565 Delegate(kVaddl, &Assembler::vaddl, cond, dt, rd, rn, rm);
14566}
14567
14568void Assembler::vaddw(
14569 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014570 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014571 CheckIT(cond);
14572 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014573 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014574 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
14575 if (encoded_dt.IsValid()) {
14576 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14577 EmitT32_32(0xef800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14578 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
14579 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14580 AdvanceIT();
14581 return;
14582 }
14583 }
14584 } else {
14585 // VADDW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
14586 if (encoded_dt.IsValid()) {
14587 if (cond.Is(al)) {
14588 EmitA32(0xf2800100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
14589 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
14590 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
14591 return;
14592 }
14593 }
14594 }
14595 Delegate(kVaddw, &Assembler::vaddw, cond, dt, rd, rn, rm);
14596}
14597
14598void Assembler::vand(Condition cond,
14599 DataType dt,
14600 DRegister rd,
14601 DRegister rn,
14602 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014603 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014604 CheckIT(cond);
14605 if (operand.IsImmediate()) {
14606 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014607 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014608 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14609 if (encoded_dt.IsValid() && rd.Is(rn)) {
14610 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14611 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14612 rd.Encode(22, 12) |
14613 (encoded_dt.GetEncodedImmediate() & 0xf) |
14614 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14615 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14616 AdvanceIT();
14617 return;
14618 }
14619 }
14620 } else {
14621 // VAND{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14622 if (encoded_dt.IsValid() && rd.Is(rn)) {
14623 if (cond.Is(al)) {
14624 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14625 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14626 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14627 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14628 return;
14629 }
14630 }
14631 }
14632 }
14633 if (operand.IsRegister()) {
14634 DRegister rm = operand.GetRegister();
14635 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014636 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014637 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14638 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14639 EmitT32_32(0xef000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14640 rm.Encode(5, 0));
14641 AdvanceIT();
14642 return;
14643 }
14644 } else {
14645 // VAND{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14646 if (cond.Is(al)) {
14647 EmitA32(0xf2000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14648 rm.Encode(5, 0));
14649 return;
14650 }
14651 }
14652 }
14653 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14654}
14655
14656void Assembler::vand(Condition cond,
14657 DataType dt,
14658 QRegister rd,
14659 QRegister rn,
14660 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014661 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014662 CheckIT(cond);
14663 if (operand.IsImmediate()) {
14664 ImmediateVand encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014665 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014666 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14667 if (encoded_dt.IsValid() && rd.Is(rn)) {
14668 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14669 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14670 rd.Encode(22, 12) |
14671 (encoded_dt.GetEncodedImmediate() & 0xf) |
14672 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14673 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14674 AdvanceIT();
14675 return;
14676 }
14677 }
14678 } else {
14679 // VAND{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14680 if (encoded_dt.IsValid() && rd.Is(rn)) {
14681 if (cond.Is(al)) {
14682 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14683 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14684 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14685 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14686 return;
14687 }
14688 }
14689 }
14690 }
14691 if (operand.IsRegister()) {
14692 QRegister rm = operand.GetRegister();
14693 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014694 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014695 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14696 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14697 EmitT32_32(0xef000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14698 rm.Encode(5, 0));
14699 AdvanceIT();
14700 return;
14701 }
14702 } else {
14703 // VAND{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14704 if (cond.Is(al)) {
14705 EmitA32(0xf2000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14706 rm.Encode(5, 0));
14707 return;
14708 }
14709 }
14710 }
14711 Delegate(kVand, &Assembler::vand, cond, dt, rd, rn, operand);
14712}
14713
14714void Assembler::vbic(Condition cond,
14715 DataType dt,
14716 DRegister rd,
14717 DRegister rn,
14718 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014719 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014720 CheckIT(cond);
14721 if (operand.IsImmediate()) {
14722 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014723 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014724 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
14725 if (encoded_dt.IsValid() && rd.Is(rn)) {
14726 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14727 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
14728 rd.Encode(22, 12) |
14729 (encoded_dt.GetEncodedImmediate() & 0xf) |
14730 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14731 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14732 AdvanceIT();
14733 return;
14734 }
14735 }
14736 } else {
14737 // VBIC{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
14738 if (encoded_dt.IsValid() && rd.Is(rn)) {
14739 if (cond.Is(al)) {
14740 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
14741 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14742 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14743 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14744 return;
14745 }
14746 }
14747 }
14748 }
14749 if (operand.IsRegister()) {
14750 DRegister rm = operand.GetRegister();
14751 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014752 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014753 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14754 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14755 EmitT32_32(0xef100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14756 rm.Encode(5, 0));
14757 AdvanceIT();
14758 return;
14759 }
14760 } else {
14761 // VBIC{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14762 if (cond.Is(al)) {
14763 EmitA32(0xf2100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14764 rm.Encode(5, 0));
14765 return;
14766 }
14767 }
14768 }
14769 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14770}
14771
14772void Assembler::vbic(Condition cond,
14773 DataType dt,
14774 QRegister rd,
14775 QRegister rn,
14776 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014777 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014778 CheckIT(cond);
14779 if (operand.IsImmediate()) {
14780 ImmediateVbic encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014781 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014782 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
14783 if (encoded_dt.IsValid() && rd.Is(rn)) {
14784 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14785 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
14786 rd.Encode(22, 12) |
14787 (encoded_dt.GetEncodedImmediate() & 0xf) |
14788 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14789 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
14790 AdvanceIT();
14791 return;
14792 }
14793 }
14794 } else {
14795 // VBIC{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
14796 if (encoded_dt.IsValid() && rd.Is(rn)) {
14797 if (cond.Is(al)) {
14798 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
14799 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
14800 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
14801 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
14802 return;
14803 }
14804 }
14805 }
14806 }
14807 if (operand.IsRegister()) {
14808 QRegister rm = operand.GetRegister();
14809 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014810 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014811 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14812 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14813 EmitT32_32(0xef100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14814 rm.Encode(5, 0));
14815 AdvanceIT();
14816 return;
14817 }
14818 } else {
14819 // VBIC{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14820 if (cond.Is(al)) {
14821 EmitA32(0xf2100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14822 rm.Encode(5, 0));
14823 return;
14824 }
14825 }
14826 }
14827 Delegate(kVbic, &Assembler::vbic, cond, dt, rd, rn, operand);
14828}
14829
14830void Assembler::vbif(
14831 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014832 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014833 CheckIT(cond);
14834 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014835 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014836 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14837 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14838 EmitT32_32(0xff300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14839 rm.Encode(5, 0));
14840 AdvanceIT();
14841 return;
14842 }
14843 } else {
14844 // VBIF{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14845 if (cond.Is(al)) {
14846 EmitA32(0xf3300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14847 rm.Encode(5, 0));
14848 return;
14849 }
14850 }
14851 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14852}
14853
14854void Assembler::vbif(
14855 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014856 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014857 CheckIT(cond);
14858 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014859 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014860 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14861 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14862 EmitT32_32(0xff300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14863 rm.Encode(5, 0));
14864 AdvanceIT();
14865 return;
14866 }
14867 } else {
14868 // VBIF{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14869 if (cond.Is(al)) {
14870 EmitA32(0xf3300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14871 rm.Encode(5, 0));
14872 return;
14873 }
14874 }
14875 Delegate(kVbif, &Assembler::vbif, cond, dt, rd, rn, rm);
14876}
14877
14878void Assembler::vbit(
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 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14885 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14886 EmitT32_32(0xff200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14887 rm.Encode(5, 0));
14888 AdvanceIT();
14889 return;
14890 }
14891 } else {
14892 // VBIT{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14893 if (cond.Is(al)) {
14894 EmitA32(0xf3200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14895 rm.Encode(5, 0));
14896 return;
14897 }
14898 }
14899 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14900}
14901
14902void Assembler::vbit(
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 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14910 EmitT32_32(0xff200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14911 rm.Encode(5, 0));
14912 AdvanceIT();
14913 return;
14914 }
14915 } else {
14916 // VBIT{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14917 if (cond.Is(al)) {
14918 EmitA32(0xf3200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14919 rm.Encode(5, 0));
14920 return;
14921 }
14922 }
14923 Delegate(kVbit, &Assembler::vbit, cond, dt, rd, rn, rm);
14924}
14925
14926void Assembler::vbsl(
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 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
14933 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14934 EmitT32_32(0xff100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14935 rm.Encode(5, 0));
14936 AdvanceIT();
14937 return;
14938 }
14939 } else {
14940 // VBSL{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
14941 if (cond.Is(al)) {
14942 EmitA32(0xf3100110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14943 rm.Encode(5, 0));
14944 return;
14945 }
14946 }
14947 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14948}
14949
14950void Assembler::vbsl(
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 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
14957 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14958 EmitT32_32(0xff100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14959 rm.Encode(5, 0));
14960 AdvanceIT();
14961 return;
14962 }
14963 } else {
14964 // VBSL{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
14965 if (cond.Is(al)) {
14966 EmitA32(0xf3100150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
14967 rm.Encode(5, 0));
14968 return;
14969 }
14970 }
14971 Delegate(kVbsl, &Assembler::vbsl, cond, dt, rd, rn, rm);
14972}
14973
14974void Assembler::vceq(Condition cond,
14975 DataType dt,
14976 DRegister rd,
14977 DRegister rm,
14978 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070014979 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010014980 CheckIT(cond);
14981 if (operand.IsImmediate()) {
14982 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
14983 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
14984 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010014985 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010014986 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
14987 if (encoded_dt.IsValid() && (imm == 0)) {
14988 if (cond.Is(al) || AllowStronglyDiscouraged()) {
14989 EmitT32_32(0xffb10100U |
14990 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
14991 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
14992 rd.Encode(22, 12) | rm.Encode(5, 0));
14993 AdvanceIT();
14994 return;
14995 }
14996 }
14997 } else {
14998 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
14999 if (encoded_dt.IsValid() && (imm == 0)) {
15000 if (cond.Is(al)) {
15001 EmitA32(0xf3b10100U |
15002 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15003 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15004 rd.Encode(22, 12) | rm.Encode(5, 0));
15005 return;
15006 }
15007 }
15008 }
15009 }
15010 }
15011 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15012}
15013
15014void Assembler::vceq(Condition cond,
15015 DataType dt,
15016 QRegister rd,
15017 QRegister rm,
15018 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015019 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015020 CheckIT(cond);
15021 if (operand.IsImmediate()) {
15022 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15023 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15024 Dt_F_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015025 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015026 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15027 if (encoded_dt.IsValid() && (imm == 0)) {
15028 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15029 EmitT32_32(0xffb10140U |
15030 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15031 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15032 rd.Encode(22, 12) | rm.Encode(5, 0));
15033 AdvanceIT();
15034 return;
15035 }
15036 }
15037 } else {
15038 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15039 if (encoded_dt.IsValid() && (imm == 0)) {
15040 if (cond.Is(al)) {
15041 EmitA32(0xf3b10140U |
15042 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15043 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15044 rd.Encode(22, 12) | rm.Encode(5, 0));
15045 return;
15046 }
15047 }
15048 }
15049 }
15050 }
15051 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rm, operand);
15052}
15053
15054void Assembler::vceq(
15055 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015056 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015057 CheckIT(cond);
15058 Dt_size_4 encoded_dt(dt);
15059 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015060 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015061 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15062 if (encoded_dt.IsValid()) {
15063 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15064 EmitT32_32(0xff000810U | (encoded_dt.GetEncodingValue() << 20) |
15065 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15066 AdvanceIT();
15067 return;
15068 }
15069 }
15070 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T2
15071 if (encoded_dt_2.IsValid()) {
15072 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15073 EmitT32_32(0xef000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15074 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15075 AdvanceIT();
15076 return;
15077 }
15078 }
15079 } else {
15080 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15081 if (encoded_dt.IsValid()) {
15082 if (cond.Is(al)) {
15083 EmitA32(0xf3000810U | (encoded_dt.GetEncodingValue() << 20) |
15084 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15085 return;
15086 }
15087 }
15088 // VCEQ{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A2
15089 if (encoded_dt_2.IsValid()) {
15090 if (cond.Is(al)) {
15091 EmitA32(0xf2000e00U | (encoded_dt_2.GetEncodingValue() << 20) |
15092 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15093 return;
15094 }
15095 }
15096 }
15097 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15098}
15099
15100void Assembler::vceq(
15101 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015102 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015103 CheckIT(cond);
15104 Dt_size_4 encoded_dt(dt);
15105 Dt_sz_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015106 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015107 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15108 if (encoded_dt.IsValid()) {
15109 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15110 EmitT32_32(0xff000850U | (encoded_dt.GetEncodingValue() << 20) |
15111 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15112 AdvanceIT();
15113 return;
15114 }
15115 }
15116 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T2
15117 if (encoded_dt_2.IsValid()) {
15118 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15119 EmitT32_32(0xef000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15120 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15121 AdvanceIT();
15122 return;
15123 }
15124 }
15125 } else {
15126 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15127 if (encoded_dt.IsValid()) {
15128 if (cond.Is(al)) {
15129 EmitA32(0xf3000850U | (encoded_dt.GetEncodingValue() << 20) |
15130 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15131 return;
15132 }
15133 }
15134 // VCEQ{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A2
15135 if (encoded_dt_2.IsValid()) {
15136 if (cond.Is(al)) {
15137 EmitA32(0xf2000e40U | (encoded_dt_2.GetEncodingValue() << 20) |
15138 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15139 return;
15140 }
15141 }
15142 }
15143 Delegate(kVceq, &Assembler::vceq, cond, dt, rd, rn, rm);
15144}
15145
15146void Assembler::vcge(Condition cond,
15147 DataType dt,
15148 DRegister rd,
15149 DRegister rm,
15150 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015151 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015152 CheckIT(cond);
15153 if (operand.IsImmediate()) {
15154 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15155 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15156 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015157 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015158 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15159 if (encoded_dt.IsValid() && (imm == 0)) {
15160 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15161 EmitT32_32(0xffb10080U |
15162 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15163 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15164 rd.Encode(22, 12) | rm.Encode(5, 0));
15165 AdvanceIT();
15166 return;
15167 }
15168 }
15169 } else {
15170 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15171 if (encoded_dt.IsValid() && (imm == 0)) {
15172 if (cond.Is(al)) {
15173 EmitA32(0xf3b10080U |
15174 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15175 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15176 rd.Encode(22, 12) | rm.Encode(5, 0));
15177 return;
15178 }
15179 }
15180 }
15181 }
15182 }
15183 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15184}
15185
15186void Assembler::vcge(Condition cond,
15187 DataType dt,
15188 QRegister rd,
15189 QRegister rm,
15190 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015191 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015192 CheckIT(cond);
15193 if (operand.IsImmediate()) {
15194 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15195 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15196 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015197 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015198 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15199 if (encoded_dt.IsValid() && (imm == 0)) {
15200 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15201 EmitT32_32(0xffb100c0U |
15202 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15203 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15204 rd.Encode(22, 12) | rm.Encode(5, 0));
15205 AdvanceIT();
15206 return;
15207 }
15208 }
15209 } else {
15210 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15211 if (encoded_dt.IsValid() && (imm == 0)) {
15212 if (cond.Is(al)) {
15213 EmitA32(0xf3b100c0U |
15214 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15215 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15216 rd.Encode(22, 12) | rm.Encode(5, 0));
15217 return;
15218 }
15219 }
15220 }
15221 }
15222 }
15223 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rm, operand);
15224}
15225
15226void Assembler::vcge(
15227 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015228 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015229 CheckIT(cond);
15230 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015231 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015232 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15233 if (encoded_dt.IsValid()) {
15234 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15235 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15236 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015237 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015238 AdvanceIT();
15239 return;
15240 }
15241 }
15242 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15243 if (dt.Is(F32)) {
15244 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15245 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15246 rm.Encode(5, 0));
15247 AdvanceIT();
15248 return;
15249 }
15250 }
15251 } else {
15252 // VCGE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15253 if (encoded_dt.IsValid()) {
15254 if (cond.Is(al)) {
15255 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15256 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15257 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15258 return;
15259 }
15260 }
15261 // VCGE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15262 if (dt.Is(F32)) {
15263 if (cond.Is(al)) {
15264 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15265 rm.Encode(5, 0));
15266 return;
15267 }
15268 }
15269 }
15270 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15271}
15272
15273void Assembler::vcge(
15274 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015275 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015276 CheckIT(cond);
15277 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015278 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015279 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15280 if (encoded_dt.IsValid()) {
15281 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15282 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15283 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015284 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015285 AdvanceIT();
15286 return;
15287 }
15288 }
15289 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15290 if (dt.Is(F32)) {
15291 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15292 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15293 rm.Encode(5, 0));
15294 AdvanceIT();
15295 return;
15296 }
15297 }
15298 } else {
15299 // VCGE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15300 if (encoded_dt.IsValid()) {
15301 if (cond.Is(al)) {
15302 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15303 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15304 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15305 return;
15306 }
15307 }
15308 // VCGE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15309 if (dt.Is(F32)) {
15310 if (cond.Is(al)) {
15311 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15312 rm.Encode(5, 0));
15313 return;
15314 }
15315 }
15316 }
15317 Delegate(kVcge, &Assembler::vcge, cond, dt, rd, rn, rm);
15318}
15319
15320void Assembler::vcgt(Condition cond,
15321 DataType dt,
15322 DRegister rd,
15323 DRegister rm,
15324 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015325 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015326 CheckIT(cond);
15327 if (operand.IsImmediate()) {
15328 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15329 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15330 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015331 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015332 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15333 if (encoded_dt.IsValid() && (imm == 0)) {
15334 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15335 EmitT32_32(0xffb10000U |
15336 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15337 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15338 rd.Encode(22, 12) | rm.Encode(5, 0));
15339 AdvanceIT();
15340 return;
15341 }
15342 }
15343 } else {
15344 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15345 if (encoded_dt.IsValid() && (imm == 0)) {
15346 if (cond.Is(al)) {
15347 EmitA32(0xf3b10000U |
15348 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15349 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15350 rd.Encode(22, 12) | rm.Encode(5, 0));
15351 return;
15352 }
15353 }
15354 }
15355 }
15356 }
15357 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15358}
15359
15360void Assembler::vcgt(Condition cond,
15361 DataType dt,
15362 QRegister rd,
15363 QRegister rm,
15364 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015365 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015366 CheckIT(cond);
15367 if (operand.IsImmediate()) {
15368 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15369 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15370 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015371 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015372 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15373 if (encoded_dt.IsValid() && (imm == 0)) {
15374 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15375 EmitT32_32(0xffb10040U |
15376 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15377 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15378 rd.Encode(22, 12) | rm.Encode(5, 0));
15379 AdvanceIT();
15380 return;
15381 }
15382 }
15383 } else {
15384 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15385 if (encoded_dt.IsValid() && (imm == 0)) {
15386 if (cond.Is(al)) {
15387 EmitA32(0xf3b10040U |
15388 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15389 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15390 rd.Encode(22, 12) | rm.Encode(5, 0));
15391 return;
15392 }
15393 }
15394 }
15395 }
15396 }
15397 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rm, operand);
15398}
15399
15400void Assembler::vcgt(
15401 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015402 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015403 CheckIT(cond);
15404 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015405 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015406 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15407 if (encoded_dt.IsValid()) {
15408 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15409 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15410 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015411 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015412 AdvanceIT();
15413 return;
15414 }
15415 }
15416 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15417 if (dt.Is(F32)) {
15418 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15419 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15420 rm.Encode(5, 0));
15421 AdvanceIT();
15422 return;
15423 }
15424 }
15425 } else {
15426 // VCGT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15427 if (encoded_dt.IsValid()) {
15428 if (cond.Is(al)) {
15429 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15430 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15431 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15432 return;
15433 }
15434 }
15435 // VCGT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15436 if (dt.Is(F32)) {
15437 if (cond.Is(al)) {
15438 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15439 rm.Encode(5, 0));
15440 return;
15441 }
15442 }
15443 }
15444 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15445}
15446
15447void Assembler::vcgt(
15448 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015449 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015450 CheckIT(cond);
15451 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015452 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015453 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15454 if (encoded_dt.IsValid()) {
15455 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15456 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15457 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois8ee2cef2016-09-12 13:22:22 +000015458 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015459 AdvanceIT();
15460 return;
15461 }
15462 }
15463 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15464 if (dt.Is(F32)) {
15465 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15466 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15467 rm.Encode(5, 0));
15468 AdvanceIT();
15469 return;
15470 }
15471 }
15472 } else {
15473 // VCGT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15474 if (encoded_dt.IsValid()) {
15475 if (cond.Is(al)) {
15476 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15477 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
15478 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
15479 return;
15480 }
15481 }
15482 // VCGT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15483 if (dt.Is(F32)) {
15484 if (cond.Is(al)) {
15485 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
15486 rm.Encode(5, 0));
15487 return;
15488 }
15489 }
15490 }
15491 Delegate(kVcgt, &Assembler::vcgt, cond, dt, rd, rn, rm);
15492}
15493
15494void Assembler::vcle(Condition cond,
15495 DataType dt,
15496 DRegister rd,
15497 DRegister rm,
15498 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015499 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015500 CheckIT(cond);
15501 if (operand.IsImmediate()) {
15502 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15503 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15504 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015505 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015506 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15507 if (encoded_dt.IsValid() && (imm == 0)) {
15508 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15509 EmitT32_32(0xffb10180U |
15510 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15511 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15512 rd.Encode(22, 12) | rm.Encode(5, 0));
15513 AdvanceIT();
15514 return;
15515 }
15516 }
15517 } else {
15518 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15519 if (encoded_dt.IsValid() && (imm == 0)) {
15520 if (cond.Is(al)) {
15521 EmitA32(0xf3b10180U |
15522 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15523 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15524 rd.Encode(22, 12) | rm.Encode(5, 0));
15525 return;
15526 }
15527 }
15528 }
15529 }
15530 }
15531 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15532}
15533
15534void Assembler::vcle(Condition cond,
15535 DataType dt,
15536 QRegister rd,
15537 QRegister rm,
15538 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015539 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015540 CheckIT(cond);
15541 if (operand.IsImmediate()) {
15542 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15543 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15544 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015545 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015546 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15547 if (encoded_dt.IsValid() && (imm == 0)) {
15548 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15549 EmitT32_32(0xffb101c0U |
15550 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15551 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15552 rd.Encode(22, 12) | rm.Encode(5, 0));
15553 AdvanceIT();
15554 return;
15555 }
15556 }
15557 } else {
15558 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15559 if (encoded_dt.IsValid() && (imm == 0)) {
15560 if (cond.Is(al)) {
15561 EmitA32(0xf3b101c0U |
15562 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15563 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15564 rd.Encode(22, 12) | rm.Encode(5, 0));
15565 return;
15566 }
15567 }
15568 }
15569 }
15570 }
15571 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rm, operand);
15572}
15573
15574void Assembler::vcle(
15575 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015576 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015577 CheckIT(cond);
15578 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015579 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015580 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15581 if (encoded_dt.IsValid()) {
15582 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15583 EmitT32_32(0xef000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15584 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015585 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015586 AdvanceIT();
15587 return;
15588 }
15589 }
15590 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15591 if (dt.Is(F32)) {
15592 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015593 EmitT32_32(0xff000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15594 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015595 AdvanceIT();
15596 return;
15597 }
15598 }
15599 } else {
15600 // VCLE{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15601 if (encoded_dt.IsValid()) {
15602 if (cond.Is(al)) {
15603 EmitA32(0xf2000310U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15604 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015605 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015606 return;
15607 }
15608 }
15609 // VCLE{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15610 if (dt.Is(F32)) {
15611 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015612 EmitA32(0xf3000e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15613 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015614 return;
15615 }
15616 }
15617 }
15618 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15619}
15620
15621void Assembler::vcle(
15622 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015623 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015624 CheckIT(cond);
15625 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015626 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015627 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15628 if (encoded_dt.IsValid()) {
15629 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15630 EmitT32_32(0xef000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15631 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015632 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015633 AdvanceIT();
15634 return;
15635 }
15636 }
15637 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15638 if (dt.Is(F32)) {
15639 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015640 EmitT32_32(0xff000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15641 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015642 AdvanceIT();
15643 return;
15644 }
15645 }
15646 } else {
15647 // VCLE{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15648 if (encoded_dt.IsValid()) {
15649 if (cond.Is(al)) {
15650 EmitA32(0xf2000350U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15651 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015652 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015653 return;
15654 }
15655 }
15656 // VCLE{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15657 if (dt.Is(F32)) {
15658 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015659 EmitA32(0xf3000e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15660 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015661 return;
15662 }
15663 }
15664 }
15665 Delegate(kVcle, &Assembler::vcle, cond, dt, rd, rn, rm);
15666}
15667
15668void Assembler::vcls(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015669 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015670 CheckIT(cond);
15671 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015672 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015673 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15674 if (encoded_dt.IsValid()) {
15675 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15676 EmitT32_32(0xffb00400U | (encoded_dt.GetEncodingValue() << 18) |
15677 rd.Encode(22, 12) | rm.Encode(5, 0));
15678 AdvanceIT();
15679 return;
15680 }
15681 }
15682 } else {
15683 // VCLS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15684 if (encoded_dt.IsValid()) {
15685 if (cond.Is(al)) {
15686 EmitA32(0xf3b00400U | (encoded_dt.GetEncodingValue() << 18) |
15687 rd.Encode(22, 12) | rm.Encode(5, 0));
15688 return;
15689 }
15690 }
15691 }
15692 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15693}
15694
15695void Assembler::vcls(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015696 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015697 CheckIT(cond);
15698 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015699 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015700 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15701 if (encoded_dt.IsValid()) {
15702 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15703 EmitT32_32(0xffb00440U | (encoded_dt.GetEncodingValue() << 18) |
15704 rd.Encode(22, 12) | rm.Encode(5, 0));
15705 AdvanceIT();
15706 return;
15707 }
15708 }
15709 } else {
15710 // VCLS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15711 if (encoded_dt.IsValid()) {
15712 if (cond.Is(al)) {
15713 EmitA32(0xf3b00440U | (encoded_dt.GetEncodingValue() << 18) |
15714 rd.Encode(22, 12) | rm.Encode(5, 0));
15715 return;
15716 }
15717 }
15718 }
15719 Delegate(kVcls, &Assembler::vcls, cond, dt, rd, rm);
15720}
15721
15722void Assembler::vclt(Condition cond,
15723 DataType dt,
15724 DRegister rd,
15725 DRegister rm,
15726 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015727 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015728 CheckIT(cond);
15729 if (operand.IsImmediate()) {
15730 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15731 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15732 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015733 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015734 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; T1
15735 if (encoded_dt.IsValid() && (imm == 0)) {
15736 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15737 EmitT32_32(0xffb10200U |
15738 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15739 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15740 rd.Encode(22, 12) | rm.Encode(5, 0));
15741 AdvanceIT();
15742 return;
15743 }
15744 }
15745 } else {
15746 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #0 ; A1
15747 if (encoded_dt.IsValid() && (imm == 0)) {
15748 if (cond.Is(al)) {
15749 EmitA32(0xf3b10200U |
15750 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15751 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15752 rd.Encode(22, 12) | rm.Encode(5, 0));
15753 return;
15754 }
15755 }
15756 }
15757 }
15758 }
15759 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15760}
15761
15762void Assembler::vclt(Condition cond,
15763 DataType dt,
15764 QRegister rd,
15765 QRegister rm,
15766 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015767 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015768 CheckIT(cond);
15769 if (operand.IsImmediate()) {
15770 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
15771 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
15772 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015773 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015774 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; T1
15775 if (encoded_dt.IsValid() && (imm == 0)) {
15776 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15777 EmitT32_32(0xffb10240U |
15778 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15779 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15780 rd.Encode(22, 12) | rm.Encode(5, 0));
15781 AdvanceIT();
15782 return;
15783 }
15784 }
15785 } else {
15786 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #0 ; A1
15787 if (encoded_dt.IsValid() && (imm == 0)) {
15788 if (cond.Is(al)) {
15789 EmitA32(0xf3b10240U |
15790 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
15791 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
15792 rd.Encode(22, 12) | rm.Encode(5, 0));
15793 return;
15794 }
15795 }
15796 }
15797 }
15798 }
15799 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rm, operand);
15800}
15801
15802void Assembler::vclt(
15803 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015804 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015805 CheckIT(cond);
15806 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015807 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015808 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
15809 if (encoded_dt.IsValid()) {
15810 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15811 EmitT32_32(0xef000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15812 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015813 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015814 AdvanceIT();
15815 return;
15816 }
15817 }
15818 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T2
15819 if (dt.Is(F32)) {
15820 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015821 EmitT32_32(0xff200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15822 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015823 AdvanceIT();
15824 return;
15825 }
15826 }
15827 } else {
15828 // VCLT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
15829 if (encoded_dt.IsValid()) {
15830 if (cond.Is(al)) {
15831 EmitA32(0xf2000300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15832 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015833 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015834 return;
15835 }
15836 }
15837 // VCLT{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A2
15838 if (dt.Is(F32)) {
15839 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015840 EmitA32(0xf3200e00U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15841 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015842 return;
15843 }
15844 }
15845 }
15846 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15847}
15848
15849void Assembler::vclt(
15850 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015851 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015852 CheckIT(cond);
15853 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015854 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015855 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
15856 if (encoded_dt.IsValid()) {
15857 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15858 EmitT32_32(0xef000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15859 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015860 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015861 AdvanceIT();
15862 return;
15863 }
15864 }
15865 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T2
15866 if (dt.Is(F32)) {
15867 if (cond.Is(al) || AllowStronglyDiscouraged()) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015868 EmitT32_32(0xff200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15869 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015870 AdvanceIT();
15871 return;
15872 }
15873 }
15874 } else {
15875 // VCLT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
15876 if (encoded_dt.IsValid()) {
15877 if (cond.Is(al)) {
15878 EmitA32(0xf2000340U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
15879 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
Pierre Langlois120cafb2016-08-30 10:32:30 +010015880 rd.Encode(22, 12) | rn.Encode(5, 0) | rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015881 return;
15882 }
15883 }
15884 // VCLT{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A2
15885 if (dt.Is(F32)) {
15886 if (cond.Is(al)) {
Pierre Langlois120cafb2016-08-30 10:32:30 +010015887 EmitA32(0xf3200e40U | rd.Encode(22, 12) | rn.Encode(5, 0) |
15888 rm.Encode(7, 16));
Alexandre Ramesd3832962016-07-04 15:03:43 +010015889 return;
15890 }
15891 }
15892 }
15893 Delegate(kVclt, &Assembler::vclt, cond, dt, rd, rn, rm);
15894}
15895
15896void Assembler::vclz(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015897 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015898 CheckIT(cond);
15899 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015900 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015901 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
15902 if (encoded_dt.IsValid()) {
15903 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15904 EmitT32_32(0xffb00480U | (encoded_dt.GetEncodingValue() << 18) |
15905 rd.Encode(22, 12) | rm.Encode(5, 0));
15906 AdvanceIT();
15907 return;
15908 }
15909 }
15910 } else {
15911 // VCLZ{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
15912 if (encoded_dt.IsValid()) {
15913 if (cond.Is(al)) {
15914 EmitA32(0xf3b00480U | (encoded_dt.GetEncodingValue() << 18) |
15915 rd.Encode(22, 12) | rm.Encode(5, 0));
15916 return;
15917 }
15918 }
15919 }
15920 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15921}
15922
15923void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015924 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015925 CheckIT(cond);
15926 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010015927 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010015928 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
15929 if (encoded_dt.IsValid()) {
15930 if (cond.Is(al) || AllowStronglyDiscouraged()) {
15931 EmitT32_32(0xffb004c0U | (encoded_dt.GetEncodingValue() << 18) |
15932 rd.Encode(22, 12) | rm.Encode(5, 0));
15933 AdvanceIT();
15934 return;
15935 }
15936 }
15937 } else {
15938 // VCLZ{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
15939 if (encoded_dt.IsValid()) {
15940 if (cond.Is(al)) {
15941 EmitA32(0xf3b004c0U | (encoded_dt.GetEncodingValue() << 18) |
15942 rd.Encode(22, 12) | rm.Encode(5, 0));
15943 return;
15944 }
15945 }
15946 }
15947 Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
15948}
15949
Vincent Belliard07f9e742017-04-21 13:10:07 -070015950void Assembler::vcmp(Condition cond,
15951 DataType dt,
15952 SRegister rd,
15953 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015954 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015955 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070015956 if (operand.IsRegister()) {
15957 SRegister rm = operand.GetRegister();
15958 if (IsUsingT32()) {
15959 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
15960 if (dt.Is(F32)) {
15961 EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
15962 AdvanceIT();
15963 return;
15964 }
15965 } else {
15966 // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
15967 if (dt.Is(F32) && cond.IsNotNever()) {
15968 EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
15969 rm.Encode(5, 0));
15970 return;
15971 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010015972 }
15973 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070015974 if (operand.IsImmediate()) {
15975 if (IsUsingT32()) {
15976 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
15977 if (dt.Is(F32) && (operand.IsFloatZero())) {
15978 EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
15979 AdvanceIT();
15980 return;
15981 }
15982 } else {
15983 // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
15984 if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
15985 EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
15986 return;
15987 }
15988 }
15989 }
15990 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010015991}
15992
Vincent Belliard07f9e742017-04-21 13:10:07 -070015993void Assembler::vcmp(Condition cond,
15994 DataType dt,
15995 DRegister rd,
15996 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070015997 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010015998 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070015999 if (operand.IsRegister()) {
16000 DRegister rm = operand.GetRegister();
16001 if (IsUsingT32()) {
16002 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16003 if (dt.Is(F64)) {
16004 EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16005 AdvanceIT();
16006 return;
16007 }
16008 } else {
16009 // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16010 if (dt.Is(F64) && cond.IsNotNever()) {
16011 EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16012 rm.Encode(5, 0));
16013 return;
16014 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016015 }
16016 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016017 if (operand.IsImmediate()) {
16018 if (IsUsingT32()) {
16019 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16020 if (dt.Is(F64) && (operand.IsFloatZero())) {
16021 EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
16022 AdvanceIT();
16023 return;
16024 }
16025 } else {
16026 // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16027 if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16028 EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16029 return;
16030 }
16031 }
16032 }
16033 Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016034}
16035
Vincent Belliard07f9e742017-04-21 13:10:07 -070016036void Assembler::vcmpe(Condition cond,
16037 DataType dt,
16038 SRegister rd,
16039 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016040 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016041 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016042 if (operand.IsRegister()) {
16043 SRegister rm = operand.GetRegister();
16044 if (IsUsingT32()) {
16045 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
16046 if (dt.Is(F32)) {
16047 EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16048 AdvanceIT();
16049 return;
16050 }
16051 } else {
16052 // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
16053 if (dt.Is(F32) && cond.IsNotNever()) {
16054 EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16055 rm.Encode(5, 0));
16056 return;
16057 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016058 }
16059 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016060 if (operand.IsImmediate()) {
16061 if (IsUsingT32()) {
16062 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
16063 if (dt.Is(F32) && (operand.IsFloatZero())) {
16064 EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
16065 AdvanceIT();
16066 return;
16067 }
16068 } else {
16069 // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
16070 if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16071 EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16072 return;
16073 }
16074 }
16075 }
16076 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016077}
16078
Vincent Belliard07f9e742017-04-21 13:10:07 -070016079void Assembler::vcmpe(Condition cond,
16080 DataType dt,
16081 DRegister rd,
16082 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016083 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016084 CheckIT(cond);
Vincent Belliard07f9e742017-04-21 13:10:07 -070016085 if (operand.IsRegister()) {
16086 DRegister rm = operand.GetRegister();
16087 if (IsUsingT32()) {
16088 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
16089 if (dt.Is(F64)) {
16090 EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16091 AdvanceIT();
16092 return;
16093 }
16094 } else {
16095 // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
16096 if (dt.Is(F64) && cond.IsNotNever()) {
16097 EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16098 rm.Encode(5, 0));
16099 return;
16100 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016101 }
16102 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016103 if (operand.IsImmediate()) {
16104 if (IsUsingT32()) {
16105 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
16106 if (dt.Is(F64) && (operand.IsFloatZero())) {
16107 EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
16108 AdvanceIT();
16109 return;
16110 }
16111 } else {
16112 // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
16113 if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
16114 EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
16115 return;
16116 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010016117 }
16118 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070016119 Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
Alexandre Ramesd3832962016-07-04 15:03:43 +010016120}
16121
16122void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016123 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016124 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016125 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016126 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; T1
16127 if (dt.Is(Untyped8)) {
16128 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16129 EmitT32_32(0xffb00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16130 AdvanceIT();
16131 return;
16132 }
16133 }
16134 } else {
16135 // VCNT{<c>}{<q>}.8 <Dd>, <Dm> ; A1
16136 if (dt.Is(Untyped8)) {
16137 if (cond.Is(al)) {
16138 EmitA32(0xf3b00500U | rd.Encode(22, 12) | rm.Encode(5, 0));
16139 return;
16140 }
16141 }
16142 }
16143 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16144}
16145
16146void Assembler::vcnt(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016147 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016148 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016149 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016150 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; T1
16151 if (dt.Is(Untyped8)) {
16152 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16153 EmitT32_32(0xffb00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16154 AdvanceIT();
16155 return;
16156 }
16157 }
16158 } else {
16159 // VCNT{<c>}{<q>}.8 <Qd>, <Qm> ; A1
16160 if (dt.Is(Untyped8)) {
16161 if (cond.Is(al)) {
16162 EmitA32(0xf3b00540U | rd.Encode(22, 12) | rm.Encode(5, 0));
16163 return;
16164 }
16165 }
16166 }
16167 Delegate(kVcnt, &Assembler::vcnt, cond, dt, rd, rm);
16168}
16169
16170void Assembler::vcvt(
16171 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016172 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016173 CheckIT(cond);
16174 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016175 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016176 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; T1
16177 if (dt1.Is(F64) && dt2.Is(F32)) {
16178 EmitT32_32(0xeeb70ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16179 AdvanceIT();
16180 return;
16181 }
16182 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; T1
16183 if (dt1.Is(F64) && encoded_dt.IsValid()) {
16184 EmitT32_32(0xeeb80b40U | (encoded_dt.GetEncodingValue() << 7) |
16185 rd.Encode(22, 12) | rm.Encode(5, 0));
16186 AdvanceIT();
16187 return;
16188 }
16189 } else {
16190 // VCVT{<c>}{<q>}.F64.F32 <Dd>, <Sm> ; A1
16191 if (dt1.Is(F64) && dt2.Is(F32) && cond.IsNotNever()) {
16192 EmitA32(0x0eb70ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16193 rm.Encode(5, 0));
16194 return;
16195 }
16196 // VCVT{<c>}{<q>}.F64.<dt> <Dd>, <Sm> ; A1
16197 if (dt1.Is(F64) && encoded_dt.IsValid() && cond.IsNotNever()) {
16198 EmitA32(0x0eb80b40U | (cond.GetCondition() << 28) |
16199 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16200 rm.Encode(5, 0));
16201 return;
16202 }
16203 }
16204 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16205}
16206
16207void Assembler::vcvt(
16208 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016209 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016210 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016211 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016212 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; T1
16213 if (dt1.Is(F32) && dt2.Is(F64)) {
16214 EmitT32_32(0xeeb70bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16215 AdvanceIT();
16216 return;
16217 }
16218 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
16219 if (dt1.Is(U32) && dt2.Is(F64)) {
16220 EmitT32_32(0xeebc0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16221 AdvanceIT();
16222 return;
16223 }
16224 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
16225 if (dt1.Is(S32) && dt2.Is(F64)) {
16226 EmitT32_32(0xeebd0bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16227 AdvanceIT();
16228 return;
16229 }
16230 } else {
16231 // VCVT{<c>}{<q>}.F32.F64 <Sd>, <Dm> ; A1
16232 if (dt1.Is(F32) && dt2.Is(F64) && cond.IsNotNever()) {
16233 EmitA32(0x0eb70bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16234 rm.Encode(5, 0));
16235 return;
16236 }
16237 // VCVT{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
16238 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
16239 EmitA32(0x0ebc0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16240 rm.Encode(5, 0));
16241 return;
16242 }
16243 // VCVT{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
16244 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
16245 EmitA32(0x0ebd0bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16246 rm.Encode(5, 0));
16247 return;
16248 }
16249 }
16250 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16251}
16252
16253void Assembler::vcvt(Condition cond,
16254 DataType dt1,
16255 DataType dt2,
16256 DRegister rd,
16257 DRegister rm,
16258 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016259 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016260 CheckIT(cond);
16261 Dt_op_U_1 encoded_dt(dt1, dt2);
16262 Dt_U_sx_1 encoded_dt_2(dt2);
16263 Dt_U_sx_1 encoded_dt_3(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016264 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016265 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; T1
16266 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16267 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16268 uint32_t fbits_ = 64 - fbits;
16269 EmitT32_32(0xef800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16270 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16271 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16272 AdvanceIT();
16273 return;
16274 }
16275 }
16276 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; T1
16277 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16278 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16279 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16280 unsigned offset = 32;
16281 if (dt2.Is(S16) || dt2.Is(U16)) {
16282 offset = 16;
16283 }
16284 uint32_t fbits_ = offset - fbits;
16285 EmitT32_32(0xeeba0b40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16286 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16287 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16288 ((fbits_ & 0x1e) >> 1));
16289 AdvanceIT();
16290 return;
16291 }
16292 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; T1
16293 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16294 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16295 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16296 unsigned offset = 32;
16297 if (dt1.Is(S16) || dt1.Is(U16)) {
16298 offset = 16;
16299 }
16300 uint32_t fbits_ = offset - fbits;
16301 EmitT32_32(0xeebe0b40U | ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16302 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16303 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16304 ((fbits_ & 0x1e) >> 1));
16305 AdvanceIT();
16306 return;
16307 }
16308 } else {
16309 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm>, #<fbits> ; A1
16310 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16311 if (cond.Is(al)) {
16312 uint32_t fbits_ = 64 - fbits;
16313 EmitA32(0xf2800e10U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16314 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16315 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16316 return;
16317 }
16318 }
16319 // VCVT{<c>}{<q>}.F64.<dt> <Ddm>, <Ddm>, #<fbits> ; A1
16320 if (dt1.Is(F64) && encoded_dt_2.IsValid() && rd.Is(rm) &&
16321 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16322 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16323 cond.IsNotNever()) {
16324 unsigned offset = 32;
16325 if (dt2.Is(S16) || dt2.Is(U16)) {
16326 offset = 16;
16327 }
16328 uint32_t fbits_ = offset - fbits;
16329 EmitA32(0x0eba0b40U | (cond.GetCondition() << 28) |
16330 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16331 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16332 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16333 ((fbits_ & 0x1e) >> 1));
16334 return;
16335 }
16336 // VCVT{<c>}{<q>}.<dt>.F64 <Ddm>, <Ddm>, #<fbits> ; A1
16337 if (encoded_dt_3.IsValid() && dt2.Is(F64) && rd.Is(rm) &&
16338 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16339 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16340 cond.IsNotNever()) {
16341 unsigned offset = 32;
16342 if (dt1.Is(S16) || dt1.Is(U16)) {
16343 offset = 16;
16344 }
16345 uint32_t fbits_ = offset - fbits;
16346 EmitA32(0x0ebe0b40U | (cond.GetCondition() << 28) |
16347 ((encoded_dt_3.GetEncodingValue() & 0x1) << 7) |
16348 ((encoded_dt_3.GetEncodingValue() & 0x2) << 15) |
16349 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16350 ((fbits_ & 0x1e) >> 1));
16351 return;
16352 }
16353 }
16354 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16355}
16356
16357void Assembler::vcvt(Condition cond,
16358 DataType dt1,
16359 DataType dt2,
16360 QRegister rd,
16361 QRegister rm,
16362 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016363 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016364 CheckIT(cond);
16365 Dt_op_U_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016366 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016367 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; T1
16368 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16369 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16370 uint32_t fbits_ = 64 - fbits;
16371 EmitT32_32(0xef800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 28) |
16372 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16373 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16374 AdvanceIT();
16375 return;
16376 }
16377 }
16378 } else {
16379 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm>, #<fbits> ; A1
16380 if (encoded_dt.IsValid() && (fbits >= 1) && (fbits <= 32)) {
16381 if (cond.Is(al)) {
16382 uint32_t fbits_ = 64 - fbits;
16383 EmitA32(0xf2800e50U | ((encoded_dt.GetEncodingValue() & 0x1) << 24) |
16384 ((encoded_dt.GetEncodingValue() & 0x2) << 7) |
16385 rd.Encode(22, 12) | rm.Encode(5, 0) | (fbits_ << 16));
16386 return;
16387 }
16388 }
16389 }
16390 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16391}
16392
16393void Assembler::vcvt(Condition cond,
16394 DataType dt1,
16395 DataType dt2,
16396 SRegister rd,
16397 SRegister rm,
16398 int32_t fbits) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016399 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016400 CheckIT(cond);
16401 Dt_U_sx_1 encoded_dt(dt2);
16402 Dt_U_sx_1 encoded_dt_2(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016403 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016404 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; T1
16405 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16406 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16407 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16408 unsigned offset = 32;
16409 if (dt2.Is(S16) || dt2.Is(U16)) {
16410 offset = 16;
16411 }
16412 uint32_t fbits_ = offset - fbits;
16413 EmitT32_32(0xeeba0a40U | ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16414 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16415 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16416 ((fbits_ & 0x1e) >> 1));
16417 AdvanceIT();
16418 return;
16419 }
16420 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; T1
16421 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16422 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16423 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32)))) {
16424 unsigned offset = 32;
16425 if (dt1.Is(S16) || dt1.Is(U16)) {
16426 offset = 16;
16427 }
16428 uint32_t fbits_ = offset - fbits;
16429 EmitT32_32(0xeebe0a40U | ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16430 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16431 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16432 ((fbits_ & 0x1e) >> 1));
16433 AdvanceIT();
16434 return;
16435 }
16436 } else {
16437 // VCVT{<c>}{<q>}.F32.<dt> <Sdm>, <Sdm>, #<fbits> ; A1
16438 if (dt1.Is(F32) && encoded_dt.IsValid() && rd.Is(rm) &&
16439 (((dt2.Is(S16) || dt2.Is(U16)) && (fbits <= 16)) ||
16440 ((dt2.Is(S32) || dt2.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16441 cond.IsNotNever()) {
16442 unsigned offset = 32;
16443 if (dt2.Is(S16) || dt2.Is(U16)) {
16444 offset = 16;
16445 }
16446 uint32_t fbits_ = offset - fbits;
16447 EmitA32(0x0eba0a40U | (cond.GetCondition() << 28) |
16448 ((encoded_dt.GetEncodingValue() & 0x1) << 7) |
16449 ((encoded_dt.GetEncodingValue() & 0x2) << 15) |
16450 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16451 ((fbits_ & 0x1e) >> 1));
16452 return;
16453 }
16454 // VCVT{<c>}{<q>}.<dt>.F32 <Sdm>, <Sdm>, #<fbits> ; A1
16455 if (encoded_dt_2.IsValid() && dt2.Is(F32) && rd.Is(rm) &&
16456 (((dt1.Is(S16) || dt1.Is(U16)) && (fbits <= 16)) ||
16457 ((dt1.Is(S32) || dt1.Is(U32)) && (fbits >= 1) && (fbits <= 32))) &&
16458 cond.IsNotNever()) {
16459 unsigned offset = 32;
16460 if (dt1.Is(S16) || dt1.Is(U16)) {
16461 offset = 16;
16462 }
16463 uint32_t fbits_ = offset - fbits;
16464 EmitA32(0x0ebe0a40U | (cond.GetCondition() << 28) |
16465 ((encoded_dt_2.GetEncodingValue() & 0x1) << 7) |
16466 ((encoded_dt_2.GetEncodingValue() & 0x2) << 15) |
16467 rd.Encode(22, 12) | ((fbits_ & 0x1) << 5) |
16468 ((fbits_ & 0x1e) >> 1));
16469 return;
16470 }
16471 }
16472 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm, fbits);
16473}
16474
16475void Assembler::vcvt(
16476 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016477 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016478 CheckIT(cond);
16479 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016480 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016481 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; T1
16482 if (encoded_dt.IsValid()) {
16483 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16484 EmitT32_32(0xffbb0600U | (encoded_dt.GetEncodingValue() << 7) |
16485 rd.Encode(22, 12) | rm.Encode(5, 0));
16486 AdvanceIT();
16487 return;
16488 }
16489 }
16490 } else {
16491 // VCVT{<c>}{<q>}.<dt>.<dt> <Dd>, <Dm> ; A1
16492 if (encoded_dt.IsValid()) {
16493 if (cond.Is(al)) {
16494 EmitA32(0xf3bb0600U | (encoded_dt.GetEncodingValue() << 7) |
16495 rd.Encode(22, 12) | rm.Encode(5, 0));
16496 return;
16497 }
16498 }
16499 }
16500 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16501}
16502
16503void Assembler::vcvt(
16504 Condition cond, DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016505 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016506 CheckIT(cond);
16507 Dt_op_1 encoded_dt(dt1, dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016508 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016509 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; T1
16510 if (encoded_dt.IsValid()) {
16511 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16512 EmitT32_32(0xffbb0640U | (encoded_dt.GetEncodingValue() << 7) |
16513 rd.Encode(22, 12) | rm.Encode(5, 0));
16514 AdvanceIT();
16515 return;
16516 }
16517 }
16518 } else {
16519 // VCVT{<c>}{<q>}.<dt>.<dt> <Qd>, <Qm> ; A1
16520 if (encoded_dt.IsValid()) {
16521 if (cond.Is(al)) {
16522 EmitA32(0xf3bb0640U | (encoded_dt.GetEncodingValue() << 7) |
16523 rd.Encode(22, 12) | rm.Encode(5, 0));
16524 return;
16525 }
16526 }
16527 }
16528 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16529}
16530
16531void Assembler::vcvt(
16532 Condition cond, DataType dt1, DataType dt2, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016534 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016535 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016536 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; T1
16537 if (dt1.Is(F16) && dt2.Is(F32)) {
16538 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16539 EmitT32_32(0xffb60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16540 AdvanceIT();
16541 return;
16542 }
16543 }
16544 } else {
16545 // VCVT{<c>}{<q>}.F16.F32 <Dd>, <Qm> ; A1
16546 if (dt1.Is(F16) && dt2.Is(F32)) {
16547 if (cond.Is(al)) {
16548 EmitA32(0xf3b60600U | rd.Encode(22, 12) | rm.Encode(5, 0));
16549 return;
16550 }
16551 }
16552 }
16553 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16554}
16555
16556void Assembler::vcvt(
16557 Condition cond, DataType dt1, DataType dt2, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016558 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016559 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016560 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016561 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; T1
16562 if (dt1.Is(F32) && dt2.Is(F16)) {
16563 if (cond.Is(al) || AllowStronglyDiscouraged()) {
16564 EmitT32_32(0xffb60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16565 AdvanceIT();
16566 return;
16567 }
16568 }
16569 } else {
16570 // VCVT{<c>}{<q>}.F32.F16 <Qd>, <Dm> ; A1
16571 if (dt1.Is(F32) && dt2.Is(F16)) {
16572 if (cond.Is(al)) {
16573 EmitA32(0xf3b60700U | rd.Encode(22, 12) | rm.Encode(5, 0));
16574 return;
16575 }
16576 }
16577 }
16578 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16579}
16580
16581void Assembler::vcvt(
16582 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016583 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016584 CheckIT(cond);
16585 Dt_op_2 encoded_dt(dt2);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016586 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016587 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
16588 if (dt1.Is(U32) && dt2.Is(F32)) {
16589 EmitT32_32(0xeebc0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16590 AdvanceIT();
16591 return;
16592 }
16593 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
16594 if (dt1.Is(S32) && dt2.Is(F32)) {
16595 EmitT32_32(0xeebd0ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
16596 AdvanceIT();
16597 return;
16598 }
16599 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; T1
16600 if (dt1.Is(F32) && encoded_dt.IsValid()) {
16601 EmitT32_32(0xeeb80a40U | (encoded_dt.GetEncodingValue() << 7) |
16602 rd.Encode(22, 12) | rm.Encode(5, 0));
16603 AdvanceIT();
16604 return;
16605 }
16606 } else {
16607 // VCVT{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
16608 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
16609 EmitA32(0x0ebc0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16610 rm.Encode(5, 0));
16611 return;
16612 }
16613 // VCVT{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
16614 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
16615 EmitA32(0x0ebd0ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16616 rm.Encode(5, 0));
16617 return;
16618 }
16619 // VCVT{<c>}{<q>}.F32.<dt> <Sd>, <Sm> ; A1
16620 if (dt1.Is(F32) && encoded_dt.IsValid() && cond.IsNotNever()) {
16621 EmitA32(0x0eb80a40U | (cond.GetCondition() << 28) |
16622 (encoded_dt.GetEncodingValue() << 7) | rd.Encode(22, 12) |
16623 rm.Encode(5, 0));
16624 return;
16625 }
16626 }
16627 Delegate(kVcvt, &Assembler::vcvt, cond, dt1, dt2, rd, rm);
16628}
16629
16630void Assembler::vcvta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016631 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016632 CheckIT(al);
16633 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016634 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016635 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16636 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16637 EmitT32_32(0xffbb0000U | (encoded_dt.GetEncodingValue() << 7) |
16638 rd.Encode(22, 12) | rm.Encode(5, 0));
16639 AdvanceIT();
16640 return;
16641 }
16642 } else {
16643 // VCVTA{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16644 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16645 EmitA32(0xf3bb0000U | (encoded_dt.GetEncodingValue() << 7) |
16646 rd.Encode(22, 12) | rm.Encode(5, 0));
16647 return;
16648 }
16649 }
16650 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16651}
16652
16653void Assembler::vcvta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016654 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016655 CheckIT(al);
16656 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016657 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016658 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16659 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16660 EmitT32_32(0xffbb0040U | (encoded_dt.GetEncodingValue() << 7) |
16661 rd.Encode(22, 12) | rm.Encode(5, 0));
16662 AdvanceIT();
16663 return;
16664 }
16665 } else {
16666 // VCVTA{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16667 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16668 EmitA32(0xf3bb0040U | (encoded_dt.GetEncodingValue() << 7) |
16669 rd.Encode(22, 12) | rm.Encode(5, 0));
16670 return;
16671 }
16672 }
16673 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16674}
16675
16676void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016677 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016678 CheckIT(al);
16679 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016680 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016681 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16682 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16683 EmitT32_32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16684 rd.Encode(22, 12) | rm.Encode(5, 0));
16685 AdvanceIT();
16686 return;
16687 }
16688 } else {
16689 // VCVTA{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16690 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16691 EmitA32(0xfebc0a40U | (encoded_dt.GetEncodingValue() << 7) |
16692 rd.Encode(22, 12) | rm.Encode(5, 0));
16693 return;
16694 }
16695 }
16696 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16697}
16698
16699void Assembler::vcvta(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016700 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016701 CheckIT(al);
16702 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016703 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016704 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16705 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16706 EmitT32_32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16707 rd.Encode(22, 12) | rm.Encode(5, 0));
16708 AdvanceIT();
16709 return;
16710 }
16711 } else {
16712 // VCVTA{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16713 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16714 EmitA32(0xfebc0b40U | (encoded_dt.GetEncodingValue() << 7) |
16715 rd.Encode(22, 12) | rm.Encode(5, 0));
16716 return;
16717 }
16718 }
16719 Delegate(kVcvta, &Assembler::vcvta, dt1, dt2, rd, rm);
16720}
16721
16722void Assembler::vcvtb(
16723 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016724 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016725 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016726 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016727 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
16728 if (dt1.Is(F32) && dt2.Is(F16)) {
16729 EmitT32_32(0xeeb20a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16730 AdvanceIT();
16731 return;
16732 }
16733 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
16734 if (dt1.Is(F16) && dt2.Is(F32)) {
16735 EmitT32_32(0xeeb30a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16736 AdvanceIT();
16737 return;
16738 }
16739 } else {
16740 // VCVTB{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
16741 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
16742 EmitA32(0x0eb20a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16743 rm.Encode(5, 0));
16744 return;
16745 }
16746 // VCVTB{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
16747 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
16748 EmitA32(0x0eb30a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16749 rm.Encode(5, 0));
16750 return;
16751 }
16752 }
16753 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16754}
16755
16756void Assembler::vcvtb(
16757 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016758 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016759 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016760 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016761 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
16762 if (dt1.Is(F64) && dt2.Is(F16)) {
16763 EmitT32_32(0xeeb20b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16764 AdvanceIT();
16765 return;
16766 }
16767 } else {
16768 // VCVTB{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
16769 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
16770 EmitA32(0x0eb20b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16771 rm.Encode(5, 0));
16772 return;
16773 }
16774 }
16775 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16776}
16777
16778void Assembler::vcvtb(
16779 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016780 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016781 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016783 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
16784 if (dt1.Is(F16) && dt2.Is(F64)) {
16785 EmitT32_32(0xeeb30b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
16786 AdvanceIT();
16787 return;
16788 }
16789 } else {
16790 // VCVTB{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
16791 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
16792 EmitA32(0x0eb30b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
16793 rm.Encode(5, 0));
16794 return;
16795 }
16796 }
16797 Delegate(kVcvtb, &Assembler::vcvtb, cond, dt1, dt2, rd, rm);
16798}
16799
16800void Assembler::vcvtm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016801 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016802 CheckIT(al);
16803 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016804 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016805 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16806 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16807 EmitT32_32(0xffbb0300U | (encoded_dt.GetEncodingValue() << 7) |
16808 rd.Encode(22, 12) | rm.Encode(5, 0));
16809 AdvanceIT();
16810 return;
16811 }
16812 } else {
16813 // VCVTM{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16814 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16815 EmitA32(0xf3bb0300U | (encoded_dt.GetEncodingValue() << 7) |
16816 rd.Encode(22, 12) | rm.Encode(5, 0));
16817 return;
16818 }
16819 }
16820 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16821}
16822
16823void Assembler::vcvtm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016824 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016825 CheckIT(al);
16826 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016827 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016828 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16829 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16830 EmitT32_32(0xffbb0340U | (encoded_dt.GetEncodingValue() << 7) |
16831 rd.Encode(22, 12) | rm.Encode(5, 0));
16832 AdvanceIT();
16833 return;
16834 }
16835 } else {
16836 // VCVTM{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16837 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16838 EmitA32(0xf3bb0340U | (encoded_dt.GetEncodingValue() << 7) |
16839 rd.Encode(22, 12) | rm.Encode(5, 0));
16840 return;
16841 }
16842 }
16843 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16844}
16845
16846void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016847 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016848 CheckIT(al);
16849 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016850 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016851 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16852 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16853 EmitT32_32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16854 rd.Encode(22, 12) | rm.Encode(5, 0));
16855 AdvanceIT();
16856 return;
16857 }
16858 } else {
16859 // VCVTM{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16860 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16861 EmitA32(0xfebf0a40U | (encoded_dt.GetEncodingValue() << 7) |
16862 rd.Encode(22, 12) | rm.Encode(5, 0));
16863 return;
16864 }
16865 }
16866 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16867}
16868
16869void Assembler::vcvtm(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016870 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016871 CheckIT(al);
16872 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016873 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016874 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16875 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16876 EmitT32_32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16877 rd.Encode(22, 12) | rm.Encode(5, 0));
16878 AdvanceIT();
16879 return;
16880 }
16881 } else {
16882 // VCVTM{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16883 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16884 EmitA32(0xfebf0b40U | (encoded_dt.GetEncodingValue() << 7) |
16885 rd.Encode(22, 12) | rm.Encode(5, 0));
16886 return;
16887 }
16888 }
16889 Delegate(kVcvtm, &Assembler::vcvtm, dt1, dt2, rd, rm);
16890}
16891
16892void Assembler::vcvtn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016893 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016894 CheckIT(al);
16895 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016896 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016897 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16898 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16899 EmitT32_32(0xffbb0100U | (encoded_dt.GetEncodingValue() << 7) |
16900 rd.Encode(22, 12) | rm.Encode(5, 0));
16901 AdvanceIT();
16902 return;
16903 }
16904 } else {
16905 // VCVTN{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16906 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16907 EmitA32(0xf3bb0100U | (encoded_dt.GetEncodingValue() << 7) |
16908 rd.Encode(22, 12) | rm.Encode(5, 0));
16909 return;
16910 }
16911 }
16912 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16913}
16914
16915void Assembler::vcvtn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016916 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016917 CheckIT(al);
16918 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016919 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016920 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
16921 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16922 EmitT32_32(0xffbb0140U | (encoded_dt.GetEncodingValue() << 7) |
16923 rd.Encode(22, 12) | rm.Encode(5, 0));
16924 AdvanceIT();
16925 return;
16926 }
16927 } else {
16928 // VCVTN{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
16929 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16930 EmitA32(0xf3bb0140U | (encoded_dt.GetEncodingValue() << 7) |
16931 rd.Encode(22, 12) | rm.Encode(5, 0));
16932 return;
16933 }
16934 }
16935 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16936}
16937
16938void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016939 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016940 CheckIT(al);
16941 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016942 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016943 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
16944 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16945 EmitT32_32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16946 rd.Encode(22, 12) | rm.Encode(5, 0));
16947 AdvanceIT();
16948 return;
16949 }
16950 } else {
16951 // VCVTN{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
16952 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16953 EmitA32(0xfebd0a40U | (encoded_dt.GetEncodingValue() << 7) |
16954 rd.Encode(22, 12) | rm.Encode(5, 0));
16955 return;
16956 }
16957 }
16958 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16959}
16960
16961void Assembler::vcvtn(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016962 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016963 CheckIT(al);
16964 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016965 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016966 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
16967 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16968 EmitT32_32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
16969 rd.Encode(22, 12) | rm.Encode(5, 0));
16970 AdvanceIT();
16971 return;
16972 }
16973 } else {
16974 // VCVTN{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
16975 if (encoded_dt.IsValid() && dt2.Is(F64)) {
16976 EmitA32(0xfebd0b40U | (encoded_dt.GetEncodingValue() << 7) |
16977 rd.Encode(22, 12) | rm.Encode(5, 0));
16978 return;
16979 }
16980 }
16981 Delegate(kVcvtn, &Assembler::vcvtn, dt1, dt2, rd, rm);
16982}
16983
16984void Assembler::vcvtp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070016985 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010016986 CheckIT(al);
16987 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010016988 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010016989 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; T1
16990 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16991 EmitT32_32(0xffbb0200U | (encoded_dt.GetEncodingValue() << 7) |
16992 rd.Encode(22, 12) | rm.Encode(5, 0));
16993 AdvanceIT();
16994 return;
16995 }
16996 } else {
16997 // VCVTP{<q>}.<dt>.F32 <Dd>, <Dm> ; A1
16998 if (encoded_dt.IsValid() && dt2.Is(F32)) {
16999 EmitA32(0xf3bb0200U | (encoded_dt.GetEncodingValue() << 7) |
17000 rd.Encode(22, 12) | rm.Encode(5, 0));
17001 return;
17002 }
17003 }
17004 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17005}
17006
17007void Assembler::vcvtp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017008 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017009 CheckIT(al);
17010 Dt_op_3 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017011 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017012 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; T1
17013 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17014 EmitT32_32(0xffbb0240U | (encoded_dt.GetEncodingValue() << 7) |
17015 rd.Encode(22, 12) | rm.Encode(5, 0));
17016 AdvanceIT();
17017 return;
17018 }
17019 } else {
17020 // VCVTP{<q>}.<dt>.F32 <Qd>, <Qm> ; A1
17021 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17022 EmitA32(0xf3bb0240U | (encoded_dt.GetEncodingValue() << 7) |
17023 rd.Encode(22, 12) | rm.Encode(5, 0));
17024 return;
17025 }
17026 }
17027 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17028}
17029
17030void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017031 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017032 CheckIT(al);
17033 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017034 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017035 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; T1
17036 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17037 EmitT32_32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17038 rd.Encode(22, 12) | rm.Encode(5, 0));
17039 AdvanceIT();
17040 return;
17041 }
17042 } else {
17043 // VCVTP{<q>}.<dt>.F32 <Sd>, <Sm> ; A1
17044 if (encoded_dt.IsValid() && dt2.Is(F32)) {
17045 EmitA32(0xfebe0a40U | (encoded_dt.GetEncodingValue() << 7) |
17046 rd.Encode(22, 12) | rm.Encode(5, 0));
17047 return;
17048 }
17049 }
17050 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17051}
17052
17053void Assembler::vcvtp(DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017054 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017055 CheckIT(al);
17056 Dt_op_2 encoded_dt(dt1);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017057 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017058 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; T1
17059 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17060 EmitT32_32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17061 rd.Encode(22, 12) | rm.Encode(5, 0));
17062 AdvanceIT();
17063 return;
17064 }
17065 } else {
17066 // VCVTP{<q>}.<dt>.F64 <Sd>, <Dm> ; A1
17067 if (encoded_dt.IsValid() && dt2.Is(F64)) {
17068 EmitA32(0xfebe0b40U | (encoded_dt.GetEncodingValue() << 7) |
17069 rd.Encode(22, 12) | rm.Encode(5, 0));
17070 return;
17071 }
17072 }
17073 Delegate(kVcvtp, &Assembler::vcvtp, dt1, dt2, rd, rm);
17074}
17075
17076void Assembler::vcvtr(
17077 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017078 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017079 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017080 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017081 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; T1
17082 if (dt1.Is(U32) && dt2.Is(F32)) {
17083 EmitT32_32(0xeebc0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17084 AdvanceIT();
17085 return;
17086 }
17087 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; T1
17088 if (dt1.Is(S32) && dt2.Is(F32)) {
17089 EmitT32_32(0xeebd0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17090 AdvanceIT();
17091 return;
17092 }
17093 } else {
17094 // VCVTR{<c>}{<q>}.U32.F32 <Sd>, <Sm> ; A1
17095 if (dt1.Is(U32) && dt2.Is(F32) && cond.IsNotNever()) {
17096 EmitA32(0x0ebc0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17097 rm.Encode(5, 0));
17098 return;
17099 }
17100 // VCVTR{<c>}{<q>}.S32.F32 <Sd>, <Sm> ; A1
17101 if (dt1.Is(S32) && dt2.Is(F32) && cond.IsNotNever()) {
17102 EmitA32(0x0ebd0a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17103 rm.Encode(5, 0));
17104 return;
17105 }
17106 }
17107 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17108}
17109
17110void Assembler::vcvtr(
17111 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017112 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017113 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017114 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017115 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; T1
17116 if (dt1.Is(U32) && dt2.Is(F64)) {
17117 EmitT32_32(0xeebc0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17118 AdvanceIT();
17119 return;
17120 }
17121 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; T1
17122 if (dt1.Is(S32) && dt2.Is(F64)) {
17123 EmitT32_32(0xeebd0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
17124 AdvanceIT();
17125 return;
17126 }
17127 } else {
17128 // VCVTR{<c>}{<q>}.U32.F64 <Sd>, <Dm> ; A1
17129 if (dt1.Is(U32) && dt2.Is(F64) && cond.IsNotNever()) {
17130 EmitA32(0x0ebc0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17131 rm.Encode(5, 0));
17132 return;
17133 }
17134 // VCVTR{<c>}{<q>}.S32.F64 <Sd>, <Dm> ; A1
17135 if (dt1.Is(S32) && dt2.Is(F64) && cond.IsNotNever()) {
17136 EmitA32(0x0ebd0b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17137 rm.Encode(5, 0));
17138 return;
17139 }
17140 }
17141 Delegate(kVcvtr, &Assembler::vcvtr, cond, dt1, dt2, rd, rm);
17142}
17143
17144void Assembler::vcvtt(
17145 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017146 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017147 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017148 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017149 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; T1
17150 if (dt1.Is(F32) && dt2.Is(F16)) {
17151 EmitT32_32(0xeeb20ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17152 AdvanceIT();
17153 return;
17154 }
17155 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; T1
17156 if (dt1.Is(F16) && dt2.Is(F32)) {
17157 EmitT32_32(0xeeb30ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17158 AdvanceIT();
17159 return;
17160 }
17161 } else {
17162 // VCVTT{<c>}{<q>}.F32.F16 <Sd>, <Sm> ; A1
17163 if (dt1.Is(F32) && dt2.Is(F16) && cond.IsNotNever()) {
17164 EmitA32(0x0eb20ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17165 rm.Encode(5, 0));
17166 return;
17167 }
17168 // VCVTT{<c>}{<q>}.F16.F32 <Sd>, <Sm> ; A1
17169 if (dt1.Is(F16) && dt2.Is(F32) && cond.IsNotNever()) {
17170 EmitA32(0x0eb30ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17171 rm.Encode(5, 0));
17172 return;
17173 }
17174 }
17175 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17176}
17177
17178void Assembler::vcvtt(
17179 Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017180 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017181 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017182 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017183 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; T1
17184 if (dt1.Is(F64) && dt2.Is(F16)) {
17185 EmitT32_32(0xeeb20bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17186 AdvanceIT();
17187 return;
17188 }
17189 } else {
17190 // VCVTT{<c>}{<q>}.F64.F16 <Dd>, <Sm> ; A1
17191 if (dt1.Is(F64) && dt2.Is(F16) && cond.IsNotNever()) {
17192 EmitA32(0x0eb20bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17193 rm.Encode(5, 0));
17194 return;
17195 }
17196 }
17197 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17198}
17199
17200void Assembler::vcvtt(
17201 Condition cond, DataType dt1, DataType dt2, SRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017202 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017203 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017204 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017205 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; T1
17206 if (dt1.Is(F16) && dt2.Is(F64)) {
17207 EmitT32_32(0xeeb30bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
17208 AdvanceIT();
17209 return;
17210 }
17211 } else {
17212 // VCVTT{<c>}{<q>}.F16.F64 <Sd>, <Dm> ; A1
17213 if (dt1.Is(F16) && dt2.Is(F64) && cond.IsNotNever()) {
17214 EmitA32(0x0eb30bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17215 rm.Encode(5, 0));
17216 return;
17217 }
17218 }
17219 Delegate(kVcvtt, &Assembler::vcvtt, cond, dt1, dt2, rd, rm);
17220}
17221
17222void Assembler::vdiv(
17223 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017224 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017225 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017226 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017227 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
17228 if (dt.Is(F32)) {
17229 EmitT32_32(0xee800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17230 rm.Encode(5, 0));
17231 AdvanceIT();
17232 return;
17233 }
17234 } else {
17235 // VDIV{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
17236 if (dt.Is(F32) && cond.IsNotNever()) {
17237 EmitA32(0x0e800a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17238 rn.Encode(7, 16) | rm.Encode(5, 0));
17239 return;
17240 }
17241 }
17242 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17243}
17244
17245void Assembler::vdiv(
17246 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017247 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017248 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017249 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017250 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
17251 if (dt.Is(F64)) {
17252 EmitT32_32(0xee800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17253 rm.Encode(5, 0));
17254 AdvanceIT();
17255 return;
17256 }
17257 } else {
17258 // VDIV{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
17259 if (dt.Is(F64) && cond.IsNotNever()) {
17260 EmitA32(0x0e800b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17261 rn.Encode(7, 16) | rm.Encode(5, 0));
17262 return;
17263 }
17264 }
17265 Delegate(kVdiv, &Assembler::vdiv, cond, dt, rd, rn, rm);
17266}
17267
17268void Assembler::vdup(Condition cond, DataType dt, QRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017269 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017270 CheckIT(cond);
17271 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017272 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017273 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017274 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017275 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17276 EmitT32_32(0xeea00b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17277 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17278 rd.Encode(7, 16) | (rt.GetCode() << 12));
17279 AdvanceIT();
17280 return;
17281 }
17282 }
17283 } else {
17284 // VDUP{<c>}{<q>}.<dt> <Qd>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017285 if (encoded_dt.IsValid() && cond.IsNotNever() &&
17286 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017287 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17288 EmitA32(0x0ea00b10U | (cond.GetCondition() << 28) |
17289 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17290 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17291 rd.Encode(7, 16) | (rt.GetCode() << 12));
17292 return;
17293 }
17294 }
17295 }
17296 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17297}
17298
17299void Assembler::vdup(Condition cond, DataType dt, DRegister rd, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017300 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017301 CheckIT(cond);
17302 Dt_B_E_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017303 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017304 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017305 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017306 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17307 EmitT32_32(0xee800b10U | ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17308 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17309 rd.Encode(7, 16) | (rt.GetCode() << 12));
17310 AdvanceIT();
17311 return;
17312 }
17313 }
17314 } else {
17315 // VDUP{<c>}{<q>}.<dt> <Dd>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000017316 if (encoded_dt.IsValid() && cond.IsNotNever() &&
17317 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017318 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17319 EmitA32(0x0e800b10U | (cond.GetCondition() << 28) |
17320 ((encoded_dt.GetEncodingValue() & 0x1) << 5) |
17321 ((encoded_dt.GetEncodingValue() & 0x2) << 21) |
17322 rd.Encode(7, 16) | (rt.GetCode() << 12));
17323 return;
17324 }
17325 }
17326 }
17327 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rt);
17328}
17329
17330void Assembler::vdup(Condition cond,
17331 DataType dt,
17332 DRegister rd,
17333 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017334 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017335 CheckIT(cond);
17336 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017337 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017338 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; T1
17339 if (encoded_dt.IsValid()) {
17340 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17341 EmitT32_32(0xffb00c00U | (encoded_dt.GetEncodingValue() << 16) |
17342 rd.Encode(22, 12) | rm.Encode(5, 0));
17343 AdvanceIT();
17344 return;
17345 }
17346 }
17347 } else {
17348 // VDUP{<c>}{<q>}.<dt> <Dd>, <Dm[x]> ; A1
17349 if (encoded_dt.IsValid()) {
17350 if (cond.Is(al)) {
17351 EmitA32(0xf3b00c00U | (encoded_dt.GetEncodingValue() << 16) |
17352 rd.Encode(22, 12) | rm.Encode(5, 0));
17353 return;
17354 }
17355 }
17356 }
17357 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17358}
17359
17360void Assembler::vdup(Condition cond,
17361 DataType dt,
17362 QRegister rd,
17363 DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017364 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017365 CheckIT(cond);
17366 Dt_imm4_1 encoded_dt(dt, rm);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017367 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017368 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; T1
17369 if (encoded_dt.IsValid()) {
17370 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17371 EmitT32_32(0xffb00c40U | (encoded_dt.GetEncodingValue() << 16) |
17372 rd.Encode(22, 12) | rm.Encode(5, 0));
17373 AdvanceIT();
17374 return;
17375 }
17376 }
17377 } else {
17378 // VDUP{<c>}{<q>}.<dt> <Qd>, <Dm[x]> ; A1
17379 if (encoded_dt.IsValid()) {
17380 if (cond.Is(al)) {
17381 EmitA32(0xf3b00c40U | (encoded_dt.GetEncodingValue() << 16) |
17382 rd.Encode(22, 12) | rm.Encode(5, 0));
17383 return;
17384 }
17385 }
17386 }
17387 Delegate(kVdup, &Assembler::vdup, cond, dt, rd, rm);
17388}
17389
17390void Assembler::veor(
17391 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017392 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017393 CheckIT(cond);
17394 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017395 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017396 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
17397 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17398 EmitT32_32(0xff000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17399 rm.Encode(5, 0));
17400 AdvanceIT();
17401 return;
17402 }
17403 } else {
17404 // VEOR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
17405 if (cond.Is(al)) {
17406 EmitA32(0xf3000110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17407 rm.Encode(5, 0));
17408 return;
17409 }
17410 }
17411 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17412}
17413
17414void Assembler::veor(
17415 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017416 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017417 CheckIT(cond);
17418 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017419 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017420 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
17421 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17422 EmitT32_32(0xff000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17423 rm.Encode(5, 0));
17424 AdvanceIT();
17425 return;
17426 }
17427 } else {
17428 // VEOR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
17429 if (cond.Is(al)) {
17430 EmitA32(0xf3000150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17431 rm.Encode(5, 0));
17432 return;
17433 }
17434 }
17435 Delegate(kVeor, &Assembler::veor, cond, dt, rd, rn, rm);
17436}
17437
17438void Assembler::vext(Condition cond,
17439 DataType dt,
17440 DRegister rd,
17441 DRegister rn,
17442 DRegister rm,
17443 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017444 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017445 CheckIT(cond);
17446 if (operand.IsImmediate()) {
17447 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17448 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017449 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017450 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17451 if (dt.Is(Untyped8) && (imm <= 7)) {
17452 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17453 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17454 rm.Encode(5, 0) | (imm << 8));
17455 AdvanceIT();
17456 return;
17457 }
17458 }
17459 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; T1
17460 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17461 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17462 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17463 uint32_t imm4 = imm / dt.GetSize();
17464 EmitT32_32(0xefb00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17465 rm.Encode(5, 0) | (imm4 << 8));
17466 AdvanceIT();
17467 return;
17468 }
17469 }
17470 } else {
17471 // VEXT{<c>}{<q>}.8 {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17472 if (dt.Is(Untyped8) && (imm <= 7)) {
17473 if (cond.Is(al)) {
17474 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17475 rm.Encode(5, 0) | (imm << 8));
17476 return;
17477 }
17478 }
17479 // VEXT{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>, #<imm> ; A1
17480 if ((dt.Is(Untyped16) || dt.Is(Untyped32)) &&
17481 (imm <= (128 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17482 if (cond.Is(al)) {
17483 uint32_t imm4 = imm / dt.GetSize();
17484 EmitA32(0xf2b00000U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17485 rm.Encode(5, 0) | (imm4 << 8));
17486 return;
17487 }
17488 }
17489 }
17490 }
17491 }
17492 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17493}
17494
17495void Assembler::vext(Condition cond,
17496 DataType dt,
17497 QRegister rd,
17498 QRegister rn,
17499 QRegister rm,
17500 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017501 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017502 CheckIT(cond);
17503 if (operand.IsImmediate()) {
17504 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
17505 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017506 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017507 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17508 if (dt.Is(Untyped8) && (imm <= 15)) {
17509 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17510 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17511 rm.Encode(5, 0) | (imm << 8));
17512 AdvanceIT();
17513 return;
17514 }
17515 }
17516 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; T1
17517 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17518 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17519 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17520 uint32_t imm4 = imm / dt.GetSize();
17521 EmitT32_32(0xefb00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17522 rm.Encode(5, 0) | (imm4 << 8));
17523 AdvanceIT();
17524 return;
17525 }
17526 }
17527 } else {
17528 // VEXT{<c>}{<q>}.8 {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17529 if (dt.Is(Untyped8) && (imm <= 15)) {
17530 if (cond.Is(al)) {
17531 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17532 rm.Encode(5, 0) | (imm << 8));
17533 return;
17534 }
17535 }
17536 // VEXT{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm>, #<imm> ; A1
17537 if ((dt.Is(Untyped16) || dt.Is(Untyped32) || dt.Is(Untyped64)) &&
17538 (imm <= (64 / dt.GetSize()) - 1) && ((imm % dt.GetSize()) == 0)) {
17539 if (cond.Is(al)) {
17540 uint32_t imm4 = imm / dt.GetSize();
17541 EmitA32(0xf2b00040U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17542 rm.Encode(5, 0) | (imm4 << 8));
17543 return;
17544 }
17545 }
17546 }
17547 }
17548 }
17549 Delegate(kVext, &Assembler::vext, cond, dt, rd, rn, rm, operand);
17550}
17551
17552void Assembler::vfma(
17553 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017554 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017555 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017556 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017557 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17558 if (dt.Is(F32)) {
17559 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17560 EmitT32_32(0xef000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17561 rm.Encode(5, 0));
17562 AdvanceIT();
17563 return;
17564 }
17565 }
17566 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17567 if (dt.Is(F64)) {
17568 EmitT32_32(0xeea00b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17569 rm.Encode(5, 0));
17570 AdvanceIT();
17571 return;
17572 }
17573 } else {
17574 // VFMA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17575 if (dt.Is(F32)) {
17576 if (cond.Is(al)) {
17577 EmitA32(0xf2000c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17578 rm.Encode(5, 0));
17579 return;
17580 }
17581 }
17582 // VFMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17583 if (dt.Is(F64) && cond.IsNotNever()) {
17584 EmitA32(0x0ea00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17585 rn.Encode(7, 16) | rm.Encode(5, 0));
17586 return;
17587 }
17588 }
17589 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17590}
17591
17592void Assembler::vfma(
17593 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017594 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017595 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017596 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017597 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17598 if (dt.Is(F32)) {
17599 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17600 EmitT32_32(0xef000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17601 rm.Encode(5, 0));
17602 AdvanceIT();
17603 return;
17604 }
17605 }
17606 } else {
17607 // VFMA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17608 if (dt.Is(F32)) {
17609 if (cond.Is(al)) {
17610 EmitA32(0xf2000c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17611 rm.Encode(5, 0));
17612 return;
17613 }
17614 }
17615 }
17616 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17617}
17618
17619void Assembler::vfma(
17620 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017621 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017622 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017623 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017624 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17625 if (dt.Is(F32)) {
17626 EmitT32_32(0xeea00a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17627 rm.Encode(5, 0));
17628 AdvanceIT();
17629 return;
17630 }
17631 } else {
17632 // VFMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17633 if (dt.Is(F32) && cond.IsNotNever()) {
17634 EmitA32(0x0ea00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17635 rn.Encode(7, 16) | rm.Encode(5, 0));
17636 return;
17637 }
17638 }
17639 Delegate(kVfma, &Assembler::vfma, cond, dt, rd, rn, rm);
17640}
17641
17642void Assembler::vfms(
17643 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017644 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017645 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017646 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017647 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
17648 if (dt.Is(F32)) {
17649 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17650 EmitT32_32(0xef200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17651 rm.Encode(5, 0));
17652 AdvanceIT();
17653 return;
17654 }
17655 }
17656 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
17657 if (dt.Is(F64)) {
17658 EmitT32_32(0xeea00b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17659 rm.Encode(5, 0));
17660 AdvanceIT();
17661 return;
17662 }
17663 } else {
17664 // VFMS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
17665 if (dt.Is(F32)) {
17666 if (cond.Is(al)) {
17667 EmitA32(0xf2200c10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17668 rm.Encode(5, 0));
17669 return;
17670 }
17671 }
17672 // VFMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
17673 if (dt.Is(F64) && cond.IsNotNever()) {
17674 EmitA32(0x0ea00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17675 rn.Encode(7, 16) | rm.Encode(5, 0));
17676 return;
17677 }
17678 }
17679 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17680}
17681
17682void Assembler::vfms(
17683 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017684 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017685 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017686 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017687 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
17688 if (dt.Is(F32)) {
17689 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17690 EmitT32_32(0xef200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17691 rm.Encode(5, 0));
17692 AdvanceIT();
17693 return;
17694 }
17695 }
17696 } else {
17697 // VFMS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
17698 if (dt.Is(F32)) {
17699 if (cond.Is(al)) {
17700 EmitA32(0xf2200c50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17701 rm.Encode(5, 0));
17702 return;
17703 }
17704 }
17705 }
17706 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17707}
17708
17709void Assembler::vfms(
17710 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017711 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017712 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017713 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017714 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
17715 if (dt.Is(F32)) {
17716 EmitT32_32(0xeea00a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17717 rm.Encode(5, 0));
17718 AdvanceIT();
17719 return;
17720 }
17721 } else {
17722 // VFMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
17723 if (dt.Is(F32) && cond.IsNotNever()) {
17724 EmitA32(0x0ea00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17725 rn.Encode(7, 16) | rm.Encode(5, 0));
17726 return;
17727 }
17728 }
17729 Delegate(kVfms, &Assembler::vfms, cond, dt, rd, rn, rm);
17730}
17731
17732void Assembler::vfnma(
17733 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017734 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017735 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017736 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017737 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17738 if (dt.Is(F32)) {
17739 EmitT32_32(0xee900a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17740 rm.Encode(5, 0));
17741 AdvanceIT();
17742 return;
17743 }
17744 } else {
17745 // VFNMA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17746 if (dt.Is(F32) && cond.IsNotNever()) {
17747 EmitA32(0x0e900a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17748 rn.Encode(7, 16) | rm.Encode(5, 0));
17749 return;
17750 }
17751 }
17752 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17753}
17754
17755void Assembler::vfnma(
17756 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017757 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017758 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017759 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017760 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17761 if (dt.Is(F64)) {
17762 EmitT32_32(0xee900b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17763 rm.Encode(5, 0));
17764 AdvanceIT();
17765 return;
17766 }
17767 } else {
17768 // VFNMA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17769 if (dt.Is(F64) && cond.IsNotNever()) {
17770 EmitA32(0x0e900b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17771 rn.Encode(7, 16) | rm.Encode(5, 0));
17772 return;
17773 }
17774 }
17775 Delegate(kVfnma, &Assembler::vfnma, cond, dt, rd, rn, rm);
17776}
17777
17778void Assembler::vfnms(
17779 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017780 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017781 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017783 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
17784 if (dt.Is(F32)) {
17785 EmitT32_32(0xee900a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17786 rm.Encode(5, 0));
17787 AdvanceIT();
17788 return;
17789 }
17790 } else {
17791 // VFNMS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
17792 if (dt.Is(F32) && cond.IsNotNever()) {
17793 EmitA32(0x0e900a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17794 rn.Encode(7, 16) | rm.Encode(5, 0));
17795 return;
17796 }
17797 }
17798 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17799}
17800
17801void Assembler::vfnms(
17802 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017803 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017804 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017805 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017806 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
17807 if (dt.Is(F64)) {
17808 EmitT32_32(0xee900b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
17809 rm.Encode(5, 0));
17810 AdvanceIT();
17811 return;
17812 }
17813 } else {
17814 // VFNMS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
17815 if (dt.Is(F64) && cond.IsNotNever()) {
17816 EmitA32(0x0e900b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
17817 rn.Encode(7, 16) | rm.Encode(5, 0));
17818 return;
17819 }
17820 }
17821 Delegate(kVfnms, &Assembler::vfnms, cond, dt, rd, rn, rm);
17822}
17823
17824void Assembler::vhadd(
17825 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017826 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017827 CheckIT(cond);
17828 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017829 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017830 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17831 if (encoded_dt.IsValid()) {
17832 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17833 EmitT32_32(0xef000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17834 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17835 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17836 AdvanceIT();
17837 return;
17838 }
17839 }
17840 } else {
17841 // VHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17842 if (encoded_dt.IsValid()) {
17843 if (cond.Is(al)) {
17844 EmitA32(0xf2000000U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17845 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17846 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17847 return;
17848 }
17849 }
17850 }
17851 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17852}
17853
17854void Assembler::vhadd(
17855 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017856 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017857 CheckIT(cond);
17858 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017859 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017860 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17861 if (encoded_dt.IsValid()) {
17862 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17863 EmitT32_32(0xef000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17864 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17865 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17866 AdvanceIT();
17867 return;
17868 }
17869 }
17870 } else {
17871 // VHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17872 if (encoded_dt.IsValid()) {
17873 if (cond.Is(al)) {
17874 EmitA32(0xf2000040U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17875 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17876 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17877 return;
17878 }
17879 }
17880 }
17881 Delegate(kVhadd, &Assembler::vhadd, cond, dt, rd, rn, rm);
17882}
17883
17884void Assembler::vhsub(
17885 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017886 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017887 CheckIT(cond);
17888 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017889 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017890 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
17891 if (encoded_dt.IsValid()) {
17892 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17893 EmitT32_32(0xef000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17894 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17895 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17896 AdvanceIT();
17897 return;
17898 }
17899 }
17900 } else {
17901 // VHSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
17902 if (encoded_dt.IsValid()) {
17903 if (cond.Is(al)) {
17904 EmitA32(0xf2000200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17905 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17906 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17907 return;
17908 }
17909 }
17910 }
17911 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17912}
17913
17914void Assembler::vhsub(
17915 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017916 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017917 CheckIT(cond);
17918 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017919 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017920 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
17921 if (encoded_dt.IsValid()) {
17922 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17923 EmitT32_32(0xef000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17924 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
17925 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17926 AdvanceIT();
17927 return;
17928 }
17929 }
17930 } else {
17931 // VHSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
17932 if (encoded_dt.IsValid()) {
17933 if (cond.Is(al)) {
17934 EmitA32(0xf2000240U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
17935 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
17936 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
17937 return;
17938 }
17939 }
17940 }
17941 Delegate(kVhsub, &Assembler::vhsub, cond, dt, rd, rn, rm);
17942}
17943
17944void Assembler::vld1(Condition cond,
17945 DataType dt,
17946 const NeonRegisterList& nreglist,
17947 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070017948 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010017949 CheckIT(cond);
17950 if (operand.IsImmediateZero()) {
17951 Register rn = operand.GetBaseRegister();
17952 Alignment align = operand.GetAlignment();
17953 Dt_size_6 encoded_dt(dt);
17954 Dt_size_7 encoded_dt_2(dt);
17955 Align_align_1 encoded_align_1(align, nreglist);
17956 Align_a_1 encoded_align_2(align, dt);
17957 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010017958 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017959 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
17960 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17961 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080017962 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080017963 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017964 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17965 const DRegister& first = nreglist.GetFirstDRegister();
17966 uint32_t len_encoding;
17967 switch (nreglist.GetLength()) {
17968 default:
17969 VIXL_UNREACHABLE_OR_FALLTHROUGH();
17970 case 1:
17971 len_encoding = 0x7;
17972 break;
17973 case 2:
17974 len_encoding = 0xa;
17975 break;
17976 case 3:
17977 len_encoding = 0x6;
17978 break;
17979 case 4:
17980 len_encoding = 0x2;
17981 break;
17982 }
17983 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
17984 (encoded_align_1.GetEncodingValue() << 4) |
17985 first.Encode(22, 12) | (len_encoding << 8) |
17986 (rn.GetCode() << 16));
17987 AdvanceIT();
17988 return;
17989 }
17990 }
17991 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
17992 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
17993 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080017994 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080017995 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010017996 if (cond.Is(al) || AllowStronglyDiscouraged()) {
17997 const DRegister& first = nreglist.GetFirstDRegister();
17998 uint32_t len_encoding;
17999 switch (nreglist.GetLength()) {
18000 default:
18001 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18002 case 1:
18003 len_encoding = 0x7;
18004 break;
18005 case 2:
18006 len_encoding = 0xa;
18007 break;
18008 case 3:
18009 len_encoding = 0x6;
18010 break;
18011 case 4:
18012 len_encoding = 0x2;
18013 break;
18014 }
18015 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18016 (encoded_align_1.GetEncodingValue() << 4) |
18017 first.Encode(22, 12) | (len_encoding << 8) |
18018 (rn.GetCode() << 16));
18019 AdvanceIT();
18020 return;
18021 }
18022 }
18023 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18024 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18025 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018026 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018027 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018028 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18029 const DRegister& first = nreglist.GetFirstDRegister();
18030 uint32_t len_encoding = nreglist.GetLength() - 1;
18031 EmitT32_32(0xf9a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18032 (encoded_align_2.GetEncodingValue() << 4) |
18033 first.Encode(22, 12) | (len_encoding << 5) |
18034 (rn.GetCode() << 16));
18035 AdvanceIT();
18036 return;
18037 }
18038 }
18039 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18040 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18041 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018042 operand.IsPostIndex() && encoded_align_2.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 = nreglist.GetLength() - 1;
18047 EmitT32_32(0xf9a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18048 (encoded_align_2.GetEncodingValue() << 4) |
18049 first.Encode(22, 12) | (len_encoding << 5) |
18050 (rn.GetCode() << 16));
18051 AdvanceIT();
18052 return;
18053 }
18054 }
18055 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18056 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018057 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018058 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018059 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18060 const DRegister& first = nreglist.GetFirstDRegister();
18061 EmitT32_32(0xf9a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18062 (encoded_align_3.GetEncodingValue() << 4) |
18063 first.Encode(22, 12) | (rn.GetCode() << 16));
18064 AdvanceIT();
18065 return;
18066 }
18067 }
18068 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18069 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018070 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018071 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018072 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18073 const DRegister& first = nreglist.GetFirstDRegister();
18074 EmitT32_32(0xf9a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18075 (encoded_align_3.GetEncodingValue() << 4) |
18076 first.Encode(22, 12) | (rn.GetCode() << 16));
18077 AdvanceIT();
18078 return;
18079 }
18080 }
18081 } else {
18082 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18083 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18084 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018085 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018086 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018087 if (cond.Is(al)) {
18088 const DRegister& first = nreglist.GetFirstDRegister();
18089 uint32_t len_encoding;
18090 switch (nreglist.GetLength()) {
18091 default:
18092 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18093 case 1:
18094 len_encoding = 0x7;
18095 break;
18096 case 2:
18097 len_encoding = 0xa;
18098 break;
18099 case 3:
18100 len_encoding = 0x6;
18101 break;
18102 case 4:
18103 len_encoding = 0x2;
18104 break;
18105 }
18106 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18107 (encoded_align_1.GetEncodingValue() << 4) |
18108 first.Encode(22, 12) | (len_encoding << 8) |
18109 (rn.GetCode() << 16));
18110 return;
18111 }
18112 }
18113 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18114 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18115 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018116 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018117 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018118 if (cond.Is(al)) {
18119 const DRegister& first = nreglist.GetFirstDRegister();
18120 uint32_t len_encoding;
18121 switch (nreglist.GetLength()) {
18122 default:
18123 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18124 case 1:
18125 len_encoding = 0x7;
18126 break;
18127 case 2:
18128 len_encoding = 0xa;
18129 break;
18130 case 3:
18131 len_encoding = 0x6;
18132 break;
18133 case 4:
18134 len_encoding = 0x2;
18135 break;
18136 }
18137 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18138 (encoded_align_1.GetEncodingValue() << 4) |
18139 first.Encode(22, 12) | (len_encoding << 8) |
18140 (rn.GetCode() << 16));
18141 return;
18142 }
18143 }
18144 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18145 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18146 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018147 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018148 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018149 if (cond.Is(al)) {
18150 const DRegister& first = nreglist.GetFirstDRegister();
18151 uint32_t len_encoding = nreglist.GetLength() - 1;
18152 EmitA32(0xf4a00c0fU | (encoded_dt_2.GetEncodingValue() << 6) |
18153 (encoded_align_2.GetEncodingValue() << 4) |
18154 first.Encode(22, 12) | (len_encoding << 5) |
18155 (rn.GetCode() << 16));
18156 return;
18157 }
18158 }
18159 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18160 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18161 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018162 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018163 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018164 if (cond.Is(al)) {
18165 const DRegister& first = nreglist.GetFirstDRegister();
18166 uint32_t len_encoding = nreglist.GetLength() - 1;
18167 EmitA32(0xf4a00c0dU | (encoded_dt_2.GetEncodingValue() << 6) |
18168 (encoded_align_2.GetEncodingValue() << 4) |
18169 first.Encode(22, 12) | (len_encoding << 5) |
18170 (rn.GetCode() << 16));
18171 return;
18172 }
18173 }
18174 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18175 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018176 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018177 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018178 if (cond.Is(al)) {
18179 const DRegister& first = nreglist.GetFirstDRegister();
18180 EmitA32(0xf4a0000fU | (encoded_dt_2.GetEncodingValue() << 10) |
18181 (encoded_align_3.GetEncodingValue() << 4) |
18182 first.Encode(22, 12) | (rn.GetCode() << 16));
18183 return;
18184 }
18185 }
18186 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18187 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018188 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018189 encoded_align_3.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018190 if (cond.Is(al)) {
18191 const DRegister& first = nreglist.GetFirstDRegister();
18192 EmitA32(0xf4a0000dU | (encoded_dt_2.GetEncodingValue() << 10) |
18193 (encoded_align_3.GetEncodingValue() << 4) |
18194 first.Encode(22, 12) | (rn.GetCode() << 16));
18195 return;
18196 }
18197 }
18198 }
18199 }
18200 if (operand.IsPlainRegister()) {
18201 Register rn = operand.GetBaseRegister();
18202 Alignment align = operand.GetAlignment();
18203 Register rm = operand.GetOffsetRegister();
18204 Dt_size_6 encoded_dt(dt);
18205 Dt_size_7 encoded_dt_2(dt);
18206 Align_align_1 encoded_align_1(align, nreglist);
18207 Align_a_1 encoded_align_2(align, dt);
18208 Align_index_align_1 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018209 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018210 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18211 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18212 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018213 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018214 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18215 const DRegister& first = nreglist.GetFirstDRegister();
18216 uint32_t len_encoding;
18217 switch (nreglist.GetLength()) {
18218 default:
18219 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18220 case 1:
18221 len_encoding = 0x7;
18222 break;
18223 case 2:
18224 len_encoding = 0xa;
18225 break;
18226 case 3:
18227 len_encoding = 0x6;
18228 break;
18229 case 4:
18230 len_encoding = 0x2;
18231 break;
18232 }
18233 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18234 (encoded_align_1.GetEncodingValue() << 4) |
18235 first.Encode(22, 12) | (len_encoding << 8) |
18236 (rn.GetCode() << 16) | rm.GetCode());
18237 AdvanceIT();
18238 return;
18239 }
18240 }
18241 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18242 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18243 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018244 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018245 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18246 const DRegister& first = nreglist.GetFirstDRegister();
18247 uint32_t len_encoding = nreglist.GetLength() - 1;
18248 EmitT32_32(0xf9a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18249 (encoded_align_2.GetEncodingValue() << 4) |
18250 first.Encode(22, 12) | (len_encoding << 5) |
18251 (rn.GetCode() << 16) | rm.GetCode());
18252 AdvanceIT();
18253 return;
18254 }
18255 }
18256 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18257 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018258 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18259 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018260 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18261 const DRegister& first = nreglist.GetFirstDRegister();
18262 EmitT32_32(0xf9a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18263 (encoded_align_3.GetEncodingValue() << 4) |
18264 first.Encode(22, 12) | (rn.GetCode() << 16) |
18265 rm.GetCode());
18266 AdvanceIT();
18267 return;
18268 }
18269 }
18270 } else {
18271 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18272 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18273 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018274 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018275 if (cond.Is(al)) {
18276 const DRegister& first = nreglist.GetFirstDRegister();
18277 uint32_t len_encoding;
18278 switch (nreglist.GetLength()) {
18279 default:
18280 VIXL_UNREACHABLE_OR_FALLTHROUGH();
18281 case 1:
18282 len_encoding = 0x7;
18283 break;
18284 case 2:
18285 len_encoding = 0xa;
18286 break;
18287 case 3:
18288 len_encoding = 0x6;
18289 break;
18290 case 4:
18291 len_encoding = 0x2;
18292 break;
18293 }
18294 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18295 (encoded_align_1.GetEncodingValue() << 4) |
18296 first.Encode(22, 12) | (len_encoding << 8) |
18297 (rn.GetCode() << 16) | rm.GetCode());
18298 return;
18299 }
18300 }
18301 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18302 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
18303 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 2) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018304 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018305 if (cond.Is(al)) {
18306 const DRegister& first = nreglist.GetFirstDRegister();
18307 uint32_t len_encoding = nreglist.GetLength() - 1;
18308 EmitA32(0xf4a00c00U | (encoded_dt_2.GetEncodingValue() << 6) |
18309 (encoded_align_2.GetEncodingValue() << 4) |
18310 first.Encode(22, 12) | (len_encoding << 5) |
18311 (rn.GetCode() << 16) | rm.GetCode());
18312 return;
18313 }
18314 }
18315 // VLD1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18316 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018317 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
18318 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018319 if (cond.Is(al)) {
18320 const DRegister& first = nreglist.GetFirstDRegister();
18321 EmitA32(0xf4a00000U | (encoded_dt_2.GetEncodingValue() << 10) |
18322 (encoded_align_3.GetEncodingValue() << 4) |
18323 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18324 return;
18325 }
18326 }
18327 }
18328 }
18329 Delegate(kVld1, &Assembler::vld1, cond, dt, nreglist, operand);
18330}
18331
18332void Assembler::vld2(Condition cond,
18333 DataType dt,
18334 const NeonRegisterList& nreglist,
18335 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018336 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018337 CheckIT(cond);
18338 if (operand.IsImmediateZero()) {
18339 Register rn = operand.GetBaseRegister();
18340 Alignment align = operand.GetAlignment();
18341 Dt_size_7 encoded_dt(dt);
18342 Align_align_2 encoded_align_1(align, nreglist);
18343 Align_a_2 encoded_align_2(align, dt);
18344 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018345 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018346 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18347 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18348 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18349 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18350 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018351 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018352 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018353 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18354 const DRegister& first = nreglist.GetFirstDRegister();
18355 uint32_t len_encoding;
18356 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18357 len_encoding = 0x8;
18358 }
18359 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18360 len_encoding = 0x9;
18361 }
18362 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18363 len_encoding = 0x3;
18364 }
18365 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18366 (encoded_align_1.GetEncodingValue() << 4) |
18367 first.Encode(22, 12) | (len_encoding << 8) |
18368 (rn.GetCode() << 16));
18369 AdvanceIT();
18370 return;
18371 }
18372 }
18373 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18374 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18375 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18376 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18377 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018378 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018379 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018380 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18381 const DRegister& first = nreglist.GetFirstDRegister();
18382 uint32_t len_encoding;
18383 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18384 len_encoding = 0x8;
18385 }
18386 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18387 len_encoding = 0x9;
18388 }
18389 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18390 len_encoding = 0x3;
18391 }
18392 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18393 (encoded_align_1.GetEncodingValue() << 4) |
18394 first.Encode(22, 12) | (len_encoding << 8) |
18395 (rn.GetCode() << 16));
18396 AdvanceIT();
18397 return;
18398 }
18399 }
18400 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18401 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18402 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18403 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018404 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018405 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018406 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18407 const DRegister& first = nreglist.GetFirstDRegister();
18408 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18409 EmitT32_32(0xf9a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18410 (encoded_align_2.GetEncodingValue() << 4) |
18411 first.Encode(22, 12) | (len_encoding << 5) |
18412 (rn.GetCode() << 16));
18413 AdvanceIT();
18414 return;
18415 }
18416 }
18417 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18418 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18419 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18420 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018421 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018422 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018423 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18424 const DRegister& first = nreglist.GetFirstDRegister();
18425 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18426 EmitT32_32(0xf9a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18427 (encoded_align_2.GetEncodingValue() << 4) |
18428 first.Encode(22, 12) | (len_encoding << 5) |
18429 (rn.GetCode() << 16));
18430 AdvanceIT();
18431 return;
18432 }
18433 }
18434 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18435 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18436 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18437 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018438 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018439 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018440 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18441 const DRegister& first = nreglist.GetFirstDRegister();
18442 EmitT32_32(0xf9a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18443 (encoded_align_3.GetEncodingValue() << 4) |
18444 first.Encode(22, 12) | (rn.GetCode() << 16));
18445 AdvanceIT();
18446 return;
18447 }
18448 }
18449 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18450 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18451 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18452 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018453 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018454 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018455 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18456 const DRegister& first = nreglist.GetFirstDRegister();
18457 EmitT32_32(0xf9a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18458 (encoded_align_3.GetEncodingValue() << 4) |
18459 first.Encode(22, 12) | (rn.GetCode() << 16));
18460 AdvanceIT();
18461 return;
18462 }
18463 }
18464 } else {
18465 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18466 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18467 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18468 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18469 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018470 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018471 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018472 if (cond.Is(al)) {
18473 const DRegister& first = nreglist.GetFirstDRegister();
18474 uint32_t len_encoding;
18475 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18476 len_encoding = 0x8;
18477 }
18478 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18479 len_encoding = 0x9;
18480 }
18481 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18482 len_encoding = 0x3;
18483 }
18484 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18485 (encoded_align_1.GetEncodingValue() << 4) |
18486 first.Encode(22, 12) | (len_encoding << 8) |
18487 (rn.GetCode() << 16));
18488 return;
18489 }
18490 }
18491 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18492 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18493 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18494 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18495 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018496 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018497 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018498 if (cond.Is(al)) {
18499 const DRegister& first = nreglist.GetFirstDRegister();
18500 uint32_t len_encoding;
18501 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18502 len_encoding = 0x8;
18503 }
18504 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18505 len_encoding = 0x9;
18506 }
18507 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18508 len_encoding = 0x3;
18509 }
18510 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18511 (encoded_align_1.GetEncodingValue() << 4) |
18512 first.Encode(22, 12) | (len_encoding << 8) |
18513 (rn.GetCode() << 16));
18514 return;
18515 }
18516 }
18517 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18518 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18519 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18520 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018521 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018522 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018523 if (cond.Is(al)) {
18524 const DRegister& first = nreglist.GetFirstDRegister();
18525 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18526 EmitA32(0xf4a00d0fU | (encoded_dt.GetEncodingValue() << 6) |
18527 (encoded_align_2.GetEncodingValue() << 4) |
18528 first.Encode(22, 12) | (len_encoding << 5) |
18529 (rn.GetCode() << 16));
18530 return;
18531 }
18532 }
18533 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18534 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18535 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18536 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018537 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018538 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018539 if (cond.Is(al)) {
18540 const DRegister& first = nreglist.GetFirstDRegister();
18541 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18542 EmitA32(0xf4a00d0dU | (encoded_dt.GetEncodingValue() << 6) |
18543 (encoded_align_2.GetEncodingValue() << 4) |
18544 first.Encode(22, 12) | (len_encoding << 5) |
18545 (rn.GetCode() << 16));
18546 return;
18547 }
18548 }
18549 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18550 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18551 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18552 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018553 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018554 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018555 if (cond.Is(al)) {
18556 const DRegister& first = nreglist.GetFirstDRegister();
18557 EmitA32(0xf4a0010fU | (encoded_dt.GetEncodingValue() << 10) |
18558 (encoded_align_3.GetEncodingValue() << 4) |
18559 first.Encode(22, 12) | (rn.GetCode() << 16));
18560 return;
18561 }
18562 }
18563 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18564 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18565 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18566 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018567 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018568 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018569 if (cond.Is(al)) {
18570 const DRegister& first = nreglist.GetFirstDRegister();
18571 EmitA32(0xf4a0010dU | (encoded_dt.GetEncodingValue() << 10) |
18572 (encoded_align_3.GetEncodingValue() << 4) |
18573 first.Encode(22, 12) | (rn.GetCode() << 16));
18574 return;
18575 }
18576 }
18577 }
18578 }
18579 if (operand.IsPlainRegister()) {
18580 Register rn = operand.GetBaseRegister();
18581 Alignment align = operand.GetAlignment();
18582 Register rm = operand.GetOffsetRegister();
18583 Dt_size_7 encoded_dt(dt);
18584 Align_align_2 encoded_align_1(align, nreglist);
18585 Align_a_2 encoded_align_2(align, dt);
18586 Align_index_align_2 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018587 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018588 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18589 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18590 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18591 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18592 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018593 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018594 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18595 const DRegister& first = nreglist.GetFirstDRegister();
18596 uint32_t len_encoding;
18597 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18598 len_encoding = 0x8;
18599 }
18600 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18601 len_encoding = 0x9;
18602 }
18603 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18604 len_encoding = 0x3;
18605 }
18606 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18607 (encoded_align_1.GetEncodingValue() << 4) |
18608 first.Encode(22, 12) | (len_encoding << 8) |
18609 (rn.GetCode() << 16) | rm.GetCode());
18610 AdvanceIT();
18611 return;
18612 }
18613 }
18614 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18615 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18616 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18617 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018618 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018619 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18620 const DRegister& first = nreglist.GetFirstDRegister();
18621 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18622 EmitT32_32(0xf9a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18623 (encoded_align_2.GetEncodingValue() << 4) |
18624 first.Encode(22, 12) | (len_encoding << 5) |
18625 (rn.GetCode() << 16) | rm.GetCode());
18626 AdvanceIT();
18627 return;
18628 }
18629 }
18630 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18631 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18632 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18633 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018634 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018635 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18636 const DRegister& first = nreglist.GetFirstDRegister();
18637 EmitT32_32(0xf9a00100U | (encoded_dt.GetEncodingValue() << 10) |
18638 (encoded_align_3.GetEncodingValue() << 4) |
18639 first.Encode(22, 12) | (rn.GetCode() << 16) |
18640 rm.GetCode());
18641 AdvanceIT();
18642 return;
18643 }
18644 }
18645 } else {
18646 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18647 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18648 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18649 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
18650 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018651 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018652 if (cond.Is(al)) {
18653 const DRegister& first = nreglist.GetFirstDRegister();
18654 uint32_t len_encoding;
18655 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
18656 len_encoding = 0x8;
18657 }
18658 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
18659 len_encoding = 0x9;
18660 }
18661 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
18662 len_encoding = 0x3;
18663 }
18664 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18665 (encoded_align_1.GetEncodingValue() << 4) |
18666 first.Encode(22, 12) | (len_encoding << 8) |
18667 (rn.GetCode() << 16) | rm.GetCode());
18668 return;
18669 }
18670 }
18671 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18672 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18673 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18674 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018675 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018676 if (cond.Is(al)) {
18677 const DRegister& first = nreglist.GetFirstDRegister();
18678 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18679 EmitA32(0xf4a00d00U | (encoded_dt.GetEncodingValue() << 6) |
18680 (encoded_align_2.GetEncodingValue() << 4) |
18681 first.Encode(22, 12) | (len_encoding << 5) |
18682 (rn.GetCode() << 16) | rm.GetCode());
18683 return;
18684 }
18685 }
18686 // VLD2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18687 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18688 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
18689 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018690 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018691 if (cond.Is(al)) {
18692 const DRegister& first = nreglist.GetFirstDRegister();
18693 EmitA32(0xf4a00100U | (encoded_dt.GetEncodingValue() << 10) |
18694 (encoded_align_3.GetEncodingValue() << 4) |
18695 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
18696 return;
18697 }
18698 }
18699 }
18700 }
18701 Delegate(kVld2, &Assembler::vld2, cond, dt, nreglist, operand);
18702}
18703
18704void Assembler::vld3(Condition cond,
18705 DataType dt,
18706 const NeonRegisterList& nreglist,
18707 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018708 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018709 CheckIT(cond);
18710 if (operand.IsImmediateZero()) {
18711 Register rn = operand.GetBaseRegister();
18712 Alignment align = operand.GetAlignment();
18713 Dt_size_7 encoded_dt(dt);
18714 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018715 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018716 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
18717 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18718 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18719 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018720 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018721 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018722 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18723 const DRegister& first = nreglist.GetFirstDRegister();
18724 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18725 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
18726 (encoded_align_1.GetEncodingValue() << 4) |
18727 first.Encode(22, 12) | (len_encoding << 8) |
18728 (rn.GetCode() << 16));
18729 AdvanceIT();
18730 return;
18731 }
18732 }
18733 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
18734 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18735 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18736 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018737 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018738 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018739 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18740 const DRegister& first = nreglist.GetFirstDRegister();
18741 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18742 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
18743 (encoded_align_1.GetEncodingValue() << 4) |
18744 first.Encode(22, 12) | (len_encoding << 8) |
18745 (rn.GetCode() << 16));
18746 AdvanceIT();
18747 return;
18748 }
18749 }
18750 } else {
18751 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
18752 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18753 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18754 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018755 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018756 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018757 if (cond.Is(al)) {
18758 const DRegister& first = nreglist.GetFirstDRegister();
18759 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18760 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
18761 (encoded_align_1.GetEncodingValue() << 4) |
18762 first.Encode(22, 12) | (len_encoding << 8) |
18763 (rn.GetCode() << 16));
18764 return;
18765 }
18766 }
18767 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
18768 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18769 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18770 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080018771 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018772 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018773 if (cond.Is(al)) {
18774 const DRegister& first = nreglist.GetFirstDRegister();
18775 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18776 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
18777 (encoded_align_1.GetEncodingValue() << 4) |
18778 first.Encode(22, 12) | (len_encoding << 8) |
18779 (rn.GetCode() << 16));
18780 return;
18781 }
18782 }
18783 }
18784 }
18785 if (operand.IsPlainRegister()) {
18786 Register rn = operand.GetBaseRegister();
18787 Alignment align = operand.GetAlignment();
18788 Register rm = operand.GetOffsetRegister();
18789 Dt_size_7 encoded_dt(dt);
18790 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018791 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018792 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
18793 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18794 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18795 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018796 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018797 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18798 const DRegister& first = nreglist.GetFirstDRegister();
18799 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18800 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
18801 (encoded_align_1.GetEncodingValue() << 4) |
18802 first.Encode(22, 12) | (len_encoding << 8) |
18803 (rn.GetCode() << 16) | rm.GetCode());
18804 AdvanceIT();
18805 return;
18806 }
18807 }
18808 } else {
18809 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
18810 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
18811 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18812 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018813 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018814 if (cond.Is(al)) {
18815 const DRegister& first = nreglist.GetFirstDRegister();
18816 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
18817 EmitA32(0xf4200000U | (encoded_dt.GetEncodingValue() << 6) |
18818 (encoded_align_1.GetEncodingValue() << 4) |
18819 first.Encode(22, 12) | (len_encoding << 8) |
18820 (rn.GetCode() << 16) | rm.GetCode());
18821 return;
18822 }
18823 }
18824 }
18825 }
18826 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
18827}
18828
18829void Assembler::vld3(Condition cond,
18830 DataType dt,
18831 const NeonRegisterList& nreglist,
18832 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070018833 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010018834 CheckIT(cond);
18835 if (operand.IsImmediateZero()) {
18836 Register rn = operand.GetBaseRegister();
18837 Dt_size_7 encoded_dt(dt);
18838 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018839 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018840 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18841 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18842 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18843 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018844 operand.IsOffset() && (!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() ? 0x0 : 0x1;
18848 EmitT32_32(0xf9a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18849 first.Encode(22, 12) | (len_encoding << 5) |
18850 (rn.GetCode() << 16));
18851 AdvanceIT();
18852 return;
18853 }
18854 }
18855 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18856 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18857 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18858 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018859 operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018860 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18861 const DRegister& first = nreglist.GetFirstDRegister();
18862 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18863 EmitT32_32(0xf9a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18864 first.Encode(22, 12) | (len_encoding << 5) |
18865 (rn.GetCode() << 16));
18866 AdvanceIT();
18867 return;
18868 }
18869 }
18870 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
18871 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18872 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18873 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018874 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018875 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18876 const DRegister& first = nreglist.GetFirstDRegister();
18877 EmitT32_32(0xf9a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18878 (encoded_align_1.GetEncodingValue() << 4) |
18879 first.Encode(22, 12) | (rn.GetCode() << 16));
18880 AdvanceIT();
18881 return;
18882 }
18883 }
18884 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
18885 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18886 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18887 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018888 operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018889 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18890 const DRegister& first = nreglist.GetFirstDRegister();
18891 EmitT32_32(0xf9a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18892 (encoded_align_1.GetEncodingValue() << 4) |
18893 first.Encode(22, 12) | (rn.GetCode() << 16));
18894 AdvanceIT();
18895 return;
18896 }
18897 }
18898 } else {
18899 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18900 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18901 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18902 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018903 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018904 if (cond.Is(al)) {
18905 const DRegister& first = nreglist.GetFirstDRegister();
18906 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18907 EmitA32(0xf4a00e0fU | (encoded_dt.GetEncodingValue() << 6) |
18908 first.Encode(22, 12) | (len_encoding << 5) |
18909 (rn.GetCode() << 16));
18910 return;
18911 }
18912 }
18913 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18914 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18915 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18916 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018917 operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018918 if (cond.Is(al)) {
18919 const DRegister& first = nreglist.GetFirstDRegister();
18920 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18921 EmitA32(0xf4a00e0dU | (encoded_dt.GetEncodingValue() << 6) |
18922 first.Encode(22, 12) | (len_encoding << 5) |
18923 (rn.GetCode() << 16));
18924 return;
18925 }
18926 }
18927 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
18928 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18929 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18930 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018931 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018932 if (cond.Is(al)) {
18933 const DRegister& first = nreglist.GetFirstDRegister();
18934 EmitA32(0xf4a0020fU | (encoded_dt.GetEncodingValue() << 10) |
18935 (encoded_align_1.GetEncodingValue() << 4) |
18936 first.Encode(22, 12) | (rn.GetCode() << 16));
18937 return;
18938 }
18939 }
18940 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
18941 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18942 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18943 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080018944 operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018945 if (cond.Is(al)) {
18946 const DRegister& first = nreglist.GetFirstDRegister();
18947 EmitA32(0xf4a0020dU | (encoded_dt.GetEncodingValue() << 10) |
18948 (encoded_align_1.GetEncodingValue() << 4) |
18949 first.Encode(22, 12) | (rn.GetCode() << 16));
18950 return;
18951 }
18952 }
18953 }
18954 }
18955 if (operand.IsPlainRegister()) {
18956 Register rn = operand.GetBaseRegister();
18957 Sign sign = operand.GetSign();
18958 Register rm = operand.GetOffsetRegister();
18959 Dt_size_7 encoded_dt(dt);
18960 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010018961 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018962 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
18963 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18964 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18965 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018966 sign.IsPlus() && operand.IsPostIndex() &&
18967 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018968 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18969 const DRegister& first = nreglist.GetFirstDRegister();
18970 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
18971 EmitT32_32(0xf9a00e00U | (encoded_dt.GetEncodingValue() << 6) |
18972 first.Encode(22, 12) | (len_encoding << 5) |
18973 (rn.GetCode() << 16) | rm.GetCode());
18974 AdvanceIT();
18975 return;
18976 }
18977 }
18978 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
18979 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
18980 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18981 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018982 sign.IsPlus() && operand.IsPostIndex() &&
18983 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010018984 if (cond.Is(al) || AllowStronglyDiscouraged()) {
18985 const DRegister& first = nreglist.GetFirstDRegister();
18986 EmitT32_32(0xf9a00200U | (encoded_dt.GetEncodingValue() << 10) |
18987 (encoded_align_1.GetEncodingValue() << 4) |
18988 first.Encode(22, 12) | (rn.GetCode() << 16) |
18989 rm.GetCode());
18990 AdvanceIT();
18991 return;
18992 }
18993 }
18994 } else {
18995 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
18996 if (encoded_dt.IsValid() && nreglist.IsTransferAllLanes() &&
18997 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
18998 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000018999 sign.IsPlus() && operand.IsPostIndex() &&
19000 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019001 if (cond.Is(al)) {
19002 const DRegister& first = nreglist.GetFirstDRegister();
19003 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19004 EmitA32(0xf4a00e00U | (encoded_dt.GetEncodingValue() << 6) |
19005 first.Encode(22, 12) | (len_encoding << 5) |
19006 (rn.GetCode() << 16) | rm.GetCode());
19007 return;
19008 }
19009 }
19010 // VLD3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
19011 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
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)) {
19017 const DRegister& first = nreglist.GetFirstDRegister();
19018 EmitA32(0xf4a00200U | (encoded_dt.GetEncodingValue() << 10) |
19019 (encoded_align_1.GetEncodingValue() << 4) |
19020 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19021 return;
19022 }
19023 }
19024 }
19025 }
19026 Delegate(kVld3, &Assembler::vld3, cond, dt, nreglist, operand);
19027}
19028
19029void Assembler::vld4(Condition cond,
19030 DataType dt,
19031 const NeonRegisterList& nreglist,
19032 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019033 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019034 CheckIT(cond);
19035 if (operand.IsImmediateZero()) {
19036 Register rn = operand.GetBaseRegister();
19037 Alignment align = operand.GetAlignment();
19038 Dt_size_7 encoded_dt(dt);
19039 Dt_size_8 encoded_dt_2(dt, align);
19040 Align_align_4 encoded_align_1(align);
19041 Align_a_3 encoded_align_2(align, dt);
19042 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019043 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019044 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19045 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19046 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19047 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019048 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019049 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019050 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19051 const DRegister& first = nreglist.GetFirstDRegister();
19052 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19053 EmitT32_32(0xf920000fU | (encoded_dt.GetEncodingValue() << 6) |
19054 (encoded_align_1.GetEncodingValue() << 4) |
19055 first.Encode(22, 12) | (len_encoding << 8) |
19056 (rn.GetCode() << 16));
19057 AdvanceIT();
19058 return;
19059 }
19060 }
19061 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19062 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19063 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19064 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019065 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019066 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019067 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19068 const DRegister& first = nreglist.GetFirstDRegister();
19069 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19070 EmitT32_32(0xf920000dU | (encoded_dt.GetEncodingValue() << 6) |
19071 (encoded_align_1.GetEncodingValue() << 4) |
19072 first.Encode(22, 12) | (len_encoding << 8) |
19073 (rn.GetCode() << 16));
19074 AdvanceIT();
19075 return;
19076 }
19077 }
19078 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19079 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19080 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19081 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019082 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019083 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019084 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19085 const DRegister& first = nreglist.GetFirstDRegister();
19086 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19087 EmitT32_32(0xf9a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19088 (encoded_align_2.GetEncodingValue() << 4) |
19089 first.Encode(22, 12) | (len_encoding << 5) |
19090 (rn.GetCode() << 16));
19091 AdvanceIT();
19092 return;
19093 }
19094 }
19095 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19096 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19097 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19098 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019099 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019100 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019101 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19102 const DRegister& first = nreglist.GetFirstDRegister();
19103 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19104 EmitT32_32(0xf9a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19105 (encoded_align_2.GetEncodingValue() << 4) |
19106 first.Encode(22, 12) | (len_encoding << 5) |
19107 (rn.GetCode() << 16));
19108 AdvanceIT();
19109 return;
19110 }
19111 }
19112 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
19113 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19114 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19115 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019116 operand.IsOffset() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019117 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019118 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19119 const DRegister& first = nreglist.GetFirstDRegister();
19120 EmitT32_32(0xf9a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19121 (encoded_align_3.GetEncodingValue() << 4) |
19122 first.Encode(22, 12) | (rn.GetCode() << 16));
19123 AdvanceIT();
19124 return;
19125 }
19126 }
19127 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
19128 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19129 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19130 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019131 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019132 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019133 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19134 const DRegister& first = nreglist.GetFirstDRegister();
19135 EmitT32_32(0xf9a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19136 (encoded_align_3.GetEncodingValue() << 4) |
19137 first.Encode(22, 12) | (rn.GetCode() << 16));
19138 AdvanceIT();
19139 return;
19140 }
19141 }
19142 } else {
19143 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19144 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19145 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19146 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019147 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019148 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019149 if (cond.Is(al)) {
19150 const DRegister& first = nreglist.GetFirstDRegister();
19151 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19152 EmitA32(0xf420000fU | (encoded_dt.GetEncodingValue() << 6) |
19153 (encoded_align_1.GetEncodingValue() << 4) |
19154 first.Encode(22, 12) | (len_encoding << 8) |
19155 (rn.GetCode() << 16));
19156 return;
19157 }
19158 }
19159 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19160 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19161 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19162 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019163 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019164 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019165 if (cond.Is(al)) {
19166 const DRegister& first = nreglist.GetFirstDRegister();
19167 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19168 EmitA32(0xf420000dU | (encoded_dt.GetEncodingValue() << 6) |
19169 (encoded_align_1.GetEncodingValue() << 4) |
19170 first.Encode(22, 12) | (len_encoding << 8) |
19171 (rn.GetCode() << 16));
19172 return;
19173 }
19174 }
19175 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19176 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19177 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19178 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019179 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019180 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019181 if (cond.Is(al)) {
19182 const DRegister& first = nreglist.GetFirstDRegister();
19183 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19184 EmitA32(0xf4a00f0fU | (encoded_dt_2.GetEncodingValue() << 6) |
19185 (encoded_align_2.GetEncodingValue() << 4) |
19186 first.Encode(22, 12) | (len_encoding << 5) |
19187 (rn.GetCode() << 16));
19188 return;
19189 }
19190 }
19191 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19192 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19193 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19194 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019195 operand.IsPostIndex() && encoded_align_2.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(0xf4a00f0dU | (encoded_dt_2.GetEncodingValue() << 6) |
19201 (encoded_align_2.GetEncodingValue() << 4) |
19202 first.Encode(22, 12) | (len_encoding << 5) |
19203 (rn.GetCode() << 16));
19204 return;
19205 }
19206 }
19207 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
19208 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19209 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19210 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019211 operand.IsOffset() && encoded_align_3.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 EmitA32(0xf4a0030fU | (encoded_dt.GetEncodingValue() << 10) |
19216 (encoded_align_3.GetEncodingValue() << 4) |
19217 first.Encode(22, 12) | (rn.GetCode() << 16));
19218 return;
19219 }
19220 }
19221 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
19222 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19223 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19224 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019225 operand.IsPostIndex() && encoded_align_3.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019226 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019227 if (cond.Is(al)) {
19228 const DRegister& first = nreglist.GetFirstDRegister();
19229 EmitA32(0xf4a0030dU | (encoded_dt.GetEncodingValue() << 10) |
19230 (encoded_align_3.GetEncodingValue() << 4) |
19231 first.Encode(22, 12) | (rn.GetCode() << 16));
19232 return;
19233 }
19234 }
19235 }
19236 }
19237 if (operand.IsPlainRegister()) {
19238 Register rn = operand.GetBaseRegister();
19239 Alignment align = operand.GetAlignment();
19240 Register rm = operand.GetOffsetRegister();
19241 Dt_size_7 encoded_dt(dt);
19242 Dt_size_8 encoded_dt_2(dt, align);
19243 Align_align_4 encoded_align_1(align);
19244 Align_a_3 encoded_align_2(align, dt);
19245 Align_index_align_3 encoded_align_3(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019246 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019247 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19248 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
19249 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19250 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019251 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019252 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19253 const DRegister& first = nreglist.GetFirstDRegister();
19254 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19255 EmitT32_32(0xf9200000U | (encoded_dt.GetEncodingValue() << 6) |
19256 (encoded_align_1.GetEncodingValue() << 4) |
19257 first.Encode(22, 12) | (len_encoding << 8) |
19258 (rn.GetCode() << 16) | rm.GetCode());
19259 AdvanceIT();
19260 return;
19261 }
19262 }
19263 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19264 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19265 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19266 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019267 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019268 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19269 const DRegister& first = nreglist.GetFirstDRegister();
19270 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19271 EmitT32_32(0xf9a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19272 (encoded_align_2.GetEncodingValue() << 4) |
19273 first.Encode(22, 12) | (len_encoding << 5) |
19274 (rn.GetCode() << 16) | rm.GetCode());
19275 AdvanceIT();
19276 return;
19277 }
19278 }
19279 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
19280 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19281 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19282 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019283 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019284 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19285 const DRegister& first = nreglist.GetFirstDRegister();
19286 EmitT32_32(0xf9a00300U | (encoded_dt.GetEncodingValue() << 10) |
19287 (encoded_align_3.GetEncodingValue() << 4) |
19288 first.Encode(22, 12) | (rn.GetCode() << 16) |
19289 rm.GetCode());
19290 AdvanceIT();
19291 return;
19292 }
19293 }
19294 } else {
19295 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
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)) {
19301 const DRegister& first = nreglist.GetFirstDRegister();
19302 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19303 EmitA32(0xf4200000U | (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 return;
19308 }
19309 }
19310 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19311 if (encoded_dt_2.IsValid() && nreglist.IsTransferAllLanes() &&
19312 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19313 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019314 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019315 if (cond.Is(al)) {
19316 const DRegister& first = nreglist.GetFirstDRegister();
19317 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
19318 EmitA32(0xf4a00f00U | (encoded_dt_2.GetEncodingValue() << 6) |
19319 (encoded_align_2.GetEncodingValue() << 4) |
19320 first.Encode(22, 12) | (len_encoding << 5) |
19321 (rn.GetCode() << 16) | rm.GetCode());
19322 return;
19323 }
19324 }
19325 // VLD4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
19326 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
19327 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
19328 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000019329 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019330 if (cond.Is(al)) {
19331 const DRegister& first = nreglist.GetFirstDRegister();
19332 EmitA32(0xf4a00300U | (encoded_dt.GetEncodingValue() << 10) |
19333 (encoded_align_3.GetEncodingValue() << 4) |
19334 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
19335 return;
19336 }
19337 }
19338 }
19339 }
19340 Delegate(kVld4, &Assembler::vld4, cond, dt, nreglist, operand);
19341}
19342
19343void Assembler::vldm(Condition cond,
19344 DataType dt,
19345 Register rn,
19346 WriteBack write_back,
19347 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019348 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019349 CheckIT(cond);
19350 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019352 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080019353 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019354 const DRegister& dreg = dreglist.GetFirstDRegister();
19355 unsigned len = dreglist.GetLength() * 2;
19356 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19357 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19358 (len & 0xff));
19359 AdvanceIT();
19360 return;
19361 }
19362 } else {
19363 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
19364 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019365 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019366 const DRegister& dreg = dreglist.GetFirstDRegister();
19367 unsigned len = dreglist.GetLength() * 2;
19368 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19369 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19370 (len & 0xff));
19371 return;
19372 }
19373 }
19374 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, dreglist);
19375}
19376
19377void Assembler::vldm(Condition cond,
19378 DataType dt,
19379 Register rn,
19380 WriteBack write_back,
19381 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019382 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019383 CheckIT(cond);
19384 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019385 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019386 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
19387 const SRegister& sreg = sreglist.GetFirstSRegister();
19388 unsigned len = sreglist.GetLength();
19389 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19390 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19391 (len & 0xff));
19392 AdvanceIT();
19393 return;
19394 } else {
19395 // VLDM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
19396 if (cond.IsNotNever()) {
19397 const SRegister& sreg = sreglist.GetFirstSRegister();
19398 unsigned len = sreglist.GetLength();
19399 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19400 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19401 (len & 0xff));
19402 return;
19403 }
19404 }
19405 Delegate(kVldm, &Assembler::vldm, cond, dt, rn, write_back, sreglist);
19406}
19407
19408void Assembler::vldmdb(Condition cond,
19409 DataType dt,
19410 Register rn,
19411 WriteBack write_back,
19412 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019413 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019414 CheckIT(cond);
19415 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019416 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019417 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
19418 if (write_back.DoesWriteBack() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019419 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019420 const DRegister& dreg = dreglist.GetFirstDRegister();
19421 unsigned len = dreglist.GetLength() * 2;
19422 EmitT32_32(0xed300b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
19423 (len & 0xff));
19424 AdvanceIT();
19425 return;
19426 }
19427 } else {
19428 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
19429 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019430 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019431 const DRegister& dreg = dreglist.GetFirstDRegister();
19432 unsigned len = dreglist.GetLength() * 2;
19433 EmitA32(0x0d300b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19434 dreg.Encode(22, 12) | (len & 0xff));
19435 return;
19436 }
19437 }
19438 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, dreglist);
19439}
19440
19441void Assembler::vldmdb(Condition cond,
19442 DataType dt,
19443 Register rn,
19444 WriteBack write_back,
19445 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019446 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019447 CheckIT(cond);
19448 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019449 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019450 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
19451 if (write_back.DoesWriteBack()) {
19452 const SRegister& sreg = sreglist.GetFirstSRegister();
19453 unsigned len = sreglist.GetLength();
19454 EmitT32_32(0xed300a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
19455 (len & 0xff));
19456 AdvanceIT();
19457 return;
19458 }
19459 } else {
19460 // VLDMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
19461 if (write_back.DoesWriteBack() && cond.IsNotNever()) {
19462 const SRegister& sreg = sreglist.GetFirstSRegister();
19463 unsigned len = sreglist.GetLength();
19464 EmitA32(0x0d300a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19465 sreg.Encode(22, 12) | (len & 0xff));
19466 return;
19467 }
19468 }
19469 Delegate(kVldmdb, &Assembler::vldmdb, cond, dt, rn, write_back, sreglist);
19470}
19471
19472void Assembler::vldmia(Condition cond,
19473 DataType dt,
19474 Register rn,
19475 WriteBack write_back,
19476 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019477 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019478 CheckIT(cond);
19479 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019480 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019481 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080019482 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019483 const DRegister& dreg = dreglist.GetFirstDRegister();
19484 unsigned len = dreglist.GetLength() * 2;
19485 EmitT32_32(0xec900b00U | (rn.GetCode() << 16) |
19486 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19487 (len & 0xff));
19488 AdvanceIT();
19489 return;
19490 }
19491 } else {
19492 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
19493 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080019494 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019495 const DRegister& dreg = dreglist.GetFirstDRegister();
19496 unsigned len = dreglist.GetLength() * 2;
19497 EmitA32(0x0c900b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19498 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
19499 (len & 0xff));
19500 return;
19501 }
19502 }
19503 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, dreglist);
19504}
19505
19506void Assembler::vldmia(Condition cond,
19507 DataType dt,
19508 Register rn,
19509 WriteBack write_back,
19510 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019511 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019512 CheckIT(cond);
19513 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019514 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019515 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
19516 const SRegister& sreg = sreglist.GetFirstSRegister();
19517 unsigned len = sreglist.GetLength();
19518 EmitT32_32(0xec900a00U | (rn.GetCode() << 16) |
19519 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19520 (len & 0xff));
19521 AdvanceIT();
19522 return;
19523 } else {
19524 // VLDMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
19525 if (cond.IsNotNever()) {
19526 const SRegister& sreg = sreglist.GetFirstSRegister();
19527 unsigned len = sreglist.GetLength();
19528 EmitA32(0x0c900a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
19529 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
19530 (len & 0xff));
19531 return;
19532 }
19533 }
19534 Delegate(kVldmia, &Assembler::vldmia, cond, dt, rn, write_back, sreglist);
19535}
19536
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019537void Assembler::vldr(Condition cond,
19538 DataType dt,
19539 DRegister rd,
19540 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019541 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019542 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019543 Location::Offset offset =
19544 location->IsBound()
19545 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +010019546 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19547 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019548 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019549 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19550 if (dt.IsNoneOr(Untyped64) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019551 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019552 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019553 !location->IsBound())) {
19554 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019555 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019556 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019557 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019558 Location::Offset pc,
19559 const Location* location) const VIXL_OVERRIDE {
19560 pc += kT32PcDelta;
19561 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019562 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19563 ((offset & 0x3) == 0));
19564 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019565 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019566 target = abs(target) | (U << 8);
19567 return instr | (target & 0xff) | ((target & 0x100) << 15);
19568 }
19569 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -070019570 EmitT32_32(Link(0xed1f0b00U | rd.Encode(22, 12),
19571 location,
19572 immop,
19573 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019574 AdvanceIT();
19575 return;
19576 }
19577 } else {
19578 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19579 if (dt.IsNoneOr(Untyped64) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019580 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019581 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019582 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019583 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019584 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019585 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019586 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019587 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019588 Location::Offset pc,
19589 const Location* location) const VIXL_OVERRIDE {
19590 pc += kA32PcDelta;
19591 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019592 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19593 ((offset & 0x3) == 0));
19594 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019595 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019596 target = abs(target) | (U << 8);
19597 return instr | (target & 0xff) | ((target & 0x100) << 15);
19598 }
19599 } immop;
19600 EmitA32(
19601 Link(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019602 location,
19603 immop,
Vincent Belliardac285442017-05-16 09:26:45 -070019604 &kA32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019605 return;
19606 }
19607 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019608 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019609}
19610
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019611bool Assembler::vldr_info(Condition cond,
19612 DataType dt,
19613 DRegister rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019614 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019615 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019616 VIXL_ASSERT(!location->IsBound());
19617 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019618 USE(rd);
19619 if (IsUsingT32()) {
19620 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; T1
19621 if (dt.IsNoneOr(Untyped64)) {
Vincent Belliardac285442017-05-16 09:26:45 -070019622 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019623 return true;
19624 }
19625 } else {
19626 // VLDR{<c>}{<q>}{.64} <Dd>, <label> ; A1
19627 if (dt.IsNoneOr(Untyped64) && cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -070019628 *info = &kA32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019629 return true;
19630 }
19631 }
19632 return false;
19633}
19634
Alexandre Ramesd3832962016-07-04 15:03:43 +010019635void Assembler::vldr(Condition cond,
19636 DataType dt,
19637 DRegister rd,
19638 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019639 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019640 CheckIT(cond);
19641 if (operand.IsImmediate()) {
19642 Register rn = operand.GetBaseRegister();
19643 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019644 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019645 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; T1
19646 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019647 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019648 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19649 uint32_t offset_ = abs(offset) >> 2;
19650 EmitT32_32(0xed1f0b00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19651 AdvanceIT();
19652 return;
19653 }
19654 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
19655 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019656 ((offset % 4) == 0) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019657 ((rn.GetCode() & 0xf) != 0xf)) {
19658 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19659 uint32_t offset_ = abs(offset) >> 2;
19660 EmitT32_32(0xed100b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19661 offset_ | (sign << 23));
19662 AdvanceIT();
19663 return;
19664 }
19665 } else {
19666 // VLDR{<c>}{<q>}{.64} <Dd>, [PC, #<_plusminus_><imm>] ; A1
19667 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019668 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19669 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019670 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19671 uint32_t offset_ = abs(offset) >> 2;
19672 EmitA32(0x0d1f0b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19673 offset_ | (sign << 23));
19674 return;
19675 }
19676 // VLDR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
19677 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019678 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19679 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019680 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19681 uint32_t offset_ = abs(offset) >> 2;
19682 EmitA32(0x0d100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19683 (rn.GetCode() << 16) | offset_ | (sign << 23));
19684 return;
19685 }
19686 }
19687 }
19688 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19689}
19690
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019691void Assembler::vldr(Condition cond,
19692 DataType dt,
19693 SRegister rd,
19694 Location* location) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019695 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019696 CheckIT(cond);
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019697 Location::Offset offset =
19698 location->IsBound()
19699 ? location->GetLocation() -
Alexandre Ramesd3832962016-07-04 15:03:43 +010019700 AlignDown(GetCursorOffset() + GetArchitectureStatePCOffset(), 4)
19701 : 0;
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019702 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019703 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19704 if (dt.IsNoneOr(Untyped32) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019705 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019706 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019707 !location->IsBound())) {
19708 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019709 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019710 EmitOp() : Location::EmitOperator(T32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019711 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019712 Location::Offset pc,
19713 const Location* location) const VIXL_OVERRIDE {
19714 pc += kT32PcDelta;
19715 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019716 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19717 ((offset & 0x3) == 0));
19718 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019719 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019720 target = abs(target) | (U << 8);
19721 return instr | (target & 0xff) | ((target & 0x100) << 15);
19722 }
19723 } immop;
Vincent Belliardac285442017-05-16 09:26:45 -070019724 EmitT32_32(Link(0xed1f0a00U | rd.Encode(22, 12),
19725 location,
19726 immop,
19727 &kT32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019728 AdvanceIT();
19729 return;
19730 }
19731 } else {
19732 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19733 if (dt.IsNoneOr(Untyped32) &&
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019734 ((location->IsBound() && (offset >= -1020) && (offset <= 1020) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019735 ((offset & 0x3) == 0)) ||
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019736 !location->IsBound()) &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019737 cond.IsNotNever()) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019738 static class EmitOp : public Location::EmitOperator {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019739 public:
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019740 EmitOp() : Location::EmitOperator(A32) {}
Pierre Langlois3fac43c2016-10-31 13:38:47 +000019741 virtual uint32_t Encode(uint32_t instr,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019742 Location::Offset pc,
19743 const Location* location) const VIXL_OVERRIDE {
19744 pc += kA32PcDelta;
19745 Location::Offset offset = location->GetLocation() - AlignDown(pc, 4);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019746 VIXL_ASSERT((offset >= -1020) && (offset <= 1020) &&
19747 ((offset & 0x3) == 0));
19748 int32_t target = offset >> 2;
Georgia Kouvelifc61fb62017-01-12 13:40:38 +000019749 uint32_t U = (target >= 0);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019750 target = abs(target) | (U << 8);
19751 return instr | (target & 0xff) | ((target & 0x100) << 15);
19752 }
19753 } immop;
19754 EmitA32(
19755 Link(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12),
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019756 location,
19757 immop,
Vincent Belliardac285442017-05-16 09:26:45 -070019758 &kA32DataInfo));
Alexandre Ramesd3832962016-07-04 15:03:43 +010019759 return;
19760 }
19761 }
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019762 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, location);
Alexandre Ramesd3832962016-07-04 15:03:43 +010019763}
19764
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019765bool Assembler::vldr_info(Condition cond,
19766 DataType dt,
19767 SRegister rd,
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019768 Location* location,
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019769 const struct ReferenceInfo** info) {
Georgia Kouveli275c9d42017-05-12 18:07:45 +010019770 VIXL_ASSERT(!location->IsBound());
19771 USE(location);
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019772 USE(rd);
19773 if (IsUsingT32()) {
19774 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; T2
19775 if (dt.IsNoneOr(Untyped32)) {
Vincent Belliardac285442017-05-16 09:26:45 -070019776 *info = &kT32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019777 return true;
19778 }
19779 } else {
19780 // VLDR{<c>}{<q>}{.32} <Sd>, <label> ; A2
19781 if (dt.IsNoneOr(Untyped32) && cond.IsNotNever()) {
Vincent Belliardac285442017-05-16 09:26:45 -070019782 *info = &kA32DataInfo;
Georgia Kouveli4b139a22017-03-31 16:11:11 +010019783 return true;
19784 }
19785 }
19786 return false;
19787}
19788
Alexandre Ramesd3832962016-07-04 15:03:43 +010019789void Assembler::vldr(Condition cond,
19790 DataType dt,
19791 SRegister rd,
19792 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019793 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019794 CheckIT(cond);
19795 if (operand.IsImmediate()) {
19796 Register rn = operand.GetBaseRegister();
19797 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019798 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019799 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; T2
19800 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019801 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019802 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19803 uint32_t offset_ = abs(offset) >> 2;
19804 EmitT32_32(0xed1f0a00U | rd.Encode(22, 12) | offset_ | (sign << 23));
19805 AdvanceIT();
19806 return;
19807 }
19808 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
19809 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019810 ((offset % 4) == 0) && operand.IsOffset() &&
Alexandre Ramesd3832962016-07-04 15:03:43 +010019811 ((rn.GetCode() & 0xf) != 0xf)) {
19812 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19813 uint32_t offset_ = abs(offset) >> 2;
19814 EmitT32_32(0xed100a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
19815 offset_ | (sign << 23));
19816 AdvanceIT();
19817 return;
19818 }
19819 } else {
19820 // VLDR{<c>}{<q>}{.32} <Sd>, [PC, #<_plusminus_><imm>] ; A2
19821 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019822 ((offset % 4) == 0) && rn.Is(pc) && operand.IsOffset() &&
19823 cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019824 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19825 uint32_t offset_ = abs(offset) >> 2;
19826 EmitA32(0x0d1f0a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19827 offset_ | (sign << 23));
19828 return;
19829 }
19830 // VLDR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
19831 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080019832 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever() &&
19833 ((rn.GetCode() & 0xf) != 0xf)) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019834 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
19835 uint32_t offset_ = abs(offset) >> 2;
19836 EmitA32(0x0d100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
19837 (rn.GetCode() << 16) | offset_ | (sign << 23));
19838 return;
19839 }
19840 }
19841 }
19842 Delegate(kVldr, &Assembler::vldr, cond, dt, rd, operand);
19843}
19844
19845void Assembler::vmax(
19846 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019847 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019848 CheckIT(cond);
19849 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019850 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019851 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
19852 if (dt.Is(F32)) {
19853 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19854 EmitT32_32(0xef000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19855 rm.Encode(5, 0));
19856 AdvanceIT();
19857 return;
19858 }
19859 }
19860 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
19861 if (encoded_dt.IsValid()) {
19862 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19863 EmitT32_32(0xef000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19864 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19865 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19866 AdvanceIT();
19867 return;
19868 }
19869 }
19870 } else {
19871 // VMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
19872 if (dt.Is(F32)) {
19873 if (cond.Is(al)) {
19874 EmitA32(0xf2000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19875 rm.Encode(5, 0));
19876 return;
19877 }
19878 }
19879 // VMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
19880 if (encoded_dt.IsValid()) {
19881 if (cond.Is(al)) {
19882 EmitA32(0xf2000600U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19883 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19884 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19885 return;
19886 }
19887 }
19888 }
19889 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19890}
19891
19892void Assembler::vmax(
19893 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019894 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019895 CheckIT(cond);
19896 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019897 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019898 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
19899 if (dt.Is(F32)) {
19900 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19901 EmitT32_32(0xef000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19902 rm.Encode(5, 0));
19903 AdvanceIT();
19904 return;
19905 }
19906 }
19907 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
19908 if (encoded_dt.IsValid()) {
19909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
19910 EmitT32_32(0xef000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19911 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
19912 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19913 AdvanceIT();
19914 return;
19915 }
19916 }
19917 } else {
19918 // VMAX{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
19919 if (dt.Is(F32)) {
19920 if (cond.Is(al)) {
19921 EmitA32(0xf2000f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19922 rm.Encode(5, 0));
19923 return;
19924 }
19925 }
19926 // VMAX{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
19927 if (encoded_dt.IsValid()) {
19928 if (cond.Is(al)) {
19929 EmitA32(0xf2000640U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
19930 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
19931 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
19932 return;
19933 }
19934 }
19935 }
19936 Delegate(kVmax, &Assembler::vmax, cond, dt, rd, rn, rm);
19937}
19938
19939void Assembler::vmaxnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019940 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019941 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019942 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019943 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
19944 if (OutsideITBlock() && dt.Is(F32)) {
19945 EmitT32_32(0xff000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19946 rm.Encode(5, 0));
19947 AdvanceIT();
19948 return;
19949 }
19950 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
19951 if (OutsideITBlock() && dt.Is(F64)) {
19952 EmitT32_32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19953 rm.Encode(5, 0));
19954 AdvanceIT();
19955 return;
19956 }
19957 } else {
19958 // VMAXNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
19959 if (dt.Is(F32)) {
19960 EmitA32(0xf3000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19961 rm.Encode(5, 0));
19962 return;
19963 }
19964 // VMAXNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
19965 if (dt.Is(F64)) {
19966 EmitA32(0xfe800b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19967 rm.Encode(5, 0));
19968 return;
19969 }
19970 }
19971 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
19972}
19973
19974void Assembler::vmaxnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019975 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019976 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019977 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010019978 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
19979 if (OutsideITBlock() && dt.Is(F32)) {
19980 EmitT32_32(0xff000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19981 rm.Encode(5, 0));
19982 AdvanceIT();
19983 return;
19984 }
19985 } else {
19986 // VMAXNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
19987 if (dt.Is(F32)) {
19988 EmitA32(0xf3000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
19989 rm.Encode(5, 0));
19990 return;
19991 }
19992 }
19993 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
19994}
19995
19996void Assembler::vmaxnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070019997 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010019998 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010019999 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020000 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20001 if (OutsideITBlock() && dt.Is(F32)) {
20002 EmitT32_32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20003 rm.Encode(5, 0));
20004 AdvanceIT();
20005 return;
20006 }
20007 } else {
20008 // VMAXNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20009 if (dt.Is(F32)) {
20010 EmitA32(0xfe800a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20011 rm.Encode(5, 0));
20012 return;
20013 }
20014 }
20015 Delegate(kVmaxnm, &Assembler::vmaxnm, dt, rd, rn, rm);
20016}
20017
20018void Assembler::vmin(
20019 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020020 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020021 CheckIT(cond);
20022 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020023 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020024 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
20025 if (dt.Is(F32)) {
20026 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20027 EmitT32_32(0xef200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20028 rm.Encode(5, 0));
20029 AdvanceIT();
20030 return;
20031 }
20032 }
20033 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
20034 if (encoded_dt.IsValid()) {
20035 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20036 EmitT32_32(0xef000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20037 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20038 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20039 AdvanceIT();
20040 return;
20041 }
20042 }
20043 } else {
20044 // VMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
20045 if (dt.Is(F32)) {
20046 if (cond.Is(al)) {
20047 EmitA32(0xf2200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20048 rm.Encode(5, 0));
20049 return;
20050 }
20051 }
20052 // VMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
20053 if (encoded_dt.IsValid()) {
20054 if (cond.Is(al)) {
20055 EmitA32(0xf2000610U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20056 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20057 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20058 return;
20059 }
20060 }
20061 }
20062 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20063}
20064
20065void Assembler::vmin(
20066 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020067 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020068 CheckIT(cond);
20069 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020070 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020071 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
20072 if (dt.Is(F32)) {
20073 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20074 EmitT32_32(0xef200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20075 rm.Encode(5, 0));
20076 AdvanceIT();
20077 return;
20078 }
20079 }
20080 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
20081 if (encoded_dt.IsValid()) {
20082 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20083 EmitT32_32(0xef000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20084 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
20085 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20086 AdvanceIT();
20087 return;
20088 }
20089 }
20090 } else {
20091 // VMIN{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
20092 if (dt.Is(F32)) {
20093 if (cond.Is(al)) {
20094 EmitA32(0xf2200f40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20095 rm.Encode(5, 0));
20096 return;
20097 }
20098 }
20099 // VMIN{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
20100 if (encoded_dt.IsValid()) {
20101 if (cond.Is(al)) {
20102 EmitA32(0xf2000650U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
20103 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
20104 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20105 return;
20106 }
20107 }
20108 }
20109 Delegate(kVmin, &Assembler::vmin, cond, dt, rd, rn, rm);
20110}
20111
20112void Assembler::vminnm(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020113 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020114 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020115 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020116 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20117 if (OutsideITBlock() && dt.Is(F32)) {
20118 EmitT32_32(0xff200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20119 rm.Encode(5, 0));
20120 AdvanceIT();
20121 return;
20122 }
20123 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20124 if (OutsideITBlock() && dt.Is(F64)) {
20125 EmitT32_32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20126 rm.Encode(5, 0));
20127 AdvanceIT();
20128 return;
20129 }
20130 } else {
20131 // VMINNM{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20132 if (dt.Is(F32)) {
20133 EmitA32(0xf3200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20134 rm.Encode(5, 0));
20135 return;
20136 }
20137 // VMINNM{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20138 if (dt.Is(F64)) {
20139 EmitA32(0xfe800b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20140 rm.Encode(5, 0));
20141 return;
20142 }
20143 }
20144 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20145}
20146
20147void Assembler::vminnm(DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020148 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020149 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020150 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020151 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20152 if (OutsideITBlock() && dt.Is(F32)) {
20153 EmitT32_32(0xff200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20154 rm.Encode(5, 0));
20155 AdvanceIT();
20156 return;
20157 }
20158 } else {
20159 // VMINNM{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20160 if (dt.Is(F32)) {
20161 EmitA32(0xf3200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20162 rm.Encode(5, 0));
20163 return;
20164 }
20165 }
20166 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20167}
20168
20169void Assembler::vminnm(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020170 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020171 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020172 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020173 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20174 if (OutsideITBlock() && dt.Is(F32)) {
20175 EmitT32_32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20176 rm.Encode(5, 0));
20177 AdvanceIT();
20178 return;
20179 }
20180 } else {
20181 // VMINNM{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20182 if (dt.Is(F32)) {
20183 EmitA32(0xfe800a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20184 rm.Encode(5, 0));
20185 return;
20186 }
20187 }
20188 Delegate(kVminnm, &Assembler::vminnm, dt, rd, rn, rm);
20189}
20190
20191void Assembler::vmla(
20192 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020193 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020194 CheckIT(cond);
20195 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020196 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020197 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20198 if (encoded_dt.IsValid() &&
20199 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20200 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20201 (rm.GetLane() <= 1)))) {
20202 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20203 EmitT32_32(0xef800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20204 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20205 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20206 AdvanceIT();
20207 return;
20208 }
20209 }
20210 } else {
20211 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20212 if (encoded_dt.IsValid() &&
20213 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20214 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20215 (rm.GetLane() <= 1)))) {
20216 if (cond.Is(al)) {
20217 EmitA32(0xf2800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20218 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20219 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20220 return;
20221 }
20222 }
20223 }
20224 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20225}
20226
20227void Assembler::vmla(
20228 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020229 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020230 CheckIT(cond);
20231 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020232 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020233 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20234 if (encoded_dt.IsValid() &&
20235 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20236 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20237 (rm.GetLane() <= 1)))) {
20238 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20239 EmitT32_32(0xff800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20240 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20241 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20242 AdvanceIT();
20243 return;
20244 }
20245 }
20246 } else {
20247 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20248 if (encoded_dt.IsValid() &&
20249 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20250 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20251 (rm.GetLane() <= 1)))) {
20252 if (cond.Is(al)) {
20253 EmitA32(0xf3800040U | (encoded_dt.GetTypeEncodingValue() << 8) |
20254 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20255 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20256 return;
20257 }
20258 }
20259 }
20260 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20261}
20262
20263void Assembler::vmla(
20264 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020265 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020266 CheckIT(cond);
20267 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020268 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020269 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20270 if (dt.Is(F32)) {
20271 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20272 EmitT32_32(0xef000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20273 rm.Encode(5, 0));
20274 AdvanceIT();
20275 return;
20276 }
20277 }
20278 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20279 if (dt.Is(F64)) {
20280 EmitT32_32(0xee000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20281 rm.Encode(5, 0));
20282 AdvanceIT();
20283 return;
20284 }
20285 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20286 if (encoded_dt.IsValid()) {
20287 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20288 EmitT32_32(0xef000900U | (encoded_dt.GetEncodingValue() << 20) |
20289 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20290 AdvanceIT();
20291 return;
20292 }
20293 }
20294 } else {
20295 // VMLA{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20296 if (dt.Is(F32)) {
20297 if (cond.Is(al)) {
20298 EmitA32(0xf2000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20299 rm.Encode(5, 0));
20300 return;
20301 }
20302 }
20303 // VMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20304 if (dt.Is(F64) && cond.IsNotNever()) {
20305 EmitA32(0x0e000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20306 rn.Encode(7, 16) | rm.Encode(5, 0));
20307 return;
20308 }
20309 // VMLA{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20310 if (encoded_dt.IsValid()) {
20311 if (cond.Is(al)) {
20312 EmitA32(0xf2000900U | (encoded_dt.GetEncodingValue() << 20) |
20313 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20314 return;
20315 }
20316 }
20317 }
20318 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20319}
20320
20321void Assembler::vmla(
20322 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020323 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020324 CheckIT(cond);
20325 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020326 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020327 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20328 if (dt.Is(F32)) {
20329 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20330 EmitT32_32(0xef000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20331 rm.Encode(5, 0));
20332 AdvanceIT();
20333 return;
20334 }
20335 }
20336 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20337 if (encoded_dt.IsValid()) {
20338 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20339 EmitT32_32(0xef000940U | (encoded_dt.GetEncodingValue() << 20) |
20340 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20341 AdvanceIT();
20342 return;
20343 }
20344 }
20345 } else {
20346 // VMLA{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20347 if (dt.Is(F32)) {
20348 if (cond.Is(al)) {
20349 EmitA32(0xf2000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20350 rm.Encode(5, 0));
20351 return;
20352 }
20353 }
20354 // VMLA{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20355 if (encoded_dt.IsValid()) {
20356 if (cond.Is(al)) {
20357 EmitA32(0xf2000940U | (encoded_dt.GetEncodingValue() << 20) |
20358 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20359 return;
20360 }
20361 }
20362 }
20363 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20364}
20365
20366void Assembler::vmla(
20367 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020368 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020369 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020370 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020371 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20372 if (dt.Is(F32)) {
20373 EmitT32_32(0xee000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20374 rm.Encode(5, 0));
20375 AdvanceIT();
20376 return;
20377 }
20378 } else {
20379 // VMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20380 if (dt.Is(F32) && cond.IsNotNever()) {
20381 EmitA32(0x0e000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20382 rn.Encode(7, 16) | rm.Encode(5, 0));
20383 return;
20384 }
20385 }
20386 Delegate(kVmla, &Assembler::vmla, cond, dt, rd, rn, rm);
20387}
20388
20389void Assembler::vmlal(
20390 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020391 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020392 CheckIT(cond);
20393 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020394 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020395 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20396 if (encoded_dt.IsValid() &&
20397 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20398 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20399 (rm.GetLane() <= 1)))) {
20400 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20401 EmitT32_32(0xef800240U | (encoded_dt.GetTypeEncodingValue() << 28) |
20402 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20403 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20404 AdvanceIT();
20405 return;
20406 }
20407 }
20408 } else {
20409 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20410 if (encoded_dt.IsValid() &&
20411 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20412 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20413 (rm.GetLane() <= 1)))) {
20414 if (cond.Is(al)) {
20415 EmitA32(0xf2800240U | (encoded_dt.GetTypeEncodingValue() << 24) |
20416 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20417 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20418 return;
20419 }
20420 }
20421 }
20422 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20423}
20424
20425void Assembler::vmlal(
20426 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020427 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020428 CheckIT(cond);
20429 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020430 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020431 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20432 if (encoded_dt.IsValid()) {
20433 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20434 EmitT32_32(0xef800800U | (encoded_dt.GetTypeEncodingValue() << 28) |
20435 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20436 rn.Encode(7, 16) | rm.Encode(5, 0));
20437 AdvanceIT();
20438 return;
20439 }
20440 }
20441 } else {
20442 // VMLAL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20443 if (encoded_dt.IsValid()) {
20444 if (cond.Is(al)) {
20445 EmitA32(0xf2800800U | (encoded_dt.GetTypeEncodingValue() << 24) |
20446 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20447 rn.Encode(7, 16) | rm.Encode(5, 0));
20448 return;
20449 }
20450 }
20451 }
20452 Delegate(kVmlal, &Assembler::vmlal, cond, dt, rd, rn, rm);
20453}
20454
20455void Assembler::vmls(
20456 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020457 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020458 CheckIT(cond);
20459 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020460 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020461 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; T1
20462 if (encoded_dt.IsValid() &&
20463 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20464 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20465 (rm.GetLane() <= 1)))) {
20466 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20467 EmitT32_32(0xef800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20468 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20469 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20470 AdvanceIT();
20471 return;
20472 }
20473 }
20474 } else {
20475 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm[x]> ; A1
20476 if (encoded_dt.IsValid() &&
20477 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20478 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20479 (rm.GetLane() <= 1)))) {
20480 if (cond.Is(al)) {
20481 EmitA32(0xf2800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20482 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20483 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20484 return;
20485 }
20486 }
20487 }
20488 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20489}
20490
20491void Assembler::vmls(
20492 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020493 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020494 CheckIT(cond);
20495 Dt_size_9 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020496 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020497 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; T1
20498 if (encoded_dt.IsValid() &&
20499 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20500 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20501 (rm.GetLane() <= 1)))) {
20502 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20503 EmitT32_32(0xff800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20504 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20505 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20506 AdvanceIT();
20507 return;
20508 }
20509 }
20510 } else {
20511 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Dm[x]> ; A1
20512 if (encoded_dt.IsValid() &&
20513 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20514 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20515 (rm.GetLane() <= 1)))) {
20516 if (cond.Is(al)) {
20517 EmitA32(0xf3800440U | (encoded_dt.GetTypeEncodingValue() << 8) |
20518 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20519 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20520 return;
20521 }
20522 }
20523 }
20524 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20525}
20526
20527void Assembler::vmls(
20528 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020529 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020530 CheckIT(cond);
20531 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020532 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020533 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; T1
20534 if (dt.Is(F32)) {
20535 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20536 EmitT32_32(0xef200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20537 rm.Encode(5, 0));
20538 AdvanceIT();
20539 return;
20540 }
20541 }
20542 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T2
20543 if (dt.Is(F64)) {
20544 EmitT32_32(0xee000b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20545 rm.Encode(5, 0));
20546 AdvanceIT();
20547 return;
20548 }
20549 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; T1
20550 if (encoded_dt.IsValid()) {
20551 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20552 EmitT32_32(0xff000900U | (encoded_dt.GetEncodingValue() << 20) |
20553 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20554 AdvanceIT();
20555 return;
20556 }
20557 }
20558 } else {
20559 // VMLS{<c>}{<q>}.F32 <Dd>, <Dn>, <Dm> ; A1
20560 if (dt.Is(F32)) {
20561 if (cond.Is(al)) {
20562 EmitA32(0xf2200d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20563 rm.Encode(5, 0));
20564 return;
20565 }
20566 }
20567 // VMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A2
20568 if (dt.Is(F64) && cond.IsNotNever()) {
20569 EmitA32(0x0e000b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20570 rn.Encode(7, 16) | rm.Encode(5, 0));
20571 return;
20572 }
20573 // VMLS{<c>}{<q>}.<type><size> <Dd>, <Dn>, <Dm> ; A1
20574 if (encoded_dt.IsValid()) {
20575 if (cond.Is(al)) {
20576 EmitA32(0xf3000900U | (encoded_dt.GetEncodingValue() << 20) |
20577 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20578 return;
20579 }
20580 }
20581 }
20582 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20583}
20584
20585void Assembler::vmls(
20586 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020587 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020588 CheckIT(cond);
20589 Dt_size_10 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020590 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020591 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; T1
20592 if (dt.Is(F32)) {
20593 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20594 EmitT32_32(0xef200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20595 rm.Encode(5, 0));
20596 AdvanceIT();
20597 return;
20598 }
20599 }
20600 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; T1
20601 if (encoded_dt.IsValid()) {
20602 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20603 EmitT32_32(0xff000940U | (encoded_dt.GetEncodingValue() << 20) |
20604 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20605 AdvanceIT();
20606 return;
20607 }
20608 }
20609 } else {
20610 // VMLS{<c>}{<q>}.F32 <Qd>, <Qn>, <Qm> ; A1
20611 if (dt.Is(F32)) {
20612 if (cond.Is(al)) {
20613 EmitA32(0xf2200d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20614 rm.Encode(5, 0));
20615 return;
20616 }
20617 }
20618 // VMLS{<c>}{<q>}.<type><size> <Qd>, <Qn>, <Qm> ; A1
20619 if (encoded_dt.IsValid()) {
20620 if (cond.Is(al)) {
20621 EmitA32(0xf3000940U | (encoded_dt.GetEncodingValue() << 20) |
20622 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
20623 return;
20624 }
20625 }
20626 }
20627 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20628}
20629
20630void Assembler::vmls(
20631 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020632 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020633 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020634 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020635 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T2
20636 if (dt.Is(F32)) {
20637 EmitT32_32(0xee000a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
20638 rm.Encode(5, 0));
20639 AdvanceIT();
20640 return;
20641 }
20642 } else {
20643 // VMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A2
20644 if (dt.Is(F32) && cond.IsNotNever()) {
20645 EmitA32(0x0e000a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20646 rn.Encode(7, 16) | rm.Encode(5, 0));
20647 return;
20648 }
20649 }
20650 Delegate(kVmls, &Assembler::vmls, cond, dt, rd, rn, rm);
20651}
20652
20653void Assembler::vmlsl(
20654 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020655 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020656 CheckIT(cond);
20657 Dt_size_11 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020658 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020659 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; T1
20660 if (encoded_dt.IsValid() &&
20661 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20662 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20663 (rm.GetLane() <= 1)))) {
20664 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20665 EmitT32_32(0xef800640U | (encoded_dt.GetTypeEncodingValue() << 28) |
20666 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20667 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20668 AdvanceIT();
20669 return;
20670 }
20671 }
20672 } else {
20673 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm[x]> ; A1
20674 if (encoded_dt.IsValid() &&
20675 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
20676 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
20677 (rm.GetLane() <= 1)))) {
20678 if (cond.Is(al)) {
20679 EmitA32(0xf2800640U | (encoded_dt.GetTypeEncodingValue() << 24) |
20680 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20681 rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
20682 return;
20683 }
20684 }
20685 }
20686 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20687}
20688
20689void Assembler::vmlsl(
20690 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020691 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020692 CheckIT(cond);
20693 Dt_size_12 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020694 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020695 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; T1
20696 if (encoded_dt.IsValid()) {
20697 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20698 EmitT32_32(0xef800a00U | (encoded_dt.GetTypeEncodingValue() << 28) |
20699 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20700 rn.Encode(7, 16) | rm.Encode(5, 0));
20701 AdvanceIT();
20702 return;
20703 }
20704 }
20705 } else {
20706 // VMLSL{<c>}{<q>}.<type><size> <Qd>, <Dn>, <Dm> ; A1
20707 if (encoded_dt.IsValid()) {
20708 if (cond.Is(al)) {
20709 EmitA32(0xf2800a00U | (encoded_dt.GetTypeEncodingValue() << 24) |
20710 (encoded_dt.GetEncodingValue() << 20) | rd.Encode(22, 12) |
20711 rn.Encode(7, 16) | rm.Encode(5, 0));
20712 return;
20713 }
20714 }
20715 }
20716 Delegate(kVmlsl, &Assembler::vmlsl, cond, dt, rd, rn, rm);
20717}
20718
20719void Assembler::vmov(Condition cond, Register rt, SRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020720 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020721 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020722 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020723 // VMOV{<c>}{<q>} <Rt>, <Sn> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020724 if ((!rt.IsPC() || AllowUnpredictable())) {
20725 EmitT32_32(0xee100a10U | (rt.GetCode() << 12) | rn.Encode(7, 16));
20726 AdvanceIT();
20727 return;
20728 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020729 } else {
20730 // VMOV{<c>}{<q>} <Rt>, <Sn> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020731 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020732 EmitA32(0x0e100a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20733 rn.Encode(7, 16));
20734 return;
20735 }
20736 }
20737 Delegate(kVmov, &Assembler::vmov, cond, rt, rn);
20738}
20739
20740void Assembler::vmov(Condition cond, SRegister rn, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020741 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020742 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020743 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020744 // VMOV{<c>}{<q>} <Sn>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020745 if ((!rt.IsPC() || AllowUnpredictable())) {
20746 EmitT32_32(0xee000a10U | rn.Encode(7, 16) | (rt.GetCode() << 12));
20747 AdvanceIT();
20748 return;
20749 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020750 } else {
20751 // VMOV{<c>}{<q>} <Sn>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020752 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020753 EmitA32(0x0e000a10U | (cond.GetCondition() << 28) | rn.Encode(7, 16) |
20754 (rt.GetCode() << 12));
20755 return;
20756 }
20757 }
20758 Delegate(kVmov, &Assembler::vmov, cond, rn, rt);
20759}
20760
20761void Assembler::vmov(Condition cond, Register rt, Register rt2, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020762 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020763 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020764 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020765 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020766 if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20767 EmitT32_32(0xec500b10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20768 rm.Encode(5, 0));
20769 AdvanceIT();
20770 return;
20771 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020772 } else {
20773 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Dm> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020774 if (cond.IsNotNever() &&
20775 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020776 EmitA32(0x0c500b10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20777 (rt2.GetCode() << 16) | rm.Encode(5, 0));
20778 return;
20779 }
20780 }
20781 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm);
20782}
20783
20784void Assembler::vmov(Condition cond, DRegister rm, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020785 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020786 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020787 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020788 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020789 if (((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
20790 EmitT32_32(0xec400b10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20791 (rt2.GetCode() << 16));
20792 AdvanceIT();
20793 return;
20794 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020795 } else {
20796 // VMOV{<c>}{<q>} <Dm>, <Rt>, <Rt2> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020797 if (cond.IsNotNever() &&
20798 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020799 EmitA32(0x0c400b10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20800 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20801 return;
20802 }
20803 }
20804 Delegate(kVmov, &Assembler::vmov, cond, rm, rt, rt2);
20805}
20806
20807void Assembler::vmov(
20808 Condition cond, Register rt, Register rt2, SRegister rm, SRegister rm1) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020809 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020810 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020811 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020812 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020813 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20814 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020815 EmitT32_32(0xec500a10U | (rt.GetCode() << 12) | (rt2.GetCode() << 16) |
20816 rm.Encode(5, 0));
20817 AdvanceIT();
20818 return;
20819 }
20820 } else {
20821 // VMOV{<c>}{<q>} <Rt>, <Rt2>, <Sm>, <Sm1> ; A1
20822 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000020823 cond.IsNotNever() &&
20824 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020825 EmitA32(0x0c500a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
20826 (rt2.GetCode() << 16) | rm.Encode(5, 0));
20827 return;
20828 }
20829 }
20830 Delegate(kVmov, &Assembler::vmov, cond, rt, rt2, rm, rm1);
20831}
20832
20833void Assembler::vmov(
20834 Condition cond, SRegister rm, SRegister rm1, Register rt, Register rt2) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020835 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020836 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020837 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020838 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020839 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
20840 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020841 EmitT32_32(0xec400a10U | rm.Encode(5, 0) | (rt.GetCode() << 12) |
20842 (rt2.GetCode() << 16));
20843 AdvanceIT();
20844 return;
20845 }
20846 } else {
20847 // VMOV{<c>}{<q>} <Sm>, <Sm1>, <Rt>, <Rt2> ; A1
20848 if ((((rm.GetCode() + 1) % kNumberOfSRegisters) == rm1.GetCode()) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000020849 cond.IsNotNever() &&
20850 ((!rt.IsPC() && !rt2.IsPC()) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020851 EmitA32(0x0c400a10U | (cond.GetCondition() << 28) | rm.Encode(5, 0) |
20852 (rt.GetCode() << 12) | (rt2.GetCode() << 16));
20853 return;
20854 }
20855 }
20856 Delegate(kVmov, &Assembler::vmov, cond, rm, rm1, rt, rt2);
20857}
20858
20859void Assembler::vmov(Condition cond,
20860 DataType dt,
20861 DRegisterLane rd,
20862 Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020863 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020864 CheckIT(cond);
20865 Dt_opc1_opc2_1 encoded_dt(dt, rd);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020866 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020867 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020868 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020869 EmitT32_32(0xee000b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20870 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
20871 rd.Encode(7, 16) | (rt.GetCode() << 12));
20872 AdvanceIT();
20873 return;
20874 }
20875 } else {
20876 // VMOV{<c>}{<q>}{.<size>} <Dd[x]>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000020877 if (encoded_dt.IsValid() && cond.IsNotNever() &&
20878 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020879 EmitA32(0x0e000b10U | (cond.GetCondition() << 28) |
20880 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
20881 ((encoded_dt.GetEncodingValue() & 0xc) << 19) | rd.Encode(7, 16) |
20882 (rt.GetCode() << 12));
20883 return;
20884 }
20885 }
20886 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, rt);
20887}
20888
20889void Assembler::vmov(Condition cond,
20890 DataType dt,
20891 DRegister rd,
20892 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020893 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020894 CheckIT(cond);
20895 if (operand.IsImmediate()) {
20896 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020897 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020898 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
20899 if (encoded_dt.IsValid()) {
20900 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20901 EmitT32_32(
20902 0xef800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20903 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20904 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20905 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20906 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
20907 AdvanceIT();
20908 return;
20909 }
20910 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010020911 } else {
20912 // VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
20913 if (encoded_dt.IsValid()) {
20914 if (cond.Is(al)) {
20915 EmitA32(0xf2800010U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20916 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20917 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
20918 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
20919 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
20920 return;
20921 }
20922 }
Vincent Belliard07f9e742017-04-21 13:10:07 -070020923 }
20924 }
20925 if (operand.IsImmediate()) {
20926 ImmediateVFP vfp(operand.GetNeonImmediate());
20927 if (IsUsingT32()) {
20928 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
20929 if (dt.Is(F64) && vfp.IsValid()) {
20930 EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
20931 (vfp.GetEncodingValue() & 0xf) |
20932 ((vfp.GetEncodingValue() & 0xf0) << 12));
20933 AdvanceIT();
20934 return;
20935 }
20936 } else {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020937 // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
20938 if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
20939 EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20940 (vfp.GetEncodingValue() & 0xf) |
20941 ((vfp.GetEncodingValue() & 0xf0) << 12));
20942 return;
20943 }
20944 }
20945 }
20946 if (operand.IsRegister()) {
20947 DRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020948 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020949 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
20950 if (dt.Is(F64)) {
20951 EmitT32_32(0xeeb00b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
20952 AdvanceIT();
20953 return;
20954 }
20955 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
20956 if (!dt.Is(F64)) {
20957 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20958 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
20959 rm.Encode(5, 0));
20960 AdvanceIT();
20961 return;
20962 }
20963 }
20964 } else {
20965 // VMOV{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
20966 if (dt.Is(F64) && cond.IsNotNever()) {
20967 EmitA32(0x0eb00b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
20968 rm.Encode(5, 0));
20969 return;
20970 }
20971 // VMOV{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
20972 if (!dt.Is(F64)) {
20973 if (cond.Is(al)) {
20974 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
20975 rm.Encode(5, 0));
20976 return;
20977 }
20978 }
20979 }
20980 }
20981 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
20982}
20983
20984void Assembler::vmov(Condition cond,
20985 DataType dt,
20986 QRegister rd,
20987 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070020988 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010020989 CheckIT(cond);
20990 if (operand.IsImmediate()) {
20991 ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010020992 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010020993 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
20994 if (encoded_dt.IsValid()) {
20995 if (cond.Is(al) || AllowStronglyDiscouraged()) {
20996 EmitT32_32(
20997 0xef800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
20998 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
20999 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21000 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21001 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21002 AdvanceIT();
21003 return;
21004 }
21005 }
21006 } else {
21007 // VMOV{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21008 if (encoded_dt.IsValid()) {
21009 if (cond.Is(al)) {
21010 EmitA32(0xf2800050U | ((encoded_dt.GetEncodingValue() & 0xf) << 8) |
21011 ((encoded_dt.GetEncodingValue() & 0x10) << 1) |
21012 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21013 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21014 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21015 return;
21016 }
21017 }
21018 }
21019 }
21020 if (operand.IsRegister()) {
21021 QRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021022 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021023 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21024 if (!dt.Is(F64)) {
21025 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21026 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21027 rm.Encode(5, 0));
21028 AdvanceIT();
21029 return;
21030 }
21031 }
21032 } else {
21033 // VMOV{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21034 if (!dt.Is(F64)) {
21035 if (cond.Is(al)) {
21036 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
21037 rm.Encode(5, 0));
21038 return;
21039 }
21040 }
21041 }
21042 }
21043 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21044}
21045
21046void Assembler::vmov(Condition cond,
21047 DataType dt,
21048 SRegister rd,
21049 const SOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021050 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021051 CheckIT(cond);
21052 if (operand.IsImmediate()) {
21053 ImmediateVFP vfp(operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021054 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021055 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; T2
21056 if (dt.Is(F32) && vfp.IsValid()) {
21057 EmitT32_32(0xeeb00a00U | rd.Encode(22, 12) |
21058 (vfp.GetEncodingValue() & 0xf) |
21059 ((vfp.GetEncodingValue() & 0xf0) << 12));
21060 AdvanceIT();
21061 return;
21062 }
21063 } else {
21064 // VMOV{<c>}{<q>}.F32 <Sd>, #<imm> ; A2
21065 if (dt.Is(F32) && vfp.IsValid() && cond.IsNotNever()) {
21066 EmitA32(0x0eb00a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21067 (vfp.GetEncodingValue() & 0xf) |
21068 ((vfp.GetEncodingValue() & 0xf0) << 12));
21069 return;
21070 }
21071 }
21072 }
21073 if (operand.IsRegister()) {
21074 SRegister rm = operand.GetRegister();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021075 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021076 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21077 if (dt.Is(F32)) {
21078 EmitT32_32(0xeeb00a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21079 AdvanceIT();
21080 return;
21081 }
21082 } else {
21083 // VMOV{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21084 if (dt.Is(F32) && cond.IsNotNever()) {
21085 EmitA32(0x0eb00a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21086 rm.Encode(5, 0));
21087 return;
21088 }
21089 }
21090 }
21091 Delegate(kVmov, &Assembler::vmov, cond, dt, rd, operand);
21092}
21093
21094void Assembler::vmov(Condition cond,
21095 DataType dt,
21096 Register rt,
21097 DRegisterLane rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021098 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021099 CheckIT(cond);
21100 Dt_U_opc1_opc2_1 encoded_dt(dt, rn);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021101 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021102 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021103 if (encoded_dt.IsValid() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021104 EmitT32_32(0xee100b10U | ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21105 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21106 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21107 (rt.GetCode() << 12) | rn.Encode(7, 16));
21108 AdvanceIT();
21109 return;
21110 }
21111 } else {
21112 // VMOV{<c>}{<q>}{.<dt>} <Rt>, <Dn[x]> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021113 if (encoded_dt.IsValid() && cond.IsNotNever() &&
21114 (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021115 EmitA32(0x0e100b10U | (cond.GetCondition() << 28) |
21116 ((encoded_dt.GetEncodingValue() & 0x3) << 5) |
21117 ((encoded_dt.GetEncodingValue() & 0xc) << 19) |
21118 ((encoded_dt.GetEncodingValue() & 0x10) << 19) |
21119 (rt.GetCode() << 12) | rn.Encode(7, 16));
21120 return;
21121 }
21122 }
21123 Delegate(kVmov, &Assembler::vmov, cond, dt, rt, rn);
21124}
21125
21126void Assembler::vmovl(Condition cond, DataType dt, QRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021127 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021128 CheckIT(cond);
21129 Dt_U_imm3H_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021130 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021131 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; T1
21132 if (encoded_dt.IsValid()) {
21133 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21134 EmitT32_32(0xef800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21135 ((encoded_dt.GetEncodingValue() & 0x8) << 25) |
21136 rd.Encode(22, 12) | rm.Encode(5, 0));
21137 AdvanceIT();
21138 return;
21139 }
21140 }
21141 } else {
21142 // VMOVL{<c>}{<q>}.<dt> <Qd>, <Dm> ; A1
21143 if (encoded_dt.IsValid()) {
21144 if (cond.Is(al)) {
21145 EmitA32(0xf2800a10U | ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
21146 ((encoded_dt.GetEncodingValue() & 0x8) << 21) |
21147 rd.Encode(22, 12) | rm.Encode(5, 0));
21148 return;
21149 }
21150 }
21151 }
21152 Delegate(kVmovl, &Assembler::vmovl, cond, dt, rd, rm);
21153}
21154
21155void Assembler::vmovn(Condition cond, DataType dt, DRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021156 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021157 CheckIT(cond);
21158 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021159 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021160 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
21161 if (encoded_dt.IsValid()) {
21162 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21163 EmitT32_32(0xffb20200U | (encoded_dt.GetEncodingValue() << 18) |
21164 rd.Encode(22, 12) | rm.Encode(5, 0));
21165 AdvanceIT();
21166 return;
21167 }
21168 }
21169 } else {
21170 // VMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
21171 if (encoded_dt.IsValid()) {
21172 if (cond.Is(al)) {
21173 EmitA32(0xf3b20200U | (encoded_dt.GetEncodingValue() << 18) |
21174 rd.Encode(22, 12) | rm.Encode(5, 0));
21175 return;
21176 }
21177 }
21178 }
21179 Delegate(kVmovn, &Assembler::vmovn, cond, dt, rd, rm);
21180}
21181
21182void Assembler::vmrs(Condition cond,
21183 RegisterOrAPSR_nzcv rt,
21184 SpecialFPRegister spec_reg) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021186 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021187 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021188 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; T1
21189 EmitT32_32(0xeef00a10U | (rt.GetCode() << 12) | (spec_reg.GetReg() << 16));
21190 AdvanceIT();
21191 return;
21192 } else {
21193 // VMRS{<c>}{<q>} <Rt>, <spec_reg> ; A1
21194 if (cond.IsNotNever()) {
21195 EmitA32(0x0ef00a10U | (cond.GetCondition() << 28) | (rt.GetCode() << 12) |
21196 (spec_reg.GetReg() << 16));
21197 return;
21198 }
21199 }
21200 Delegate(kVmrs, &Assembler::vmrs, cond, rt, spec_reg);
21201}
21202
21203void Assembler::vmsr(Condition cond, SpecialFPRegister spec_reg, Register rt) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021204 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021205 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021206 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021207 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; T1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021208 if ((!rt.IsPC() || AllowUnpredictable())) {
21209 EmitT32_32(0xeee00a10U | (spec_reg.GetReg() << 16) |
21210 (rt.GetCode() << 12));
21211 AdvanceIT();
21212 return;
21213 }
Alexandre Ramesd3832962016-07-04 15:03:43 +010021214 } else {
21215 // VMSR{<c>}{<q>} <spec_reg>, <Rt> ; A1
Pierre Langlois960d28b2017-02-15 13:06:01 +000021216 if (cond.IsNotNever() && (!rt.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021217 EmitA32(0x0ee00a10U | (cond.GetCondition() << 28) |
21218 (spec_reg.GetReg() << 16) | (rt.GetCode() << 12));
21219 return;
21220 }
21221 }
21222 Delegate(kVmsr, &Assembler::vmsr, cond, spec_reg, rt);
21223}
21224
21225void Assembler::vmul(Condition cond,
21226 DataType dt,
21227 DRegister rd,
21228 DRegister rn,
21229 DRegister dm,
21230 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021231 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021232 CheckIT(cond);
21233 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021234 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021235 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; T1
21236 if (encoded_dt.IsValid() &&
21237 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21238 (!dt.Is(I16) && (index <= 1)))) {
21239 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21240 uint32_t shift = 4;
21241 if (dt.Is(I16)) {
21242 shift = 3;
21243 }
21244 uint32_t mvm = dm.GetCode() | index << shift;
21245 EmitT32_32(0xef800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21246 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21247 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21248 ((mvm & 0x10) << 1));
21249 AdvanceIT();
21250 return;
21251 }
21252 }
21253 } else {
21254 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm>[<index>] ; A1
21255 if (encoded_dt.IsValid() &&
21256 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21257 (!dt.Is(I16) && (index <= 1)))) {
21258 if (cond.Is(al)) {
21259 uint32_t shift = 4;
21260 if (dt.Is(I16)) {
21261 shift = 3;
21262 }
21263 uint32_t mvm = dm.GetCode() | index << shift;
21264 EmitA32(0xf2800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21265 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21266 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21267 ((mvm & 0x10) << 1));
21268 return;
21269 }
21270 }
21271 }
21272 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21273}
21274
21275void Assembler::vmul(Condition cond,
21276 DataType dt,
21277 QRegister rd,
21278 QRegister rn,
21279 DRegister dm,
21280 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021281 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021282 CheckIT(cond);
21283 Dt_F_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021285 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; T1
21286 if (encoded_dt.IsValid() &&
21287 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21288 (!dt.Is(I16) && (index <= 1)))) {
21289 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21290 uint32_t shift = 4;
21291 if (dt.Is(I16)) {
21292 shift = 3;
21293 }
21294 uint32_t mvm = dm.GetCode() | index << shift;
21295 EmitT32_32(0xff800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21296 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21297 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21298 ((mvm & 0x10) << 1));
21299 AdvanceIT();
21300 return;
21301 }
21302 }
21303 } else {
21304 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm>[<index>] ; A1
21305 if (encoded_dt.IsValid() &&
21306 ((dt.Is(I16) && (index <= 3) && (dm.GetCode() <= 7)) ||
21307 (!dt.Is(I16) && (index <= 1)))) {
21308 if (cond.Is(al)) {
21309 uint32_t shift = 4;
21310 if (dt.Is(I16)) {
21311 shift = 3;
21312 }
21313 uint32_t mvm = dm.GetCode() | index << shift;
21314 EmitA32(0xf3800840U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21315 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
21316 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21317 ((mvm & 0x10) << 1));
21318 return;
21319 }
21320 }
21321 }
21322 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, dm, index);
21323}
21324
21325void Assembler::vmul(
21326 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021327 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021328 CheckIT(cond);
21329 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021330 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021331 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
21332 if (dt.Is(F32)) {
21333 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21334 EmitT32_32(0xff000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21335 rm.Encode(5, 0));
21336 AdvanceIT();
21337 return;
21338 }
21339 }
21340 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
21341 if (dt.Is(F64)) {
21342 EmitT32_32(0xee200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21343 rm.Encode(5, 0));
21344 AdvanceIT();
21345 return;
21346 }
21347 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
21348 if (encoded_dt.IsValid()) {
21349 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21350 EmitT32_32(0xef000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21351 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21352 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21353 AdvanceIT();
21354 return;
21355 }
21356 }
21357 } else {
21358 // VMUL{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
21359 if (dt.Is(F32)) {
21360 if (cond.Is(al)) {
21361 EmitA32(0xf3000d10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21362 rm.Encode(5, 0));
21363 return;
21364 }
21365 }
21366 // VMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
21367 if (dt.Is(F64) && cond.IsNotNever()) {
21368 EmitA32(0x0e200b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21369 rn.Encode(7, 16) | rm.Encode(5, 0));
21370 return;
21371 }
21372 // VMUL{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
21373 if (encoded_dt.IsValid()) {
21374 if (cond.Is(al)) {
21375 EmitA32(0xf2000910U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21376 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21377 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21378 return;
21379 }
21380 }
21381 }
21382 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21383}
21384
21385void Assembler::vmul(
21386 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021387 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021388 CheckIT(cond);
21389 Dt_op_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021390 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021391 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
21392 if (dt.Is(F32)) {
21393 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21394 EmitT32_32(0xff000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21395 rm.Encode(5, 0));
21396 AdvanceIT();
21397 return;
21398 }
21399 }
21400 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
21401 if (encoded_dt.IsValid()) {
21402 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21403 EmitT32_32(0xef000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21404 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21405 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21406 AdvanceIT();
21407 return;
21408 }
21409 }
21410 } else {
21411 // VMUL{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
21412 if (dt.Is(F32)) {
21413 if (cond.Is(al)) {
21414 EmitA32(0xf3000d50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21415 rm.Encode(5, 0));
21416 return;
21417 }
21418 }
21419 // VMUL{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
21420 if (encoded_dt.IsValid()) {
21421 if (cond.Is(al)) {
21422 EmitA32(0xf2000950U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21423 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21424 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21425 return;
21426 }
21427 }
21428 }
21429 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21430}
21431
21432void Assembler::vmul(
21433 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021434 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021435 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021436 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021437 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
21438 if (dt.Is(F32)) {
21439 EmitT32_32(0xee200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21440 rm.Encode(5, 0));
21441 AdvanceIT();
21442 return;
21443 }
21444 } else {
21445 // VMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
21446 if (dt.Is(F32) && cond.IsNotNever()) {
21447 EmitA32(0x0e200a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21448 rn.Encode(7, 16) | rm.Encode(5, 0));
21449 return;
21450 }
21451 }
21452 Delegate(kVmul, &Assembler::vmul, cond, dt, rd, rn, rm);
21453}
21454
21455void Assembler::vmull(Condition cond,
21456 DataType dt,
21457 QRegister rd,
21458 DRegister rn,
21459 DRegister dm,
21460 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021461 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021462 CheckIT(cond);
21463 Dt_U_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021464 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021465 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T1
21466 if (encoded_dt.IsValid() &&
21467 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
21468 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
21469 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21470 uint32_t shift = 4;
21471 if (dt.Is(S16) || dt.Is(U16)) {
21472 shift = 3;
21473 }
21474 uint32_t mvm = dm.GetCode() | index << shift;
21475 EmitT32_32(0xef800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21476 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21477 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21478 ((mvm & 0x10) << 1));
21479 AdvanceIT();
21480 return;
21481 }
21482 }
21483 } else {
21484 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A1
21485 if (encoded_dt.IsValid() &&
21486 (((dt.Is(S16) || dt.Is(U16)) && (index <= 3) && (dm.GetCode() <= 7)) ||
21487 (!dt.Is(S16) && !dt.Is(U16) && (index <= 1)))) {
21488 if (cond.Is(al)) {
21489 uint32_t shift = 4;
21490 if (dt.Is(S16) || dt.Is(U16)) {
21491 shift = 3;
21492 }
21493 uint32_t mvm = dm.GetCode() | index << shift;
21494 EmitA32(0xf2800a40U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21495 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21496 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
21497 ((mvm & 0x10) << 1));
21498 return;
21499 }
21500 }
21501 }
21502 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, dm, index);
21503}
21504
21505void Assembler::vmull(
21506 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021507 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021508 CheckIT(cond);
21509 Dt_op_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021510 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021511 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
21512 if (encoded_dt.IsValid()) {
21513 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21514 EmitT32_32(0xef800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21515 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
21516 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21517 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21518 AdvanceIT();
21519 return;
21520 }
21521 }
21522 } else {
21523 // VMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
21524 if (encoded_dt.IsValid()) {
21525 if (cond.Is(al)) {
21526 EmitA32(0xf2800c00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
21527 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
21528 ((encoded_dt.GetEncodingValue() & 0x8) << 6) |
21529 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
21530 return;
21531 }
21532 }
21533 }
21534 Delegate(kVmull, &Assembler::vmull, cond, dt, rd, rn, rm);
21535}
21536
21537void Assembler::vmvn(Condition cond,
21538 DataType dt,
21539 DRegister rd,
21540 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021541 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021542 CheckIT(cond);
21543 if (operand.IsImmediate()) {
21544 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021545 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021546 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
21547 if (encoded_dt.IsValid()) {
21548 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21549 EmitT32_32(0xef800030U | (encoded_dt.GetEncodingValue() << 8) |
21550 rd.Encode(22, 12) |
21551 (encoded_dt.GetEncodedImmediate() & 0xf) |
21552 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21553 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21554 AdvanceIT();
21555 return;
21556 }
21557 }
21558 } else {
21559 // VMVN{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
21560 if (encoded_dt.IsValid()) {
21561 if (cond.Is(al)) {
21562 EmitA32(0xf2800030U | (encoded_dt.GetEncodingValue() << 8) |
21563 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21564 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21565 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21566 return;
21567 }
21568 }
21569 }
21570 }
21571 if (operand.IsRegister()) {
21572 DRegister rm = operand.GetRegister();
21573 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021574 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021575 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
21576 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21577 EmitT32_32(0xffb00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21578 AdvanceIT();
21579 return;
21580 }
21581 } else {
21582 // VMVN{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
21583 if (cond.Is(al)) {
21584 EmitA32(0xf3b00580U | rd.Encode(22, 12) | rm.Encode(5, 0));
21585 return;
21586 }
21587 }
21588 }
21589 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21590}
21591
21592void Assembler::vmvn(Condition cond,
21593 DataType dt,
21594 QRegister rd,
21595 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021596 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021597 CheckIT(cond);
21598 if (operand.IsImmediate()) {
21599 ImmediateVmvn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021600 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021601 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; T1
21602 if (encoded_dt.IsValid()) {
21603 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21604 EmitT32_32(0xef800070U | (encoded_dt.GetEncodingValue() << 8) |
21605 rd.Encode(22, 12) |
21606 (encoded_dt.GetEncodedImmediate() & 0xf) |
21607 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21608 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21609 AdvanceIT();
21610 return;
21611 }
21612 }
21613 } else {
21614 // VMVN{<c>}{<q>}.<dt> <Qd>, #<imm> ; A1
21615 if (encoded_dt.IsValid()) {
21616 if (cond.Is(al)) {
21617 EmitA32(0xf2800070U | (encoded_dt.GetEncodingValue() << 8) |
21618 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21619 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21620 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21621 return;
21622 }
21623 }
21624 }
21625 }
21626 if (operand.IsRegister()) {
21627 QRegister rm = operand.GetRegister();
21628 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021629 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021630 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
21631 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21632 EmitT32_32(0xffb005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21633 AdvanceIT();
21634 return;
21635 }
21636 } else {
21637 // VMVN{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
21638 if (cond.Is(al)) {
21639 EmitA32(0xf3b005c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
21640 return;
21641 }
21642 }
21643 }
21644 Delegate(kVmvn, &Assembler::vmvn, cond, dt, rd, operand);
21645}
21646
21647void Assembler::vneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021648 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021649 CheckIT(cond);
21650 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021651 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021652 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
21653 if (encoded_dt.IsValid()) {
21654 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21655 EmitT32_32(0xffb10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21656 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21657 rd.Encode(22, 12) | rm.Encode(5, 0));
21658 AdvanceIT();
21659 return;
21660 }
21661 }
21662 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; T2
21663 if (dt.Is(F64)) {
21664 EmitT32_32(0xeeb10b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21665 AdvanceIT();
21666 return;
21667 }
21668 } else {
21669 // VNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
21670 if (encoded_dt.IsValid()) {
21671 if (cond.Is(al)) {
21672 EmitA32(0xf3b10380U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21673 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21674 rd.Encode(22, 12) | rm.Encode(5, 0));
21675 return;
21676 }
21677 }
21678 // VNEG{<c>}{<q>}.F64 <Dd>, <Dm> ; A2
21679 if (dt.Is(F64) && cond.IsNotNever()) {
21680 EmitA32(0x0eb10b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21681 rm.Encode(5, 0));
21682 return;
21683 }
21684 }
21685 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21686}
21687
21688void Assembler::vneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021689 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021690 CheckIT(cond);
21691 Dt_F_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021692 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021693 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
21694 if (encoded_dt.IsValid()) {
21695 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21696 EmitT32_32(0xffb103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21697 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21698 rd.Encode(22, 12) | rm.Encode(5, 0));
21699 AdvanceIT();
21700 return;
21701 }
21702 }
21703 } else {
21704 // VNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
21705 if (encoded_dt.IsValid()) {
21706 if (cond.Is(al)) {
21707 EmitA32(0xf3b103c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
21708 ((encoded_dt.GetEncodingValue() & 0x4) << 8) |
21709 rd.Encode(22, 12) | rm.Encode(5, 0));
21710 return;
21711 }
21712 }
21713 }
21714 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21715}
21716
21717void Assembler::vneg(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021718 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021719 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021720 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021721 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; T2
21722 if (dt.Is(F32)) {
21723 EmitT32_32(0xeeb10a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
21724 AdvanceIT();
21725 return;
21726 }
21727 } else {
21728 // VNEG{<c>}{<q>}.F32 <Sd>, <Sm> ; A2
21729 if (dt.Is(F32) && cond.IsNotNever()) {
21730 EmitA32(0x0eb10a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21731 rm.Encode(5, 0));
21732 return;
21733 }
21734 }
21735 Delegate(kVneg, &Assembler::vneg, cond, dt, rd, rm);
21736}
21737
21738void Assembler::vnmla(
21739 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021740 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021741 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021743 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21744 if (dt.Is(F32)) {
21745 EmitT32_32(0xee100a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21746 rm.Encode(5, 0));
21747 AdvanceIT();
21748 return;
21749 }
21750 } else {
21751 // VNMLA{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21752 if (dt.Is(F32) && cond.IsNotNever()) {
21753 EmitA32(0x0e100a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21754 rn.Encode(7, 16) | rm.Encode(5, 0));
21755 return;
21756 }
21757 }
21758 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21759}
21760
21761void Assembler::vnmla(
21762 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021763 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021764 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021765 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021766 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21767 if (dt.Is(F64)) {
21768 EmitT32_32(0xee100b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21769 rm.Encode(5, 0));
21770 AdvanceIT();
21771 return;
21772 }
21773 } else {
21774 // VNMLA{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21775 if (dt.Is(F64) && cond.IsNotNever()) {
21776 EmitA32(0x0e100b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21777 rn.Encode(7, 16) | rm.Encode(5, 0));
21778 return;
21779 }
21780 }
21781 Delegate(kVnmla, &Assembler::vnmla, cond, dt, rd, rn, rm);
21782}
21783
21784void Assembler::vnmls(
21785 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021786 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021787 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021788 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021789 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; T1
21790 if (dt.Is(F32)) {
21791 EmitT32_32(0xee100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21792 rm.Encode(5, 0));
21793 AdvanceIT();
21794 return;
21795 }
21796 } else {
21797 // VNMLS{<c>}{<q>}.F32 <Sd>, <Sn>, <Sm> ; A1
21798 if (dt.Is(F32) && cond.IsNotNever()) {
21799 EmitA32(0x0e100a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21800 rn.Encode(7, 16) | rm.Encode(5, 0));
21801 return;
21802 }
21803 }
21804 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21805}
21806
21807void Assembler::vnmls(
21808 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021809 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021810 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021811 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021812 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; T1
21813 if (dt.Is(F64)) {
21814 EmitT32_32(0xee100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21815 rm.Encode(5, 0));
21816 AdvanceIT();
21817 return;
21818 }
21819 } else {
21820 // VNMLS{<c>}{<q>}.F64 <Dd>, <Dn>, <Dm> ; A1
21821 if (dt.Is(F64) && cond.IsNotNever()) {
21822 EmitA32(0x0e100b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21823 rn.Encode(7, 16) | rm.Encode(5, 0));
21824 return;
21825 }
21826 }
21827 Delegate(kVnmls, &Assembler::vnmls, cond, dt, rd, rn, rm);
21828}
21829
21830void Assembler::vnmul(
21831 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021832 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021833 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021834 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021835 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T1
21836 if (dt.Is(F32)) {
21837 EmitT32_32(0xee200a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21838 rm.Encode(5, 0));
21839 AdvanceIT();
21840 return;
21841 }
21842 } else {
21843 // VNMUL{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A1
21844 if (dt.Is(F32) && cond.IsNotNever()) {
21845 EmitA32(0x0e200a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21846 rn.Encode(7, 16) | rm.Encode(5, 0));
21847 return;
21848 }
21849 }
21850 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21851}
21852
21853void Assembler::vnmul(
21854 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021855 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021856 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021857 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021858 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T1
21859 if (dt.Is(F64)) {
21860 EmitT32_32(0xee200b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21861 rm.Encode(5, 0));
21862 AdvanceIT();
21863 return;
21864 }
21865 } else {
21866 // VNMUL{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A1
21867 if (dt.Is(F64) && cond.IsNotNever()) {
21868 EmitA32(0x0e200b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
21869 rn.Encode(7, 16) | rm.Encode(5, 0));
21870 return;
21871 }
21872 }
21873 Delegate(kVnmul, &Assembler::vnmul, cond, dt, rd, rn, rm);
21874}
21875
21876void Assembler::vorn(Condition cond,
21877 DataType dt,
21878 DRegister rd,
21879 DRegister rn,
21880 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021881 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021882 CheckIT(cond);
21883 if (operand.IsImmediate()) {
21884 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021885 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021886 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
21887 if (encoded_dt.IsValid() && rd.Is(rn)) {
21888 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21889 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
21890 rd.Encode(22, 12) |
21891 (encoded_dt.GetEncodedImmediate() & 0xf) |
21892 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21893 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21894 AdvanceIT();
21895 return;
21896 }
21897 }
21898 } else {
21899 // VORN{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
21900 if (encoded_dt.IsValid() && rd.Is(rn)) {
21901 if (cond.Is(al)) {
21902 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
21903 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21904 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21905 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21906 return;
21907 }
21908 }
21909 }
21910 }
21911 if (operand.IsRegister()) {
21912 DRegister rm = operand.GetRegister();
21913 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021914 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021915 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
21916 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21917 EmitT32_32(0xef300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21918 rm.Encode(5, 0));
21919 AdvanceIT();
21920 return;
21921 }
21922 } else {
21923 // VORN{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
21924 if (cond.Is(al)) {
21925 EmitA32(0xf2300110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21926 rm.Encode(5, 0));
21927 return;
21928 }
21929 }
21930 }
21931 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
21932}
21933
21934void Assembler::vorn(Condition cond,
21935 DataType dt,
21936 QRegister rd,
21937 QRegister rn,
21938 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021939 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021940 CheckIT(cond);
21941 if (operand.IsImmediate()) {
21942 ImmediateVorn encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021943 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021944 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
21945 if (encoded_dt.IsValid() && rd.Is(rn)) {
21946 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21947 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
21948 rd.Encode(22, 12) |
21949 (encoded_dt.GetEncodedImmediate() & 0xf) |
21950 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21951 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
21952 AdvanceIT();
21953 return;
21954 }
21955 }
21956 } else {
21957 // VORN{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
21958 if (encoded_dt.IsValid() && rd.Is(rn)) {
21959 if (cond.Is(al)) {
21960 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
21961 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
21962 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
21963 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
21964 return;
21965 }
21966 }
21967 }
21968 }
21969 if (operand.IsRegister()) {
21970 QRegister rm = operand.GetRegister();
21971 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010021972 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010021973 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
21974 if (cond.Is(al) || AllowStronglyDiscouraged()) {
21975 EmitT32_32(0xef300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21976 rm.Encode(5, 0));
21977 AdvanceIT();
21978 return;
21979 }
21980 } else {
21981 // VORN{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
21982 if (cond.Is(al)) {
21983 EmitA32(0xf2300150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
21984 rm.Encode(5, 0));
21985 return;
21986 }
21987 }
21988 }
21989 Delegate(kVorn, &Assembler::vorn, cond, dt, rd, rn, operand);
21990}
21991
21992void Assembler::vorr(Condition cond,
21993 DataType dt,
21994 DRegister rd,
21995 DRegister rn,
21996 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070021997 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010021998 CheckIT(cond);
21999 if (operand.IsRegister()) {
22000 DRegister rm = operand.GetRegister();
22001 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022002 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022003 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; T1
22004 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22005 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22006 rm.Encode(5, 0));
22007 AdvanceIT();
22008 return;
22009 }
22010 } else {
22011 // VORR{<c>}{<q>}{.<dt>} {<Dd>}, <Dn>, <Dm> ; A1
22012 if (cond.Is(al)) {
22013 EmitA32(0xf2200110U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22014 rm.Encode(5, 0));
22015 return;
22016 }
22017 }
22018 }
22019 if (operand.IsImmediate()) {
22020 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022021 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022022 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; T1
22023 if (encoded_dt.IsValid() && rd.Is(rn)) {
22024 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22025 EmitT32_32(0xef800010U | (encoded_dt.GetEncodingValue() << 8) |
22026 rd.Encode(22, 12) |
22027 (encoded_dt.GetEncodedImmediate() & 0xf) |
22028 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22029 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22030 AdvanceIT();
22031 return;
22032 }
22033 }
22034 } else {
22035 // VORR{<c>}{<q>}.<dt> {<Ddn>}, <Ddn>, #<imm> ; A1
22036 if (encoded_dt.IsValid() && rd.Is(rn)) {
22037 if (cond.Is(al)) {
22038 EmitA32(0xf2800010U | (encoded_dt.GetEncodingValue() << 8) |
22039 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22040 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22041 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22042 return;
22043 }
22044 }
22045 }
22046 }
22047 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22048}
22049
22050void Assembler::vorr(Condition cond,
22051 DataType dt,
22052 QRegister rd,
22053 QRegister rn,
22054 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022055 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022056 CheckIT(cond);
22057 if (operand.IsRegister()) {
22058 QRegister rm = operand.GetRegister();
22059 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022060 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022061 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; T1
22062 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22063 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22064 rm.Encode(5, 0));
22065 AdvanceIT();
22066 return;
22067 }
22068 } else {
22069 // VORR{<c>}{<q>}{.<dt>} {<Qd>}, <Qn>, <Qm> ; A1
22070 if (cond.Is(al)) {
22071 EmitA32(0xf2200150U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22072 rm.Encode(5, 0));
22073 return;
22074 }
22075 }
22076 }
22077 if (operand.IsImmediate()) {
22078 ImmediateVorr encoded_dt(dt, operand.GetNeonImmediate());
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022079 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022080 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; T1
22081 if (encoded_dt.IsValid() && rd.Is(rn)) {
22082 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22083 EmitT32_32(0xef800050U | (encoded_dt.GetEncodingValue() << 8) |
22084 rd.Encode(22, 12) |
22085 (encoded_dt.GetEncodedImmediate() & 0xf) |
22086 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22087 ((encoded_dt.GetEncodedImmediate() & 0x80) << 21));
22088 AdvanceIT();
22089 return;
22090 }
22091 }
22092 } else {
22093 // VORR{<c>}{<q>}.<dt> {<Qdn>}, <Qdn>, #<imm> ; A1
22094 if (encoded_dt.IsValid() && rd.Is(rn)) {
22095 if (cond.Is(al)) {
22096 EmitA32(0xf2800050U | (encoded_dt.GetEncodingValue() << 8) |
22097 rd.Encode(22, 12) | (encoded_dt.GetEncodedImmediate() & 0xf) |
22098 ((encoded_dt.GetEncodedImmediate() & 0x70) << 12) |
22099 ((encoded_dt.GetEncodedImmediate() & 0x80) << 17));
22100 return;
22101 }
22102 }
22103 }
22104 }
22105 Delegate(kVorr, &Assembler::vorr, cond, dt, rd, rn, operand);
22106}
22107
22108void Assembler::vpadal(Condition cond,
22109 DataType dt,
22110 DRegister rd,
22111 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022112 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022113 CheckIT(cond);
22114 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022115 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022116 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22117 if (encoded_dt.IsValid()) {
22118 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22119 EmitT32_32(0xffb00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22120 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22121 rd.Encode(22, 12) | rm.Encode(5, 0));
22122 AdvanceIT();
22123 return;
22124 }
22125 }
22126 } else {
22127 // VPADAL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22128 if (encoded_dt.IsValid()) {
22129 if (cond.Is(al)) {
22130 EmitA32(0xf3b00600U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22131 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22132 rd.Encode(22, 12) | rm.Encode(5, 0));
22133 return;
22134 }
22135 }
22136 }
22137 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22138}
22139
22140void Assembler::vpadal(Condition cond,
22141 DataType dt,
22142 QRegister rd,
22143 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022144 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022145 CheckIT(cond);
22146 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022147 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022148 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22149 if (encoded_dt.IsValid()) {
22150 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22151 EmitT32_32(0xffb00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22152 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22153 rd.Encode(22, 12) | rm.Encode(5, 0));
22154 AdvanceIT();
22155 return;
22156 }
22157 }
22158 } else {
22159 // VPADAL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22160 if (encoded_dt.IsValid()) {
22161 if (cond.Is(al)) {
22162 EmitA32(0xf3b00640U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22163 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22164 rd.Encode(22, 12) | rm.Encode(5, 0));
22165 return;
22166 }
22167 }
22168 }
22169 Delegate(kVpadal, &Assembler::vpadal, cond, dt, rd, rm);
22170}
22171
22172void Assembler::vpadd(
22173 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022174 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022175 CheckIT(cond);
22176 Dt_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022177 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022178 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22179 if (dt.Is(F32)) {
22180 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22181 EmitT32_32(0xff000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22182 rm.Encode(5, 0));
22183 AdvanceIT();
22184 return;
22185 }
22186 }
22187 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22188 if (encoded_dt.IsValid()) {
22189 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22190 EmitT32_32(0xef000b10U | (encoded_dt.GetEncodingValue() << 20) |
22191 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22192 AdvanceIT();
22193 return;
22194 }
22195 }
22196 } else {
22197 // VPADD{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22198 if (dt.Is(F32)) {
22199 if (cond.Is(al)) {
22200 EmitA32(0xf3000d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22201 rm.Encode(5, 0));
22202 return;
22203 }
22204 }
22205 // VPADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22206 if (encoded_dt.IsValid()) {
22207 if (cond.Is(al)) {
22208 EmitA32(0xf2000b10U | (encoded_dt.GetEncodingValue() << 20) |
22209 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22210 return;
22211 }
22212 }
22213 }
22214 Delegate(kVpadd, &Assembler::vpadd, cond, dt, rd, rn, rm);
22215}
22216
22217void Assembler::vpaddl(Condition cond,
22218 DataType dt,
22219 DRegister rd,
22220 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022221 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022222 CheckIT(cond);
22223 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022224 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022225 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22226 if (encoded_dt.IsValid()) {
22227 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22228 EmitT32_32(0xffb00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22229 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22230 rd.Encode(22, 12) | rm.Encode(5, 0));
22231 AdvanceIT();
22232 return;
22233 }
22234 }
22235 } else {
22236 // VPADDL{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22237 if (encoded_dt.IsValid()) {
22238 if (cond.Is(al)) {
22239 EmitA32(0xf3b00200U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22240 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22241 rd.Encode(22, 12) | rm.Encode(5, 0));
22242 return;
22243 }
22244 }
22245 }
22246 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22247}
22248
22249void Assembler::vpaddl(Condition cond,
22250 DataType dt,
22251 QRegister rd,
22252 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022253 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022254 CheckIT(cond);
22255 Dt_op_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022256 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022257 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22258 if (encoded_dt.IsValid()) {
22259 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22260 EmitT32_32(0xffb00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22261 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22262 rd.Encode(22, 12) | rm.Encode(5, 0));
22263 AdvanceIT();
22264 return;
22265 }
22266 }
22267 } else {
22268 // VPADDL{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22269 if (encoded_dt.IsValid()) {
22270 if (cond.Is(al)) {
22271 EmitA32(0xf3b00240U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22272 ((encoded_dt.GetEncodingValue() & 0x4) << 5) |
22273 rd.Encode(22, 12) | rm.Encode(5, 0));
22274 return;
22275 }
22276 }
22277 }
22278 Delegate(kVpaddl, &Assembler::vpaddl, cond, dt, rd, rm);
22279}
22280
22281void Assembler::vpmax(
22282 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022283 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022284 CheckIT(cond);
22285 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022286 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022287 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22288 if (dt.Is(F32)) {
22289 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22290 EmitT32_32(0xff000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22291 rm.Encode(5, 0));
22292 AdvanceIT();
22293 return;
22294 }
22295 }
22296 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22297 if (encoded_dt.IsValid()) {
22298 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22299 EmitT32_32(0xef000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22300 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22301 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22302 AdvanceIT();
22303 return;
22304 }
22305 }
22306 } else {
22307 // VPMAX{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22308 if (dt.Is(F32)) {
22309 if (cond.Is(al)) {
22310 EmitA32(0xf3000f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22311 rm.Encode(5, 0));
22312 return;
22313 }
22314 }
22315 // VPMAX{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22316 if (encoded_dt.IsValid()) {
22317 if (cond.Is(al)) {
22318 EmitA32(0xf2000a00U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22319 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22320 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22321 return;
22322 }
22323 }
22324 }
22325 Delegate(kVpmax, &Assembler::vpmax, cond, dt, rd, rn, rm);
22326}
22327
22328void Assembler::vpmin(
22329 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022330 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022331 CheckIT(cond);
22332 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022333 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022334 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
22335 if (dt.Is(F32)) {
22336 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22337 EmitT32_32(0xff200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22338 rm.Encode(5, 0));
22339 AdvanceIT();
22340 return;
22341 }
22342 }
22343 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22344 if (encoded_dt.IsValid()) {
22345 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22346 EmitT32_32(0xef000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22347 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22348 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22349 AdvanceIT();
22350 return;
22351 }
22352 }
22353 } else {
22354 // VPMIN{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
22355 if (dt.Is(F32)) {
22356 if (cond.Is(al)) {
22357 EmitA32(0xf3200f00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
22358 rm.Encode(5, 0));
22359 return;
22360 }
22361 }
22362 // VPMIN{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22363 if (encoded_dt.IsValid()) {
22364 if (cond.Is(al)) {
22365 EmitA32(0xf2000a10U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22366 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22367 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22368 return;
22369 }
22370 }
22371 }
22372 Delegate(kVpmin, &Assembler::vpmin, cond, dt, rd, rn, rm);
22373}
22374
22375void Assembler::vpop(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022376 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022377 CheckIT(cond);
22378 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022379 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022380 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080022381 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022382 const DRegister& dreg = dreglist.GetFirstDRegister();
22383 unsigned len = dreglist.GetLength() * 2;
22384 EmitT32_32(0xecbd0b00U | dreg.Encode(22, 12) | (len & 0xff));
22385 AdvanceIT();
22386 return;
22387 }
22388 } else {
22389 // VPOP{<c>}{<q>}{.<size>} <dreglist> ; A1
22390 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080022391 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022392 const DRegister& dreg = dreglist.GetFirstDRegister();
22393 unsigned len = dreglist.GetLength() * 2;
22394 EmitA32(0x0cbd0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22395 (len & 0xff));
22396 return;
22397 }
22398 }
22399 Delegate(kVpop, &Assembler::vpop, cond, dt, dreglist);
22400}
22401
22402void Assembler::vpop(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022403 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022404 CheckIT(cond);
22405 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022406 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022407 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; T2
22408 const SRegister& sreg = sreglist.GetFirstSRegister();
22409 unsigned len = sreglist.GetLength();
22410 EmitT32_32(0xecbd0a00U | sreg.Encode(22, 12) | (len & 0xff));
22411 AdvanceIT();
22412 return;
22413 } else {
22414 // VPOP{<c>}{<q>}{.<size>} <sreglist> ; A2
22415 if (cond.IsNotNever()) {
22416 const SRegister& sreg = sreglist.GetFirstSRegister();
22417 unsigned len = sreglist.GetLength();
22418 EmitA32(0x0cbd0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22419 (len & 0xff));
22420 return;
22421 }
22422 }
22423 Delegate(kVpop, &Assembler::vpop, cond, dt, sreglist);
22424}
22425
22426void Assembler::vpush(Condition cond, DataType dt, DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022427 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022428 CheckIT(cond);
22429 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022430 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022431 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080022432 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022433 const DRegister& dreg = dreglist.GetFirstDRegister();
22434 unsigned len = dreglist.GetLength() * 2;
22435 EmitT32_32(0xed2d0b00U | dreg.Encode(22, 12) | (len & 0xff));
22436 AdvanceIT();
22437 return;
22438 }
22439 } else {
22440 // VPUSH{<c>}{<q>}{.<size>} <dreglist> ; A1
22441 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080022442 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022443 const DRegister& dreg = dreglist.GetFirstDRegister();
22444 unsigned len = dreglist.GetLength() * 2;
22445 EmitA32(0x0d2d0b00U | (cond.GetCondition() << 28) | dreg.Encode(22, 12) |
22446 (len & 0xff));
22447 return;
22448 }
22449 }
22450 Delegate(kVpush, &Assembler::vpush, cond, dt, dreglist);
22451}
22452
22453void Assembler::vpush(Condition cond, DataType dt, SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022454 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022455 CheckIT(cond);
22456 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022457 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022458 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; T2
22459 const SRegister& sreg = sreglist.GetFirstSRegister();
22460 unsigned len = sreglist.GetLength();
22461 EmitT32_32(0xed2d0a00U | sreg.Encode(22, 12) | (len & 0xff));
22462 AdvanceIT();
22463 return;
22464 } else {
22465 // VPUSH{<c>}{<q>}{.<size>} <sreglist> ; A2
22466 if (cond.IsNotNever()) {
22467 const SRegister& sreg = sreglist.GetFirstSRegister();
22468 unsigned len = sreglist.GetLength();
22469 EmitA32(0x0d2d0a00U | (cond.GetCondition() << 28) | sreg.Encode(22, 12) |
22470 (len & 0xff));
22471 return;
22472 }
22473 }
22474 Delegate(kVpush, &Assembler::vpush, cond, dt, sreglist);
22475}
22476
22477void Assembler::vqabs(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022478 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022479 CheckIT(cond);
22480 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022481 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022482 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
22483 if (encoded_dt.IsValid()) {
22484 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22485 EmitT32_32(0xffb00700U | (encoded_dt.GetEncodingValue() << 18) |
22486 rd.Encode(22, 12) | rm.Encode(5, 0));
22487 AdvanceIT();
22488 return;
22489 }
22490 }
22491 } else {
22492 // VQABS{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
22493 if (encoded_dt.IsValid()) {
22494 if (cond.Is(al)) {
22495 EmitA32(0xf3b00700U | (encoded_dt.GetEncodingValue() << 18) |
22496 rd.Encode(22, 12) | rm.Encode(5, 0));
22497 return;
22498 }
22499 }
22500 }
22501 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22502}
22503
22504void Assembler::vqabs(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022505 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022506 CheckIT(cond);
22507 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022508 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022509 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
22510 if (encoded_dt.IsValid()) {
22511 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22512 EmitT32_32(0xffb00740U | (encoded_dt.GetEncodingValue() << 18) |
22513 rd.Encode(22, 12) | rm.Encode(5, 0));
22514 AdvanceIT();
22515 return;
22516 }
22517 }
22518 } else {
22519 // VQABS{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
22520 if (encoded_dt.IsValid()) {
22521 if (cond.Is(al)) {
22522 EmitA32(0xf3b00740U | (encoded_dt.GetEncodingValue() << 18) |
22523 rd.Encode(22, 12) | rm.Encode(5, 0));
22524 return;
22525 }
22526 }
22527 }
22528 Delegate(kVqabs, &Assembler::vqabs, cond, dt, rd, rm);
22529}
22530
22531void Assembler::vqadd(
22532 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022534 CheckIT(cond);
22535 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022536 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022537 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22538 if (encoded_dt.IsValid()) {
22539 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22540 EmitT32_32(0xef000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22541 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22542 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22543 AdvanceIT();
22544 return;
22545 }
22546 }
22547 } else {
22548 // VQADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22549 if (encoded_dt.IsValid()) {
22550 if (cond.Is(al)) {
22551 EmitA32(0xf2000010U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22552 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22553 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22554 return;
22555 }
22556 }
22557 }
22558 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22559}
22560
22561void Assembler::vqadd(
22562 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022563 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022564 CheckIT(cond);
22565 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022566 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022567 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22568 if (encoded_dt.IsValid()) {
22569 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22570 EmitT32_32(0xef000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22571 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
22572 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22573 AdvanceIT();
22574 return;
22575 }
22576 }
22577 } else {
22578 // VQADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22579 if (encoded_dt.IsValid()) {
22580 if (cond.Is(al)) {
22581 EmitA32(0xf2000050U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
22582 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
22583 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22584 return;
22585 }
22586 }
22587 }
22588 Delegate(kVqadd, &Assembler::vqadd, cond, dt, rd, rn, rm);
22589}
22590
22591void Assembler::vqdmlal(
22592 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022593 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022594 CheckIT(cond);
22595 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022596 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022597 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22598 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22599 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22600 EmitT32_32(0xef800900U | (encoded_dt.GetEncodingValue() << 20) |
22601 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22602 AdvanceIT();
22603 return;
22604 }
22605 }
22606 } else {
22607 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22608 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22609 if (cond.Is(al)) {
22610 EmitA32(0xf2800900U | (encoded_dt.GetEncodingValue() << 20) |
22611 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22612 return;
22613 }
22614 }
22615 }
22616 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, rm);
22617}
22618
22619void Assembler::vqdmlal(Condition cond,
22620 DataType dt,
22621 QRegister rd,
22622 DRegister rn,
22623 DRegister dm,
22624 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022625 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022626 CheckIT(cond);
22627 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022628 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022629 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22630 if (encoded_dt.IsValid() &&
22631 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22632 (!dt.Is(S16) && (index <= 1))) &&
22633 (dt.Is(S16) || dt.Is(S32))) {
22634 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22635 uint32_t shift = 4;
22636 if (dt.Is(S16)) {
22637 shift = 3;
22638 }
22639 uint32_t mvm = dm.GetCode() | index << shift;
22640 EmitT32_32(0xef800340U | (encoded_dt.GetEncodingValue() << 20) |
22641 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22642 ((mvm & 0x10) << 1));
22643 AdvanceIT();
22644 return;
22645 }
22646 }
22647 } else {
22648 // VQDMLAL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22649 if (encoded_dt.IsValid() &&
22650 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22651 (!dt.Is(S16) && (index <= 1))) &&
22652 (dt.Is(S16) || dt.Is(S32))) {
22653 if (cond.Is(al)) {
22654 uint32_t shift = 4;
22655 if (dt.Is(S16)) {
22656 shift = 3;
22657 }
22658 uint32_t mvm = dm.GetCode() | index << shift;
22659 EmitA32(0xf2800340U | (encoded_dt.GetEncodingValue() << 20) |
22660 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22661 ((mvm & 0x10) << 1));
22662 return;
22663 }
22664 }
22665 }
22666 Delegate(kVqdmlal, &Assembler::vqdmlal, cond, dt, rd, rn, dm, index);
22667}
22668
22669void Assembler::vqdmlsl(
22670 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022671 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022672 CheckIT(cond);
22673 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022674 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022675 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22676 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22677 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22678 EmitT32_32(0xef800b00U | (encoded_dt.GetEncodingValue() << 20) |
22679 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22680 AdvanceIT();
22681 return;
22682 }
22683 }
22684 } else {
22685 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22686 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22687 if (cond.Is(al)) {
22688 EmitA32(0xf2800b00U | (encoded_dt.GetEncodingValue() << 20) |
22689 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22690 return;
22691 }
22692 }
22693 }
22694 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, rm);
22695}
22696
22697void Assembler::vqdmlsl(Condition cond,
22698 DataType dt,
22699 QRegister rd,
22700 DRegister rn,
22701 DRegister dm,
22702 unsigned index) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022703 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022704 CheckIT(cond);
22705 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022706 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022707 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; T2
22708 if (encoded_dt.IsValid() &&
22709 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22710 (!dt.Is(S16) && (index <= 1))) &&
22711 (dt.Is(S16) || dt.Is(S32))) {
22712 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22713 uint32_t shift = 4;
22714 if (dt.Is(S16)) {
22715 shift = 3;
22716 }
22717 uint32_t mvm = dm.GetCode() | index << shift;
22718 EmitT32_32(0xef800740U | (encoded_dt.GetEncodingValue() << 20) |
22719 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22720 ((mvm & 0x10) << 1));
22721 AdvanceIT();
22722 return;
22723 }
22724 }
22725 } else {
22726 // VQDMLSL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm>[<index>] ; A2
22727 if (encoded_dt.IsValid() &&
22728 ((dt.Is(S16) && (index <= 3) && (dm.GetCode() <= 7)) ||
22729 (!dt.Is(S16) && (index <= 1))) &&
22730 (dt.Is(S16) || dt.Is(S32))) {
22731 if (cond.Is(al)) {
22732 uint32_t shift = 4;
22733 if (dt.Is(S16)) {
22734 shift = 3;
22735 }
22736 uint32_t mvm = dm.GetCode() | index << shift;
22737 EmitA32(0xf2800740U | (encoded_dt.GetEncodingValue() << 20) |
22738 rd.Encode(22, 12) | rn.Encode(7, 16) | (mvm & 0xf) |
22739 ((mvm & 0x10) << 1));
22740 return;
22741 }
22742 }
22743 }
22744 Delegate(kVqdmlsl, &Assembler::vqdmlsl, cond, dt, rd, rn, dm, index);
22745}
22746
22747void Assembler::vqdmulh(
22748 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022749 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022750 CheckIT(cond);
22751 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022752 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022753 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
22754 if (encoded_dt.IsValid()) {
22755 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22756 EmitT32_32(0xef000b00U | (encoded_dt.GetEncodingValue() << 20) |
22757 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22758 AdvanceIT();
22759 return;
22760 }
22761 }
22762 } else {
22763 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
22764 if (encoded_dt.IsValid()) {
22765 if (cond.Is(al)) {
22766 EmitA32(0xf2000b00U | (encoded_dt.GetEncodingValue() << 20) |
22767 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22768 return;
22769 }
22770 }
22771 }
22772 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22773}
22774
22775void Assembler::vqdmulh(
22776 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022777 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022778 CheckIT(cond);
22779 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022780 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022781 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
22782 if (encoded_dt.IsValid()) {
22783 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22784 EmitT32_32(0xef000b40U | (encoded_dt.GetEncodingValue() << 20) |
22785 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22786 AdvanceIT();
22787 return;
22788 }
22789 }
22790 } else {
22791 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
22792 if (encoded_dt.IsValid()) {
22793 if (cond.Is(al)) {
22794 EmitA32(0xf2000b40U | (encoded_dt.GetEncodingValue() << 20) |
22795 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22796 return;
22797 }
22798 }
22799 }
22800 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22801}
22802
22803void Assembler::vqdmulh(
22804 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022805 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022806 CheckIT(cond);
22807 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022808 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022809 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
22810 if (encoded_dt.IsValid() &&
22811 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22812 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22813 (rm.GetLane() <= 1))) &&
22814 (dt.Is(S16) || dt.Is(S32))) {
22815 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22816 EmitT32_32(0xef800c40U | (encoded_dt.GetEncodingValue() << 20) |
22817 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22818 AdvanceIT();
22819 return;
22820 }
22821 }
22822 } else {
22823 // VQDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
22824 if (encoded_dt.IsValid() &&
22825 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22826 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22827 (rm.GetLane() <= 1))) &&
22828 (dt.Is(S16) || dt.Is(S32))) {
22829 if (cond.Is(al)) {
22830 EmitA32(0xf2800c40U | (encoded_dt.GetEncodingValue() << 20) |
22831 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22832 return;
22833 }
22834 }
22835 }
22836 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22837}
22838
22839void Assembler::vqdmulh(
22840 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022841 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022842 CheckIT(cond);
22843 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022844 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022845 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
22846 if (encoded_dt.IsValid() &&
22847 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22848 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22849 (rm.GetLane() <= 1))) &&
22850 (dt.Is(S16) || dt.Is(S32))) {
22851 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22852 EmitT32_32(0xff800c40U | (encoded_dt.GetEncodingValue() << 20) |
22853 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22854 AdvanceIT();
22855 return;
22856 }
22857 }
22858 } else {
22859 // VQDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
22860 if (encoded_dt.IsValid() &&
22861 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22862 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22863 (rm.GetLane() <= 1))) &&
22864 (dt.Is(S16) || dt.Is(S32))) {
22865 if (cond.Is(al)) {
22866 EmitA32(0xf3800c40U | (encoded_dt.GetEncodingValue() << 20) |
22867 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22868 return;
22869 }
22870 }
22871 }
22872 Delegate(kVqdmulh, &Assembler::vqdmulh, cond, dt, rd, rn, rm);
22873}
22874
22875void Assembler::vqdmull(
22876 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022877 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022878 CheckIT(cond);
22879 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022880 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022881 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
22882 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22883 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22884 EmitT32_32(0xef800d00U | (encoded_dt.GetEncodingValue() << 20) |
22885 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22886 AdvanceIT();
22887 return;
22888 }
22889 }
22890 } else {
22891 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
22892 if (encoded_dt.IsValid() && (dt.Is(S16) || dt.Is(S32))) {
22893 if (cond.Is(al)) {
22894 EmitA32(0xf2800d00U | (encoded_dt.GetEncodingValue() << 20) |
22895 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
22896 return;
22897 }
22898 }
22899 }
22900 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22901}
22902
22903void Assembler::vqdmull(
22904 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022905 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022906 CheckIT(cond);
22907 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022908 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022909 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; T2
22910 if (encoded_dt.IsValid() &&
22911 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22912 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22913 (rm.GetLane() <= 1))) &&
22914 (dt.Is(S16) || dt.Is(S32))) {
22915 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22916 EmitT32_32(0xef800b40U | (encoded_dt.GetEncodingValue() << 20) |
22917 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22918 AdvanceIT();
22919 return;
22920 }
22921 }
22922 } else {
22923 // VQDMULL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm[x]> ; A2
22924 if (encoded_dt.IsValid() &&
22925 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
22926 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
22927 (rm.GetLane() <= 1))) &&
22928 (dt.Is(S16) || dt.Is(S32))) {
22929 if (cond.Is(al)) {
22930 EmitA32(0xf2800b40U | (encoded_dt.GetEncodingValue() << 20) |
22931 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
22932 return;
22933 }
22934 }
22935 }
22936 Delegate(kVqdmull, &Assembler::vqdmull, cond, dt, rd, rn, rm);
22937}
22938
22939void Assembler::vqmovn(Condition cond,
22940 DataType dt,
22941 DRegister rd,
22942 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022943 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022944 CheckIT(cond);
22945 Dt_op_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022946 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022947 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
22948 if (encoded_dt.IsValid()) {
22949 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22950 EmitT32_32(0xffb20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22951 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22952 rd.Encode(22, 12) | rm.Encode(5, 0));
22953 AdvanceIT();
22954 return;
22955 }
22956 }
22957 } else {
22958 // VQMOVN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
22959 if (encoded_dt.IsValid()) {
22960 if (cond.Is(al)) {
22961 EmitA32(0xf3b20280U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
22962 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
22963 rd.Encode(22, 12) | rm.Encode(5, 0));
22964 return;
22965 }
22966 }
22967 }
22968 Delegate(kVqmovn, &Assembler::vqmovn, cond, dt, rd, rm);
22969}
22970
22971void Assembler::vqmovun(Condition cond,
22972 DataType dt,
22973 DRegister rd,
22974 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070022975 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010022976 CheckIT(cond);
22977 Dt_size_14 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010022978 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010022979 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; T1
22980 if (encoded_dt.IsValid()) {
22981 if (cond.Is(al) || AllowStronglyDiscouraged()) {
22982 EmitT32_32(0xffb20240U | (encoded_dt.GetEncodingValue() << 18) |
22983 rd.Encode(22, 12) | rm.Encode(5, 0));
22984 AdvanceIT();
22985 return;
22986 }
22987 }
22988 } else {
22989 // VQMOVUN{<c>}{<q>}.<dt> <Dd>, <Qm> ; A1
22990 if (encoded_dt.IsValid()) {
22991 if (cond.Is(al)) {
22992 EmitA32(0xf3b20240U | (encoded_dt.GetEncodingValue() << 18) |
22993 rd.Encode(22, 12) | rm.Encode(5, 0));
22994 return;
22995 }
22996 }
22997 }
22998 Delegate(kVqmovun, &Assembler::vqmovun, cond, dt, rd, rm);
22999}
23000
23001void Assembler::vqneg(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023002 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023003 CheckIT(cond);
23004 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023005 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023006 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23007 if (encoded_dt.IsValid()) {
23008 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23009 EmitT32_32(0xffb00780U | (encoded_dt.GetEncodingValue() << 18) |
23010 rd.Encode(22, 12) | rm.Encode(5, 0));
23011 AdvanceIT();
23012 return;
23013 }
23014 }
23015 } else {
23016 // VQNEG{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23017 if (encoded_dt.IsValid()) {
23018 if (cond.Is(al)) {
23019 EmitA32(0xf3b00780U | (encoded_dt.GetEncodingValue() << 18) |
23020 rd.Encode(22, 12) | rm.Encode(5, 0));
23021 return;
23022 }
23023 }
23024 }
23025 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23026}
23027
23028void Assembler::vqneg(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023029 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023030 CheckIT(cond);
23031 Dt_size_5 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023032 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023033 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23034 if (encoded_dt.IsValid()) {
23035 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23036 EmitT32_32(0xffb007c0U | (encoded_dt.GetEncodingValue() << 18) |
23037 rd.Encode(22, 12) | rm.Encode(5, 0));
23038 AdvanceIT();
23039 return;
23040 }
23041 }
23042 } else {
23043 // VQNEG{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23044 if (encoded_dt.IsValid()) {
23045 if (cond.Is(al)) {
23046 EmitA32(0xf3b007c0U | (encoded_dt.GetEncodingValue() << 18) |
23047 rd.Encode(22, 12) | rm.Encode(5, 0));
23048 return;
23049 }
23050 }
23051 }
23052 Delegate(kVqneg, &Assembler::vqneg, cond, dt, rd, rm);
23053}
23054
23055void Assembler::vqrdmulh(
23056 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023057 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023058 CheckIT(cond);
23059 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023060 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023061 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23062 if (encoded_dt.IsValid()) {
23063 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23064 EmitT32_32(0xff000b00U | (encoded_dt.GetEncodingValue() << 20) |
23065 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23066 AdvanceIT();
23067 return;
23068 }
23069 }
23070 } else {
23071 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23072 if (encoded_dt.IsValid()) {
23073 if (cond.Is(al)) {
23074 EmitA32(0xf3000b00U | (encoded_dt.GetEncodingValue() << 20) |
23075 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23076 return;
23077 }
23078 }
23079 }
23080 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23081}
23082
23083void Assembler::vqrdmulh(
23084 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023085 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023086 CheckIT(cond);
23087 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023088 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023089 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23090 if (encoded_dt.IsValid()) {
23091 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23092 EmitT32_32(0xff000b40U | (encoded_dt.GetEncodingValue() << 20) |
23093 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23094 AdvanceIT();
23095 return;
23096 }
23097 }
23098 } else {
23099 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23100 if (encoded_dt.IsValid()) {
23101 if (cond.Is(al)) {
23102 EmitA32(0xf3000b40U | (encoded_dt.GetEncodingValue() << 20) |
23103 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23104 return;
23105 }
23106 }
23107 }
23108 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23109}
23110
23111void Assembler::vqrdmulh(
23112 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023113 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023114 CheckIT(cond);
23115 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023116 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023117 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; T2
23118 if (encoded_dt.IsValid() &&
23119 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23120 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23121 (rm.GetLane() <= 1))) &&
23122 (dt.Is(S16) || dt.Is(S32))) {
23123 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23124 EmitT32_32(0xef800d40U | (encoded_dt.GetEncodingValue() << 20) |
23125 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23126 AdvanceIT();
23127 return;
23128 }
23129 }
23130 } else {
23131 // VQRDMULH{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm[x]> ; A2
23132 if (encoded_dt.IsValid() &&
23133 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23134 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23135 (rm.GetLane() <= 1))) &&
23136 (dt.Is(S16) || dt.Is(S32))) {
23137 if (cond.Is(al)) {
23138 EmitA32(0xf2800d40U | (encoded_dt.GetEncodingValue() << 20) |
23139 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23140 return;
23141 }
23142 }
23143 }
23144 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23145}
23146
23147void Assembler::vqrdmulh(
23148 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegisterLane rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023149 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023150 CheckIT(cond);
23151 Dt_size_13 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023152 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023153 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; T2
23154 if (encoded_dt.IsValid() &&
23155 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23156 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23157 (rm.GetLane() <= 1))) &&
23158 (dt.Is(S16) || dt.Is(S32))) {
23159 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23160 EmitT32_32(0xff800d40U | (encoded_dt.GetEncodingValue() << 20) |
23161 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23162 AdvanceIT();
23163 return;
23164 }
23165 }
23166 } else {
23167 // VQRDMULH{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm[x]> ; A2
23168 if (encoded_dt.IsValid() &&
23169 (((dt.GetSize() == 16) && (rm.GetCode() <= 7) && (rm.GetLane() <= 3)) ||
23170 ((dt.GetSize() == 32) && (rm.GetCode() <= 15) &&
23171 (rm.GetLane() <= 1))) &&
23172 (dt.Is(S16) || dt.Is(S32))) {
23173 if (cond.Is(al)) {
23174 EmitA32(0xf3800d40U | (encoded_dt.GetEncodingValue() << 20) |
23175 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.EncodeX(dt, 5, 0));
23176 return;
23177 }
23178 }
23179 }
23180 Delegate(kVqrdmulh, &Assembler::vqrdmulh, cond, dt, rd, rn, rm);
23181}
23182
23183void Assembler::vqrshl(
23184 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023186 CheckIT(cond);
23187 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023188 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023189 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23190 if (encoded_dt.IsValid()) {
23191 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23192 EmitT32_32(0xef000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23193 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23194 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23195 AdvanceIT();
23196 return;
23197 }
23198 }
23199 } else {
23200 // VQRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23201 if (encoded_dt.IsValid()) {
23202 if (cond.Is(al)) {
23203 EmitA32(0xf2000510U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23204 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23205 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23206 return;
23207 }
23208 }
23209 }
23210 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23211}
23212
23213void Assembler::vqrshl(
23214 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023215 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023216 CheckIT(cond);
23217 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023218 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023219 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23220 if (encoded_dt.IsValid()) {
23221 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23222 EmitT32_32(0xef000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23223 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23224 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23225 AdvanceIT();
23226 return;
23227 }
23228 }
23229 } else {
23230 // VQRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23231 if (encoded_dt.IsValid()) {
23232 if (cond.Is(al)) {
23233 EmitA32(0xf2000550U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23234 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23235 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23236 return;
23237 }
23238 }
23239 }
23240 Delegate(kVqrshl, &Assembler::vqrshl, cond, dt, rd, rm, rn);
23241}
23242
23243void Assembler::vqrshrn(Condition cond,
23244 DataType dt,
23245 DRegister rd,
23246 QRegister rm,
23247 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023248 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023249 CheckIT(cond);
23250 if (operand.IsImmediate()) {
23251 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23252 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23253 Dt_op_size_3 encoded_dt(dt);
23254 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023255 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023256 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23257 if (encoded_dt.IsValid() && (imm == 0)) {
23258 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23259 EmitT32_32(0xffb20280U |
23260 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23261 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23262 rd.Encode(22, 12) | rm.Encode(5, 0));
23263 AdvanceIT();
23264 return;
23265 }
23266 }
23267 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23268 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23269 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23270 uint32_t imm6 = dt.GetSize() / 2 - imm;
23271 EmitT32_32(0xef800950U |
23272 (encoded_dt_2.GetTypeEncodingValue() << 28) |
23273 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23274 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23275 AdvanceIT();
23276 return;
23277 }
23278 }
23279 } else {
23280 // VQRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23281 if (encoded_dt.IsValid() && (imm == 0)) {
23282 if (cond.Is(al)) {
23283 EmitA32(0xf3b20280U |
23284 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23285 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23286 rd.Encode(22, 12) | rm.Encode(5, 0));
23287 return;
23288 }
23289 }
23290 // VQRSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23291 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23292 if (cond.Is(al)) {
23293 uint32_t imm6 = dt.GetSize() / 2 - imm;
23294 EmitA32(0xf2800950U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23295 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23296 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23297 return;
23298 }
23299 }
23300 }
23301 }
23302 }
23303 Delegate(kVqrshrn, &Assembler::vqrshrn, cond, dt, rd, rm, operand);
23304}
23305
23306void Assembler::vqrshrun(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_imm6_2 encoded_dt(dt);
23317 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023318 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023319 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23320 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23321 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23322 uint32_t imm6 = dt.GetSize() / 2 - imm;
23323 EmitT32_32(0xff800850U | (encoded_dt.GetTypeEncodingValue() << 28) |
23324 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23325 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23326 AdvanceIT();
23327 return;
23328 }
23329 }
23330 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23331 if (encoded_dt_2.IsValid() && (imm == 0)) {
23332 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23333 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23334 rd.Encode(22, 12) | rm.Encode(5, 0));
23335 AdvanceIT();
23336 return;
23337 }
23338 }
23339 } else {
23340 // VQRSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23341 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23342 if (cond.Is(al)) {
23343 uint32_t imm6 = dt.GetSize() / 2 - imm;
23344 EmitA32(0xf3800850U | (encoded_dt.GetTypeEncodingValue() << 24) |
23345 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23346 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23347 return;
23348 }
23349 }
23350 // VQRSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23351 if (encoded_dt_2.IsValid() && (imm == 0)) {
23352 if (cond.Is(al)) {
23353 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23354 rd.Encode(22, 12) | rm.Encode(5, 0));
23355 return;
23356 }
23357 }
23358 }
23359 }
23360 }
23361 Delegate(kVqrshrun, &Assembler::vqrshrun, cond, dt, rd, rm, operand);
23362}
23363
23364void Assembler::vqshl(Condition cond,
23365 DataType dt,
23366 DRegister rd,
23367 DRegister rm,
23368 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023369 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023370 CheckIT(cond);
23371 if (operand.IsRegister()) {
23372 DRegister rn = operand.GetRegister();
23373 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023374 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023375 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
23376 if (encoded_dt.IsValid()) {
23377 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23378 EmitT32_32(0xef000410U |
23379 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23380 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23381 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23382 AdvanceIT();
23383 return;
23384 }
23385 }
23386 } else {
23387 // VQSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
23388 if (encoded_dt.IsValid()) {
23389 if (cond.Is(al)) {
23390 EmitA32(0xf2000410U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23391 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23392 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23393 return;
23394 }
23395 }
23396 }
23397 }
23398 if (operand.IsImmediate()) {
23399 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23400 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23401 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023402 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023403 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23404 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23405 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23406 uint32_t imm6 = imm;
23407 EmitT32_32(0xef800710U | (encoded_dt.GetTypeEncodingValue() << 28) |
23408 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23409 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23410 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23411 AdvanceIT();
23412 return;
23413 }
23414 }
23415 } else {
23416 // VQSHL{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23417 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23418 if (cond.Is(al)) {
23419 uint32_t imm6 = imm;
23420 EmitA32(0xf2800710U | (encoded_dt.GetTypeEncodingValue() << 24) |
23421 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23422 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23423 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23424 return;
23425 }
23426 }
23427 }
23428 }
23429 }
23430 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23431}
23432
23433void Assembler::vqshl(Condition cond,
23434 DataType dt,
23435 QRegister rd,
23436 QRegister rm,
23437 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023438 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023439 CheckIT(cond);
23440 if (operand.IsRegister()) {
23441 QRegister rn = operand.GetRegister();
23442 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023443 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023444 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
23445 if (encoded_dt.IsValid()) {
23446 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23447 EmitT32_32(0xef000450U |
23448 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23449 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23450 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23451 AdvanceIT();
23452 return;
23453 }
23454 }
23455 } else {
23456 // VQSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
23457 if (encoded_dt.IsValid()) {
23458 if (cond.Is(al)) {
23459 EmitA32(0xf2000450U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23460 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23461 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
23462 return;
23463 }
23464 }
23465 }
23466 }
23467 if (operand.IsImmediate()) {
23468 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23469 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23470 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023471 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023472 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23473 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23474 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23475 uint32_t imm6 = imm;
23476 EmitT32_32(0xef800750U | (encoded_dt.GetTypeEncodingValue() << 28) |
23477 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23478 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23479 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23480 AdvanceIT();
23481 return;
23482 }
23483 }
23484 } else {
23485 // VQSHL{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23486 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23487 if (cond.Is(al)) {
23488 uint32_t imm6 = imm;
23489 EmitA32(0xf2800750U | (encoded_dt.GetTypeEncodingValue() << 24) |
23490 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23491 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23492 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23493 return;
23494 }
23495 }
23496 }
23497 }
23498 }
23499 Delegate(kVqshl, &Assembler::vqshl, cond, dt, rd, rm, operand);
23500}
23501
23502void Assembler::vqshlu(Condition cond,
23503 DataType dt,
23504 DRegister rd,
23505 DRegister rm,
23506 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023507 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023508 CheckIT(cond);
23509 if (operand.IsImmediate()) {
23510 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23511 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23512 Dt_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023513 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023514 // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
23515 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23516 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23517 uint32_t imm6 = imm;
23518 EmitT32_32(0xef800610U | (encoded_dt.GetTypeEncodingValue() << 28) |
23519 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23520 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23521 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23522 AdvanceIT();
23523 return;
23524 }
23525 }
23526 } else {
23527 // VQSHLU{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
23528 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23529 if (cond.Is(al)) {
23530 uint32_t imm6 = imm;
23531 EmitA32(0xf2800610U | (encoded_dt.GetTypeEncodingValue() << 24) |
23532 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23533 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23534 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23535 return;
23536 }
23537 }
23538 }
23539 }
23540 }
23541 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23542}
23543
23544void Assembler::vqshlu(Condition cond,
23545 DataType dt,
23546 QRegister rd,
23547 QRegister rm,
23548 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023549 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023550 CheckIT(cond);
23551 if (operand.IsImmediate()) {
23552 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23553 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23554 Dt_L_imm6_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023555 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023556 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
23557 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23558 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23559 uint32_t imm6 = imm;
23560 EmitT32_32(0xef800650U | (encoded_dt.GetTypeEncodingValue() << 28) |
23561 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23562 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23563 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23564 AdvanceIT();
23565 return;
23566 }
23567 }
23568 } else {
23569 // VQSHLU{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
23570 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
23571 if (cond.Is(al)) {
23572 uint32_t imm6 = imm;
23573 EmitA32(0xf2800650U | (encoded_dt.GetTypeEncodingValue() << 24) |
23574 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23575 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
23576 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23577 return;
23578 }
23579 }
23580 }
23581 }
23582 }
23583 Delegate(kVqshlu, &Assembler::vqshlu, cond, dt, rd, rm, operand);
23584}
23585
23586void Assembler::vqshrn(Condition cond,
23587 DataType dt,
23588 DRegister rd,
23589 QRegister rm,
23590 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023591 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023592 CheckIT(cond);
23593 if (operand.IsImmediate()) {
23594 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
23595 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
23596 Dt_op_size_3 encoded_dt(dt);
23597 Dt_imm6_1 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023598 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023599 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23600 if (encoded_dt.IsValid() && (imm == 0)) {
23601 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23602 EmitT32_32(0xffb20280U |
23603 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23604 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23605 rd.Encode(22, 12) | rm.Encode(5, 0));
23606 AdvanceIT();
23607 return;
23608 }
23609 }
23610 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23611 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23612 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23613 uint32_t imm6 = dt.GetSize() / 2 - imm;
23614 EmitT32_32(0xef800910U |
23615 (encoded_dt_2.GetTypeEncodingValue() << 28) |
23616 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23617 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23618 AdvanceIT();
23619 return;
23620 }
23621 }
23622 } else {
23623 // VQSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23624 if (encoded_dt.IsValid() && (imm == 0)) {
23625 if (cond.Is(al)) {
23626 EmitA32(0xf3b20280U |
23627 ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23628 ((encoded_dt.GetEncodingValue() & 0xc) << 4) |
23629 rd.Encode(22, 12) | rm.Encode(5, 0));
23630 return;
23631 }
23632 }
23633 // VQSHRN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23634 if (encoded_dt_2.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23635 if (cond.Is(al)) {
23636 uint32_t imm6 = dt.GetSize() / 2 - imm;
23637 EmitA32(0xf2800910U | (encoded_dt_2.GetTypeEncodingValue() << 24) |
23638 ((encoded_dt_2.GetEncodingValue() & 0x7) << 19) |
23639 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23640 return;
23641 }
23642 }
23643 }
23644 }
23645 }
23646 Delegate(kVqshrn, &Assembler::vqshrn, cond, dt, rd, rm, operand);
23647}
23648
23649void Assembler::vqshrun(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_imm6_2 encoded_dt(dt);
23660 Dt_size_14 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023661 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023662 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; T1
23663 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23664 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23665 uint32_t imm6 = dt.GetSize() / 2 - imm;
23666 EmitT32_32(0xff800810U | (encoded_dt.GetTypeEncodingValue() << 28) |
23667 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23668 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23669 AdvanceIT();
23670 return;
23671 }
23672 }
23673 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
23674 if (encoded_dt_2.IsValid() && (imm == 0)) {
23675 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23676 EmitT32_32(0xffb20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23677 rd.Encode(22, 12) | rm.Encode(5, 0));
23678 AdvanceIT();
23679 return;
23680 }
23681 }
23682 } else {
23683 // VQSHRUN{<c>}{<q>}.<type><size> <Dd>, <Qm>, #<imm> ; A1
23684 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
23685 if (cond.Is(al)) {
23686 uint32_t imm6 = dt.GetSize() / 2 - imm;
23687 EmitA32(0xf3800810U | (encoded_dt.GetTypeEncodingValue() << 24) |
23688 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
23689 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
23690 return;
23691 }
23692 }
23693 // VQSHRUN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
23694 if (encoded_dt_2.IsValid() && (imm == 0)) {
23695 if (cond.Is(al)) {
23696 EmitA32(0xf3b20240U | (encoded_dt_2.GetEncodingValue() << 18) |
23697 rd.Encode(22, 12) | rm.Encode(5, 0));
23698 return;
23699 }
23700 }
23701 }
23702 }
23703 }
23704 Delegate(kVqshrun, &Assembler::vqshrun, cond, dt, rd, rm, operand);
23705}
23706
23707void Assembler::vqsub(
23708 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023709 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023710 CheckIT(cond);
23711 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023712 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023713 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
23714 if (encoded_dt.IsValid()) {
23715 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23716 EmitT32_32(0xef000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23717 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23718 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23719 AdvanceIT();
23720 return;
23721 }
23722 }
23723 } else {
23724 // VQSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
23725 if (encoded_dt.IsValid()) {
23726 if (cond.Is(al)) {
23727 EmitA32(0xf2000210U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23728 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23729 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23730 return;
23731 }
23732 }
23733 }
23734 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23735}
23736
23737void Assembler::vqsub(
23738 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023739 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023740 CheckIT(cond);
23741 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023742 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023743 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
23744 if (encoded_dt.IsValid()) {
23745 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23746 EmitT32_32(0xef000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23747 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
23748 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23749 AdvanceIT();
23750 return;
23751 }
23752 }
23753 } else {
23754 // VQSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
23755 if (encoded_dt.IsValid()) {
23756 if (cond.Is(al)) {
23757 EmitA32(0xf2000250U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
23758 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
23759 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23760 return;
23761 }
23762 }
23763 }
23764 Delegate(kVqsub, &Assembler::vqsub, cond, dt, rd, rn, rm);
23765}
23766
23767void Assembler::vraddhn(
23768 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023769 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023770 CheckIT(cond);
23771 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023772 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023773 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
23774 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23775 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23776 EmitT32_32(0xff800400U | (encoded_dt.GetEncodingValue() << 20) |
23777 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23778 AdvanceIT();
23779 return;
23780 }
23781 }
23782 } else {
23783 // VRADDHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
23784 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
23785 if (cond.Is(al)) {
23786 EmitA32(0xf3800400U | (encoded_dt.GetEncodingValue() << 20) |
23787 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
23788 return;
23789 }
23790 }
23791 }
23792 Delegate(kVraddhn, &Assembler::vraddhn, cond, dt, rd, rn, rm);
23793}
23794
23795void Assembler::vrecpe(Condition cond,
23796 DataType dt,
23797 DRegister rd,
23798 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023799 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023800 CheckIT(cond);
23801 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023802 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023803 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23804 if (encoded_dt.IsValid()) {
23805 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23806 EmitT32_32(0xffb30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23807 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23808 rd.Encode(22, 12) | rm.Encode(5, 0));
23809 AdvanceIT();
23810 return;
23811 }
23812 }
23813 } else {
23814 // VRECPE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23815 if (encoded_dt.IsValid()) {
23816 if (cond.Is(al)) {
23817 EmitA32(0xf3b30400U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23818 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23819 rd.Encode(22, 12) | rm.Encode(5, 0));
23820 return;
23821 }
23822 }
23823 }
23824 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23825}
23826
23827void Assembler::vrecpe(Condition cond,
23828 DataType dt,
23829 QRegister rd,
23830 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023831 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023832 CheckIT(cond);
23833 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023834 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023835 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23836 if (encoded_dt.IsValid()) {
23837 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23838 EmitT32_32(0xffb30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23839 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23840 rd.Encode(22, 12) | rm.Encode(5, 0));
23841 AdvanceIT();
23842 return;
23843 }
23844 }
23845 } else {
23846 // VRECPE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23847 if (encoded_dt.IsValid()) {
23848 if (cond.Is(al)) {
23849 EmitA32(0xf3b30440U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
23850 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
23851 rd.Encode(22, 12) | rm.Encode(5, 0));
23852 return;
23853 }
23854 }
23855 }
23856 Delegate(kVrecpe, &Assembler::vrecpe, cond, dt, rd, rm);
23857}
23858
23859void Assembler::vrecps(
23860 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023861 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023862 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023863 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023864 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
23865 if (dt.Is(F32)) {
23866 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23867 EmitT32_32(0xef000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23868 rm.Encode(5, 0));
23869 AdvanceIT();
23870 return;
23871 }
23872 }
23873 } else {
23874 // VRECPS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
23875 if (dt.Is(F32)) {
23876 if (cond.Is(al)) {
23877 EmitA32(0xf2000f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23878 rm.Encode(5, 0));
23879 return;
23880 }
23881 }
23882 }
23883 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23884}
23885
23886void Assembler::vrecps(
23887 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023888 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023889 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023890 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023891 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
23892 if (dt.Is(F32)) {
23893 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23894 EmitT32_32(0xef000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23895 rm.Encode(5, 0));
23896 AdvanceIT();
23897 return;
23898 }
23899 }
23900 } else {
23901 // VRECPS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
23902 if (dt.Is(F32)) {
23903 if (cond.Is(al)) {
23904 EmitA32(0xf2000f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
23905 rm.Encode(5, 0));
23906 return;
23907 }
23908 }
23909 }
23910 Delegate(kVrecps, &Assembler::vrecps, cond, dt, rd, rn, rm);
23911}
23912
23913void Assembler::vrev16(Condition cond,
23914 DataType dt,
23915 DRegister rd,
23916 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023917 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023918 CheckIT(cond);
23919 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023920 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023921 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23922 if (encoded_dt.IsValid()) {
23923 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23924 EmitT32_32(0xffb00100U | (encoded_dt.GetEncodingValue() << 18) |
23925 rd.Encode(22, 12) | rm.Encode(5, 0));
23926 AdvanceIT();
23927 return;
23928 }
23929 }
23930 } else {
23931 // VREV16{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23932 if (encoded_dt.IsValid()) {
23933 if (cond.Is(al)) {
23934 EmitA32(0xf3b00100U | (encoded_dt.GetEncodingValue() << 18) |
23935 rd.Encode(22, 12) | rm.Encode(5, 0));
23936 return;
23937 }
23938 }
23939 }
23940 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
23941}
23942
23943void Assembler::vrev16(Condition cond,
23944 DataType dt,
23945 QRegister rd,
23946 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023947 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023948 CheckIT(cond);
23949 Dt_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023950 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023951 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
23952 if (encoded_dt.IsValid()) {
23953 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23954 EmitT32_32(0xffb00140U | (encoded_dt.GetEncodingValue() << 18) |
23955 rd.Encode(22, 12) | rm.Encode(5, 0));
23956 AdvanceIT();
23957 return;
23958 }
23959 }
23960 } else {
23961 // VREV16{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
23962 if (encoded_dt.IsValid()) {
23963 if (cond.Is(al)) {
23964 EmitA32(0xf3b00140U | (encoded_dt.GetEncodingValue() << 18) |
23965 rd.Encode(22, 12) | rm.Encode(5, 0));
23966 return;
23967 }
23968 }
23969 }
23970 Delegate(kVrev16, &Assembler::vrev16, cond, dt, rd, rm);
23971}
23972
23973void Assembler::vrev32(Condition cond,
23974 DataType dt,
23975 DRegister rd,
23976 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070023977 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010023978 CheckIT(cond);
23979 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010023980 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010023981 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
23982 if (encoded_dt.IsValid()) {
23983 if (cond.Is(al) || AllowStronglyDiscouraged()) {
23984 EmitT32_32(0xffb00080U | (encoded_dt.GetEncodingValue() << 18) |
23985 rd.Encode(22, 12) | rm.Encode(5, 0));
23986 AdvanceIT();
23987 return;
23988 }
23989 }
23990 } else {
23991 // VREV32{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
23992 if (encoded_dt.IsValid()) {
23993 if (cond.Is(al)) {
23994 EmitA32(0xf3b00080U | (encoded_dt.GetEncodingValue() << 18) |
23995 rd.Encode(22, 12) | rm.Encode(5, 0));
23996 return;
23997 }
23998 }
23999 }
24000 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24001}
24002
24003void Assembler::vrev32(Condition cond,
24004 DataType dt,
24005 QRegister rd,
24006 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024007 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024008 CheckIT(cond);
24009 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024010 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024011 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24012 if (encoded_dt.IsValid()) {
24013 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24014 EmitT32_32(0xffb000c0U | (encoded_dt.GetEncodingValue() << 18) |
24015 rd.Encode(22, 12) | rm.Encode(5, 0));
24016 AdvanceIT();
24017 return;
24018 }
24019 }
24020 } else {
24021 // VREV32{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24022 if (encoded_dt.IsValid()) {
24023 if (cond.Is(al)) {
24024 EmitA32(0xf3b000c0U | (encoded_dt.GetEncodingValue() << 18) |
24025 rd.Encode(22, 12) | rm.Encode(5, 0));
24026 return;
24027 }
24028 }
24029 }
24030 Delegate(kVrev32, &Assembler::vrev32, cond, dt, rd, rm);
24031}
24032
24033void Assembler::vrev64(Condition cond,
24034 DataType dt,
24035 DRegister rd,
24036 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024037 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024038 CheckIT(cond);
24039 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024040 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024041 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24042 if (encoded_dt.IsValid()) {
24043 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24044 EmitT32_32(0xffb00000U | (encoded_dt.GetEncodingValue() << 18) |
24045 rd.Encode(22, 12) | rm.Encode(5, 0));
24046 AdvanceIT();
24047 return;
24048 }
24049 }
24050 } else {
24051 // VREV64{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24052 if (encoded_dt.IsValid()) {
24053 if (cond.Is(al)) {
24054 EmitA32(0xf3b00000U | (encoded_dt.GetEncodingValue() << 18) |
24055 rd.Encode(22, 12) | rm.Encode(5, 0));
24056 return;
24057 }
24058 }
24059 }
24060 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24061}
24062
24063void Assembler::vrev64(Condition cond,
24064 DataType dt,
24065 QRegister rd,
24066 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024067 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024068 CheckIT(cond);
24069 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024070 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024071 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24072 if (encoded_dt.IsValid()) {
24073 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24074 EmitT32_32(0xffb00040U | (encoded_dt.GetEncodingValue() << 18) |
24075 rd.Encode(22, 12) | rm.Encode(5, 0));
24076 AdvanceIT();
24077 return;
24078 }
24079 }
24080 } else {
24081 // VREV64{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24082 if (encoded_dt.IsValid()) {
24083 if (cond.Is(al)) {
24084 EmitA32(0xf3b00040U | (encoded_dt.GetEncodingValue() << 18) |
24085 rd.Encode(22, 12) | rm.Encode(5, 0));
24086 return;
24087 }
24088 }
24089 }
24090 Delegate(kVrev64, &Assembler::vrev64, cond, dt, rd, rm);
24091}
24092
24093void Assembler::vrhadd(
24094 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024095 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024096 CheckIT(cond);
24097 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024098 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024099 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
24100 if (encoded_dt.IsValid()) {
24101 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24102 EmitT32_32(0xef000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24103 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24104 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24105 AdvanceIT();
24106 return;
24107 }
24108 }
24109 } else {
24110 // VRHADD{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
24111 if (encoded_dt.IsValid()) {
24112 if (cond.Is(al)) {
24113 EmitA32(0xf2000100U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24114 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24115 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24116 return;
24117 }
24118 }
24119 }
24120 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24121}
24122
24123void Assembler::vrhadd(
24124 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024125 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024126 CheckIT(cond);
24127 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024128 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024129 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
24130 if (encoded_dt.IsValid()) {
24131 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24132 EmitT32_32(0xef000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24133 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24134 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24135 AdvanceIT();
24136 return;
24137 }
24138 }
24139 } else {
24140 // VRHADD{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
24141 if (encoded_dt.IsValid()) {
24142 if (cond.Is(al)) {
24143 EmitA32(0xf2000140U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24144 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24145 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
24146 return;
24147 }
24148 }
24149 }
24150 Delegate(kVrhadd, &Assembler::vrhadd, cond, dt, rd, rn, rm);
24151}
24152
24153void Assembler::vrinta(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024154 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024155 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024156 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024157 // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; T1
24158 if (dt1.Is(F32) && dt2.Is(F32)) {
24159 EmitT32_32(0xffba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
24160 AdvanceIT();
24161 return;
24162 }
24163 // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; T1
24164 if (dt1.Is(F64) && dt2.Is(F64)) {
24165 EmitT32_32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24166 AdvanceIT();
24167 return;
24168 }
24169 } else {
24170 // VRINTA{<q>}.F32.F32 <Dd>, <Dm> ; A1
24171 if (dt1.Is(F32) && dt2.Is(F32)) {
24172 EmitA32(0xf3ba0500U | rd.Encode(22, 12) | rm.Encode(5, 0));
24173 return;
24174 }
24175 // VRINTA{<q>}.F64.F64 <Dd>, <Dm> ; A1
24176 if (dt1.Is(F64) && dt2.Is(F64)) {
24177 EmitA32(0xfeb80b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24178 return;
24179 }
24180 }
24181 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24182}
24183
24184void Assembler::vrinta(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024185 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024186 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024187 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024188 // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; T1
24189 if (dt1.Is(F32) && dt2.Is(F32)) {
24190 EmitT32_32(0xffba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
24191 AdvanceIT();
24192 return;
24193 }
24194 } else {
24195 // VRINTA{<q>}.F32.F32 <Qd>, <Qm> ; A1
24196 if (dt1.Is(F32) && dt2.Is(F32)) {
24197 EmitA32(0xf3ba0540U | rd.Encode(22, 12) | rm.Encode(5, 0));
24198 return;
24199 }
24200 }
24201 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24202}
24203
24204void Assembler::vrinta(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024205 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024206 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024207 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024208 // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; T1
24209 if (dt1.Is(F32) && dt2.Is(F32)) {
24210 EmitT32_32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24211 AdvanceIT();
24212 return;
24213 }
24214 } else {
24215 // VRINTA{<q>}.F32.F32 <Sd>, <Sm> ; A1
24216 if (dt1.Is(F32) && dt2.Is(F32)) {
24217 EmitA32(0xfeb80a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24218 return;
24219 }
24220 }
24221 Delegate(kVrinta, &Assembler::vrinta, dt1, dt2, rd, rm);
24222}
24223
24224void Assembler::vrintm(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024225 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024226 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024227 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024228 // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; T1
24229 if (dt1.Is(F32) && dt2.Is(F32)) {
24230 EmitT32_32(0xffba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
24231 AdvanceIT();
24232 return;
24233 }
24234 // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; T1
24235 if (dt1.Is(F64) && dt2.Is(F64)) {
24236 EmitT32_32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24237 AdvanceIT();
24238 return;
24239 }
24240 } else {
24241 // VRINTM{<q>}.F32.F32 <Dd>, <Dm> ; A1
24242 if (dt1.Is(F32) && dt2.Is(F32)) {
24243 EmitA32(0xf3ba0680U | rd.Encode(22, 12) | rm.Encode(5, 0));
24244 return;
24245 }
24246 // VRINTM{<q>}.F64.F64 <Dd>, <Dm> ; A1
24247 if (dt1.Is(F64) && dt2.Is(F64)) {
24248 EmitA32(0xfebb0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24249 return;
24250 }
24251 }
24252 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24253}
24254
24255void Assembler::vrintm(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024256 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024257 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024258 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024259 // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; T1
24260 if (dt1.Is(F32) && dt2.Is(F32)) {
24261 EmitT32_32(0xffba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24262 AdvanceIT();
24263 return;
24264 }
24265 } else {
24266 // VRINTM{<q>}.F32.F32 <Qd>, <Qm> ; A1
24267 if (dt1.Is(F32) && dt2.Is(F32)) {
24268 EmitA32(0xf3ba06c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24269 return;
24270 }
24271 }
24272 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24273}
24274
24275void Assembler::vrintm(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024276 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024277 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024278 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024279 // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; T1
24280 if (dt1.Is(F32) && dt2.Is(F32)) {
24281 EmitT32_32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24282 AdvanceIT();
24283 return;
24284 }
24285 } else {
24286 // VRINTM{<q>}.F32.F32 <Sd>, <Sm> ; A1
24287 if (dt1.Is(F32) && dt2.Is(F32)) {
24288 EmitA32(0xfebb0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24289 return;
24290 }
24291 }
24292 Delegate(kVrintm, &Assembler::vrintm, dt1, dt2, rd, rm);
24293}
24294
24295void Assembler::vrintn(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024296 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024297 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024298 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024299 // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; T1
24300 if (dt1.Is(F32) && dt2.Is(F32)) {
24301 EmitT32_32(0xffba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
24302 AdvanceIT();
24303 return;
24304 }
24305 // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; T1
24306 if (dt1.Is(F64) && dt2.Is(F64)) {
24307 EmitT32_32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24308 AdvanceIT();
24309 return;
24310 }
24311 } else {
24312 // VRINTN{<q>}.F32.F32 <Dd>, <Dm> ; A1
24313 if (dt1.Is(F32) && dt2.Is(F32)) {
24314 EmitA32(0xf3ba0400U | rd.Encode(22, 12) | rm.Encode(5, 0));
24315 return;
24316 }
24317 // VRINTN{<q>}.F64.F64 <Dd>, <Dm> ; A1
24318 if (dt1.Is(F64) && dt2.Is(F64)) {
24319 EmitA32(0xfeb90b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24320 return;
24321 }
24322 }
24323 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24324}
24325
24326void Assembler::vrintn(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024327 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024328 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024329 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024330 // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; T1
24331 if (dt1.Is(F32) && dt2.Is(F32)) {
24332 EmitT32_32(0xffba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
24333 AdvanceIT();
24334 return;
24335 }
24336 } else {
24337 // VRINTN{<q>}.F32.F32 <Qd>, <Qm> ; A1
24338 if (dt1.Is(F32) && dt2.Is(F32)) {
24339 EmitA32(0xf3ba0440U | rd.Encode(22, 12) | rm.Encode(5, 0));
24340 return;
24341 }
24342 }
24343 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24344}
24345
24346void Assembler::vrintn(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024347 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024348 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024349 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024350 // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; T1
24351 if (dt1.Is(F32) && dt2.Is(F32)) {
24352 EmitT32_32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24353 AdvanceIT();
24354 return;
24355 }
24356 } else {
24357 // VRINTN{<q>}.F32.F32 <Sd>, <Sm> ; A1
24358 if (dt1.Is(F32) && dt2.Is(F32)) {
24359 EmitA32(0xfeb90a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24360 return;
24361 }
24362 }
24363 Delegate(kVrintn, &Assembler::vrintn, dt1, dt2, rd, rm);
24364}
24365
24366void Assembler::vrintp(DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024367 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024368 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024369 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024370 // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; T1
24371 if (dt1.Is(F32) && dt2.Is(F32)) {
24372 EmitT32_32(0xffba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
24373 AdvanceIT();
24374 return;
24375 }
24376 // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; T1
24377 if (dt1.Is(F64) && dt2.Is(F64)) {
24378 EmitT32_32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24379 AdvanceIT();
24380 return;
24381 }
24382 } else {
24383 // VRINTP{<q>}.F32.F32 <Dd>, <Dm> ; A1
24384 if (dt1.Is(F32) && dt2.Is(F32)) {
24385 EmitA32(0xf3ba0780U | rd.Encode(22, 12) | rm.Encode(5, 0));
24386 return;
24387 }
24388 // VRINTP{<q>}.F64.F64 <Dd>, <Dm> ; A1
24389 if (dt1.Is(F64) && dt2.Is(F64)) {
24390 EmitA32(0xfeba0b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24391 return;
24392 }
24393 }
24394 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24395}
24396
24397void Assembler::vrintp(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024398 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024399 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024400 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024401 // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; T1
24402 if (dt1.Is(F32) && dt2.Is(F32)) {
24403 EmitT32_32(0xffba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24404 AdvanceIT();
24405 return;
24406 }
24407 } else {
24408 // VRINTP{<q>}.F32.F32 <Qd>, <Qm> ; A1
24409 if (dt1.Is(F32) && dt2.Is(F32)) {
24410 EmitA32(0xf3ba07c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24411 return;
24412 }
24413 }
24414 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24415}
24416
24417void Assembler::vrintp(DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024418 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024419 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024420 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024421 // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; T1
24422 if (dt1.Is(F32) && dt2.Is(F32)) {
24423 EmitT32_32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24424 AdvanceIT();
24425 return;
24426 }
24427 } else {
24428 // VRINTP{<q>}.F32.F32 <Sd>, <Sm> ; A1
24429 if (dt1.Is(F32) && dt2.Is(F32)) {
24430 EmitA32(0xfeba0a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24431 return;
24432 }
24433 }
24434 Delegate(kVrintp, &Assembler::vrintp, dt1, dt2, rd, rm);
24435}
24436
24437void Assembler::vrintr(
24438 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024439 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024440 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024441 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024442 // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24443 if (dt1.Is(F32) && dt2.Is(F32)) {
24444 EmitT32_32(0xeeb60a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24445 AdvanceIT();
24446 return;
24447 }
24448 } else {
24449 // VRINTR{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24450 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24451 EmitA32(0x0eb60a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24452 rm.Encode(5, 0));
24453 return;
24454 }
24455 }
24456 Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
24457}
24458
24459void Assembler::vrintr(
24460 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024461 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024462 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024463 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024464 // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24465 if (dt1.Is(F64) && dt2.Is(F64)) {
24466 EmitT32_32(0xeeb60b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24467 AdvanceIT();
24468 return;
24469 }
24470 } else {
24471 // VRINTR{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24472 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24473 EmitA32(0x0eb60b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24474 rm.Encode(5, 0));
24475 return;
24476 }
24477 }
24478 Delegate(kVrintr, &Assembler::vrintr, cond, dt1, dt2, rd, rm);
24479}
24480
24481void Assembler::vrintx(
24482 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024483 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024484 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024485 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024486 // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; T1
24487 if (dt1.Is(F32) && dt2.Is(F32)) {
24488 EmitT32_32(0xffba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
24489 AdvanceIT();
24490 return;
24491 }
24492 // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24493 if (dt1.Is(F64) && dt2.Is(F64)) {
24494 EmitT32_32(0xeeb70b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24495 AdvanceIT();
24496 return;
24497 }
24498 } else {
24499 // VRINTX{<q>}.F32.F32 <Dd>, <Dm> ; A1
24500 if (dt1.Is(F32) && dt2.Is(F32)) {
24501 EmitA32(0xf3ba0480U | rd.Encode(22, 12) | rm.Encode(5, 0));
24502 return;
24503 }
24504 // VRINTX{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24505 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24506 EmitA32(0x0eb70b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24507 rm.Encode(5, 0));
24508 return;
24509 }
24510 }
24511 Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
24512}
24513
24514void Assembler::vrintx(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024515 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024516 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024517 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024518 // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; T1
24519 if (dt1.Is(F32) && dt2.Is(F32)) {
24520 EmitT32_32(0xffba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24521 AdvanceIT();
24522 return;
24523 }
24524 } else {
24525 // VRINTX{<q>}.F32.F32 <Qd>, <Qm> ; A1
24526 if (dt1.Is(F32) && dt2.Is(F32)) {
24527 EmitA32(0xf3ba04c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24528 return;
24529 }
24530 }
24531 Delegate(kVrintx, &Assembler::vrintx, dt1, dt2, rd, rm);
24532}
24533
24534void Assembler::vrintx(
24535 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024536 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024537 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024538 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024539 // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24540 if (dt1.Is(F32) && dt2.Is(F32)) {
24541 EmitT32_32(0xeeb70a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
24542 AdvanceIT();
24543 return;
24544 }
24545 } else {
24546 // VRINTX{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24547 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24548 EmitA32(0x0eb70a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24549 rm.Encode(5, 0));
24550 return;
24551 }
24552 }
24553 Delegate(kVrintx, &Assembler::vrintx, cond, dt1, dt2, rd, rm);
24554}
24555
24556void Assembler::vrintz(
24557 Condition cond, DataType dt1, DataType dt2, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024558 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024559 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024560 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024561 // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; T1
24562 if (dt1.Is(F32) && dt2.Is(F32)) {
24563 EmitT32_32(0xffba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
24564 AdvanceIT();
24565 return;
24566 }
24567 // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; T1
24568 if (dt1.Is(F64) && dt2.Is(F64)) {
24569 EmitT32_32(0xeeb60bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24570 AdvanceIT();
24571 return;
24572 }
24573 } else {
24574 // VRINTZ{<q>}.F32.F32 <Dd>, <Dm> ; A1
24575 if (dt1.Is(F32) && dt2.Is(F32)) {
24576 EmitA32(0xf3ba0580U | rd.Encode(22, 12) | rm.Encode(5, 0));
24577 return;
24578 }
24579 // VRINTZ{<c>}{<q>}.F64.F64 <Dd>, <Dm> ; A1
24580 if (dt1.Is(F64) && dt2.Is(F64) && cond.IsNotNever()) {
24581 EmitA32(0x0eb60bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24582 rm.Encode(5, 0));
24583 return;
24584 }
24585 }
24586 Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
24587}
24588
24589void Assembler::vrintz(DataType dt1, DataType dt2, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024590 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024591 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024592 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024593 // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; T1
24594 if (dt1.Is(F32) && dt2.Is(F32)) {
24595 EmitT32_32(0xffba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24596 AdvanceIT();
24597 return;
24598 }
24599 } else {
24600 // VRINTZ{<q>}.F32.F32 <Qd>, <Qm> ; A1
24601 if (dt1.Is(F32) && dt2.Is(F32)) {
24602 EmitA32(0xf3ba05c0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24603 return;
24604 }
24605 }
24606 Delegate(kVrintz, &Assembler::vrintz, dt1, dt2, rd, rm);
24607}
24608
24609void Assembler::vrintz(
24610 Condition cond, DataType dt1, DataType dt2, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024611 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024612 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024613 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024614 // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; T1
24615 if (dt1.Is(F32) && dt2.Is(F32)) {
24616 EmitT32_32(0xeeb60ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
24617 AdvanceIT();
24618 return;
24619 }
24620 } else {
24621 // VRINTZ{<c>}{<q>}.F32.F32 <Sd>, <Sm> ; A1
24622 if (dt1.Is(F32) && dt2.Is(F32) && cond.IsNotNever()) {
24623 EmitA32(0x0eb60ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
24624 rm.Encode(5, 0));
24625 return;
24626 }
24627 }
24628 Delegate(kVrintz, &Assembler::vrintz, cond, dt1, dt2, rd, rm);
24629}
24630
24631void Assembler::vrshl(
24632 Condition cond, DataType dt, DRegister rd, DRegister rm, DRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024633 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024634 CheckIT(cond);
24635 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024636 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024637 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
24638 if (encoded_dt.IsValid()) {
24639 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24640 EmitT32_32(0xef000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24641 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24642 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24643 AdvanceIT();
24644 return;
24645 }
24646 }
24647 } else {
24648 // VRSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
24649 if (encoded_dt.IsValid()) {
24650 if (cond.Is(al)) {
24651 EmitA32(0xf2000500U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24652 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24653 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24654 return;
24655 }
24656 }
24657 }
24658 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24659}
24660
24661void Assembler::vrshl(
24662 Condition cond, DataType dt, QRegister rd, QRegister rm, QRegister rn) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024663 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024664 CheckIT(cond);
24665 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024666 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024667 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
24668 if (encoded_dt.IsValid()) {
24669 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24670 EmitT32_32(0xef000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24671 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
24672 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24673 AdvanceIT();
24674 return;
24675 }
24676 }
24677 } else {
24678 // VRSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
24679 if (encoded_dt.IsValid()) {
24680 if (cond.Is(al)) {
24681 EmitA32(0xf2000540U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
24682 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
24683 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
24684 return;
24685 }
24686 }
24687 }
24688 Delegate(kVrshl, &Assembler::vrshl, cond, dt, rd, rm, rn);
24689}
24690
24691void Assembler::vrshr(Condition cond,
24692 DataType dt,
24693 DRegister rd,
24694 DRegister rm,
24695 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024696 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024697 CheckIT(cond);
24698 if (operand.IsImmediate()) {
24699 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24700 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24701 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024702 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024703 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24704 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24705 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24706 uint32_t imm6 = dt.GetSize() - imm;
24707 EmitT32_32(0xef800210U | (encoded_dt.GetTypeEncodingValue() << 28) |
24708 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24709 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24710 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24711 AdvanceIT();
24712 return;
24713 }
24714 }
24715 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
24716 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24717 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24718 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24719 rm.Encode(5, 0));
24720 AdvanceIT();
24721 return;
24722 }
24723 }
24724 } else {
24725 // VRSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
24726 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24727 if (cond.Is(al)) {
24728 uint32_t imm6 = dt.GetSize() - imm;
24729 EmitA32(0xf2800210U | (encoded_dt.GetTypeEncodingValue() << 24) |
24730 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24731 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24732 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24733 return;
24734 }
24735 }
24736 // VRSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
24737 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24738 if (cond.Is(al)) {
24739 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24740 rm.Encode(5, 0));
24741 return;
24742 }
24743 }
24744 }
24745 }
24746 }
24747 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24748}
24749
24750void Assembler::vrshr(Condition cond,
24751 DataType dt,
24752 QRegister rd,
24753 QRegister rm,
24754 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024755 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024756 CheckIT(cond);
24757 if (operand.IsImmediate()) {
24758 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24759 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24760 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024761 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024762 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
24763 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24764 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24765 uint32_t imm6 = dt.GetSize() - imm;
24766 EmitT32_32(0xef800250U | (encoded_dt.GetTypeEncodingValue() << 28) |
24767 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24768 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24769 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24770 AdvanceIT();
24771 return;
24772 }
24773 }
24774 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
24775 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24776 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24777 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24778 rm.Encode(5, 0));
24779 AdvanceIT();
24780 return;
24781 }
24782 }
24783 } else {
24784 // VRSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
24785 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24786 if (cond.Is(al)) {
24787 uint32_t imm6 = dt.GetSize() - imm;
24788 EmitA32(0xf2800250U | (encoded_dt.GetTypeEncodingValue() << 24) |
24789 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24790 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
24791 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24792 return;
24793 }
24794 }
24795 // VRSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
24796 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
24797 if (cond.Is(al)) {
24798 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
24799 rm.Encode(5, 0));
24800 return;
24801 }
24802 }
24803 }
24804 }
24805 }
24806 Delegate(kVrshr, &Assembler::vrshr, cond, dt, rd, rm, operand);
24807}
24808
24809void Assembler::vrshrn(Condition cond,
24810 DataType dt,
24811 DRegister rd,
24812 QRegister rm,
24813 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024814 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024815 CheckIT(cond);
24816 if (operand.IsImmediate()) {
24817 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24818 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24819 Dt_imm6_3 encoded_dt(dt);
24820 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024821 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024822 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
24823 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24824 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24825 uint32_t imm6 = dt.GetSize() / 2 - imm;
24826 EmitT32_32(0xef800850U |
24827 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24828 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24829 AdvanceIT();
24830 return;
24831 }
24832 }
24833 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
24834 if (encoded_dt_2.IsValid() && (imm == 0)) {
24835 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24836 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24837 rd.Encode(22, 12) | rm.Encode(5, 0));
24838 AdvanceIT();
24839 return;
24840 }
24841 }
24842 } else {
24843 // VRSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
24844 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
24845 if (cond.Is(al)) {
24846 uint32_t imm6 = dt.GetSize() / 2 - imm;
24847 EmitA32(0xf2800850U |
24848 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
24849 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
24850 return;
24851 }
24852 }
24853 // VRSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
24854 if (encoded_dt_2.IsValid() && (imm == 0)) {
24855 if (cond.Is(al)) {
24856 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
24857 rd.Encode(22, 12) | rm.Encode(5, 0));
24858 return;
24859 }
24860 }
24861 }
24862 }
24863 }
24864 Delegate(kVrshrn, &Assembler::vrshrn, cond, dt, rd, rm, operand);
24865}
24866
24867void Assembler::vrsqrte(Condition cond,
24868 DataType dt,
24869 DRegister rd,
24870 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024871 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024872 CheckIT(cond);
24873 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024874 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024875 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
24876 if (encoded_dt.IsValid()) {
24877 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24878 EmitT32_32(0xffb30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24879 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24880 rd.Encode(22, 12) | rm.Encode(5, 0));
24881 AdvanceIT();
24882 return;
24883 }
24884 }
24885 } else {
24886 // VRSQRTE{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
24887 if (encoded_dt.IsValid()) {
24888 if (cond.Is(al)) {
24889 EmitA32(0xf3b30480U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24890 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24891 rd.Encode(22, 12) | rm.Encode(5, 0));
24892 return;
24893 }
24894 }
24895 }
24896 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
24897}
24898
24899void Assembler::vrsqrte(Condition cond,
24900 DataType dt,
24901 QRegister rd,
24902 QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024903 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024904 CheckIT(cond);
24905 Dt_F_size_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024906 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024907 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
24908 if (encoded_dt.IsValid()) {
24909 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24910 EmitT32_32(0xffb304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24911 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24912 rd.Encode(22, 12) | rm.Encode(5, 0));
24913 AdvanceIT();
24914 return;
24915 }
24916 }
24917 } else {
24918 // VRSQRTE{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
24919 if (encoded_dt.IsValid()) {
24920 if (cond.Is(al)) {
24921 EmitA32(0xf3b304c0U | ((encoded_dt.GetEncodingValue() & 0x3) << 18) |
24922 ((encoded_dt.GetEncodingValue() & 0x4) << 6) |
24923 rd.Encode(22, 12) | rm.Encode(5, 0));
24924 return;
24925 }
24926 }
24927 }
24928 Delegate(kVrsqrte, &Assembler::vrsqrte, cond, dt, rd, rm);
24929}
24930
24931void Assembler::vrsqrts(
24932 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024933 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024934 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024935 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024936 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
24937 if (dt.Is(F32)) {
24938 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24939 EmitT32_32(0xef200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24940 rm.Encode(5, 0));
24941 AdvanceIT();
24942 return;
24943 }
24944 }
24945 } else {
24946 // VRSQRTS{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
24947 if (dt.Is(F32)) {
24948 if (cond.Is(al)) {
24949 EmitA32(0xf2200f10U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24950 rm.Encode(5, 0));
24951 return;
24952 }
24953 }
24954 }
24955 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
24956}
24957
24958void Assembler::vrsqrts(
24959 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024960 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024961 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024962 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024963 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
24964 if (dt.Is(F32)) {
24965 if (cond.Is(al) || AllowStronglyDiscouraged()) {
24966 EmitT32_32(0xef200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24967 rm.Encode(5, 0));
24968 AdvanceIT();
24969 return;
24970 }
24971 }
24972 } else {
24973 // VRSQRTS{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
24974 if (dt.Is(F32)) {
24975 if (cond.Is(al)) {
24976 EmitA32(0xf2200f50U | rd.Encode(22, 12) | rn.Encode(7, 16) |
24977 rm.Encode(5, 0));
24978 return;
24979 }
24980 }
24981 }
24982 Delegate(kVrsqrts, &Assembler::vrsqrts, cond, dt, rd, rn, rm);
24983}
24984
24985void Assembler::vrsra(Condition cond,
24986 DataType dt,
24987 DRegister rd,
24988 DRegister rm,
24989 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070024990 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010024991 CheckIT(cond);
24992 if (operand.IsImmediate()) {
24993 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
24994 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
24995 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010024996 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010024997 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
24998 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
24999 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25000 uint32_t imm6 = dt.GetSize() - imm;
25001 EmitT32_32(0xef800310U | (encoded_dt.GetTypeEncodingValue() << 28) |
25002 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25003 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25004 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25005 AdvanceIT();
25006 return;
25007 }
25008 }
25009 } else {
25010 // VRSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25011 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25012 if (cond.Is(al)) {
25013 uint32_t imm6 = dt.GetSize() - imm;
25014 EmitA32(0xf2800310U | (encoded_dt.GetTypeEncodingValue() << 24) |
25015 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25016 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25017 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25018 return;
25019 }
25020 }
25021 }
25022 }
25023 }
25024 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25025}
25026
25027void Assembler::vrsra(Condition cond,
25028 DataType dt,
25029 QRegister rd,
25030 QRegister rm,
25031 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025032 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025033 CheckIT(cond);
25034 if (operand.IsImmediate()) {
25035 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25036 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25037 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025038 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025039 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25040 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25041 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25042 uint32_t imm6 = dt.GetSize() - imm;
25043 EmitT32_32(0xef800350U | (encoded_dt.GetTypeEncodingValue() << 28) |
25044 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25045 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25046 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25047 AdvanceIT();
25048 return;
25049 }
25050 }
25051 } else {
25052 // VRSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25053 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25054 if (cond.Is(al)) {
25055 uint32_t imm6 = dt.GetSize() - imm;
25056 EmitA32(0xf2800350U | (encoded_dt.GetTypeEncodingValue() << 24) |
25057 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25058 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25059 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25060 return;
25061 }
25062 }
25063 }
25064 }
25065 }
25066 Delegate(kVrsra, &Assembler::vrsra, cond, dt, rd, rm, operand);
25067}
25068
25069void Assembler::vrsubhn(
25070 Condition cond, DataType dt, DRegister 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);
25073 Dt_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025074 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025075 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
25076 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25077 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25078 EmitT32_32(0xff800600U | (encoded_dt.GetEncodingValue() << 20) |
25079 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25080 AdvanceIT();
25081 return;
25082 }
25083 }
25084 } else {
25085 // VRSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
25086 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
25087 if (cond.Is(al)) {
25088 EmitA32(0xf3800600U | (encoded_dt.GetEncodingValue() << 20) |
25089 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
25090 return;
25091 }
25092 }
25093 }
25094 Delegate(kVrsubhn, &Assembler::vrsubhn, cond, dt, rd, rn, rm);
25095}
25096
25097void Assembler::vseleq(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025098 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025099 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025100 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025101 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; T1
25102 if (OutsideITBlock() && dt.Is(F64)) {
25103 EmitT32_32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25104 rm.Encode(5, 0));
25105 AdvanceIT();
25106 return;
25107 }
25108 } else {
25109 // VSELEQ.F64 <Dd>, <Dn>, <Dm> ; A1
25110 if (dt.Is(F64)) {
25111 EmitA32(0xfe000b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25112 rm.Encode(5, 0));
25113 return;
25114 }
25115 }
25116 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25117}
25118
25119void Assembler::vseleq(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025120 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025121 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025122 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025123 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; T1
25124 if (OutsideITBlock() && dt.Is(F32)) {
25125 EmitT32_32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25126 rm.Encode(5, 0));
25127 AdvanceIT();
25128 return;
25129 }
25130 } else {
25131 // VSELEQ.F32 <Sd>, <Sn>, <Sm> ; A1
25132 if (dt.Is(F32)) {
25133 EmitA32(0xfe000a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25134 rm.Encode(5, 0));
25135 return;
25136 }
25137 }
25138 Delegate(kVseleq, &Assembler::vseleq, dt, rd, rn, rm);
25139}
25140
25141void Assembler::vselge(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025142 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025143 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025144 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025145 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; T1
25146 if (OutsideITBlock() && dt.Is(F64)) {
25147 EmitT32_32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25148 rm.Encode(5, 0));
25149 AdvanceIT();
25150 return;
25151 }
25152 } else {
25153 // VSELGE.F64 <Dd>, <Dn>, <Dm> ; A1
25154 if (dt.Is(F64)) {
25155 EmitA32(0xfe200b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25156 rm.Encode(5, 0));
25157 return;
25158 }
25159 }
25160 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25161}
25162
25163void Assembler::vselge(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025164 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025165 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025166 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025167 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; T1
25168 if (OutsideITBlock() && dt.Is(F32)) {
25169 EmitT32_32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25170 rm.Encode(5, 0));
25171 AdvanceIT();
25172 return;
25173 }
25174 } else {
25175 // VSELGE.F32 <Sd>, <Sn>, <Sm> ; A1
25176 if (dt.Is(F32)) {
25177 EmitA32(0xfe200a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25178 rm.Encode(5, 0));
25179 return;
25180 }
25181 }
25182 Delegate(kVselge, &Assembler::vselge, dt, rd, rn, rm);
25183}
25184
25185void Assembler::vselgt(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025186 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025187 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025188 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025189 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; T1
25190 if (OutsideITBlock() && dt.Is(F64)) {
25191 EmitT32_32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25192 rm.Encode(5, 0));
25193 AdvanceIT();
25194 return;
25195 }
25196 } else {
25197 // VSELGT.F64 <Dd>, <Dn>, <Dm> ; A1
25198 if (dt.Is(F64)) {
25199 EmitA32(0xfe300b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25200 rm.Encode(5, 0));
25201 return;
25202 }
25203 }
25204 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25205}
25206
25207void Assembler::vselgt(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025208 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025209 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025210 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025211 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; T1
25212 if (OutsideITBlock() && dt.Is(F32)) {
25213 EmitT32_32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25214 rm.Encode(5, 0));
25215 AdvanceIT();
25216 return;
25217 }
25218 } else {
25219 // VSELGT.F32 <Sd>, <Sn>, <Sm> ; A1
25220 if (dt.Is(F32)) {
25221 EmitA32(0xfe300a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25222 rm.Encode(5, 0));
25223 return;
25224 }
25225 }
25226 Delegate(kVselgt, &Assembler::vselgt, dt, rd, rn, rm);
25227}
25228
25229void Assembler::vselvs(DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025230 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025231 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025232 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025233 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; T1
25234 if (OutsideITBlock() && dt.Is(F64)) {
25235 EmitT32_32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25236 rm.Encode(5, 0));
25237 AdvanceIT();
25238 return;
25239 }
25240 } else {
25241 // VSELVS.F64 <Dd>, <Dn>, <Dm> ; A1
25242 if (dt.Is(F64)) {
25243 EmitA32(0xfe100b00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25244 rm.Encode(5, 0));
25245 return;
25246 }
25247 }
25248 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25249}
25250
25251void Assembler::vselvs(DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025252 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025253 CheckIT(al);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025254 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025255 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; T1
25256 if (OutsideITBlock() && dt.Is(F32)) {
25257 EmitT32_32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25258 rm.Encode(5, 0));
25259 AdvanceIT();
25260 return;
25261 }
25262 } else {
25263 // VSELVS.F32 <Sd>, <Sn>, <Sm> ; A1
25264 if (dt.Is(F32)) {
25265 EmitA32(0xfe100a00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
25266 rm.Encode(5, 0));
25267 return;
25268 }
25269 }
25270 Delegate(kVselvs, &Assembler::vselvs, dt, rd, rn, rm);
25271}
25272
25273void Assembler::vshl(Condition cond,
25274 DataType dt,
25275 DRegister rd,
25276 DRegister rm,
25277 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025278 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025279 CheckIT(cond);
25280 if (operand.IsImmediate()) {
25281 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25282 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25283 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025284 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025285 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; T1
25286 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25287 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25288 uint32_t imm6 = imm;
25289 EmitT32_32(0xef800510U |
25290 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25291 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25292 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25293 AdvanceIT();
25294 return;
25295 }
25296 }
25297 } else {
25298 // VSHL{<c>}{<q>}.I<size> {<Dd>}, <Dm>, #<imm> ; A1
25299 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25300 if (cond.Is(al)) {
25301 uint32_t imm6 = imm;
25302 EmitA32(0xf2800510U |
25303 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25304 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25305 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25306 return;
25307 }
25308 }
25309 }
25310 }
25311 }
25312 if (operand.IsRegister()) {
25313 DRegister rn = operand.GetRegister();
25314 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025315 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025316 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; T1
25317 if (encoded_dt.IsValid()) {
25318 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25319 EmitT32_32(0xef000400U |
25320 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25321 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25322 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25323 AdvanceIT();
25324 return;
25325 }
25326 }
25327 } else {
25328 // VSHL{<c>}{<q>}.<dt> {<Dd>}, <Dm>, <Dn> ; A1
25329 if (encoded_dt.IsValid()) {
25330 if (cond.Is(al)) {
25331 EmitA32(0xf2000400U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25332 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25333 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25334 return;
25335 }
25336 }
25337 }
25338 }
25339 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25340}
25341
25342void Assembler::vshl(Condition cond,
25343 DataType dt,
25344 QRegister rd,
25345 QRegister rm,
25346 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025347 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025348 CheckIT(cond);
25349 if (operand.IsImmediate()) {
25350 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25351 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25352 Dt_L_imm6_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025353 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025354 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; T1
25355 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25356 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25357 uint32_t imm6 = imm;
25358 EmitT32_32(0xef800550U |
25359 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25360 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25361 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25362 AdvanceIT();
25363 return;
25364 }
25365 }
25366 } else {
25367 // VSHL{<c>}{<q>}.I<size> {<Qd>}, <Qm>, #<imm> ; A1
25368 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25369 if (cond.Is(al)) {
25370 uint32_t imm6 = imm;
25371 EmitA32(0xf2800550U |
25372 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25373 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25374 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25375 return;
25376 }
25377 }
25378 }
25379 }
25380 }
25381 if (operand.IsRegister()) {
25382 QRegister rn = operand.GetRegister();
25383 Dt_U_size_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025384 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025385 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; T1
25386 if (encoded_dt.IsValid()) {
25387 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25388 EmitT32_32(0xef000440U |
25389 ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25390 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
25391 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25392 AdvanceIT();
25393 return;
25394 }
25395 }
25396 } else {
25397 // VSHL{<c>}{<q>}.<dt> {<Qd>}, <Qm>, <Qn> ; A1
25398 if (encoded_dt.IsValid()) {
25399 if (cond.Is(al)) {
25400 EmitA32(0xf2000440U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
25401 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
25402 rd.Encode(22, 12) | rm.Encode(5, 0) | rn.Encode(7, 16));
25403 return;
25404 }
25405 }
25406 }
25407 }
25408 Delegate(kVshl, &Assembler::vshl, cond, dt, rd, rm, operand);
25409}
25410
25411void Assembler::vshll(Condition cond,
25412 DataType dt,
25413 QRegister rd,
25414 DRegister rm,
25415 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025416 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025417 CheckIT(cond);
25418 if (operand.IsImmediate()) {
25419 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25420 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25421 Dt_imm6_4 encoded_dt(dt);
25422 Dt_size_16 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025423 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025424 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T1
25425 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25426 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25427 uint32_t imm6 = dt.GetSize() + imm;
25428 EmitT32_32(0xef800a10U | (encoded_dt.GetTypeEncodingValue() << 28) |
25429 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25430 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25431 AdvanceIT();
25432 return;
25433 }
25434 }
25435 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; T2
25436 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25437 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25438 EmitT32_32(0xffb20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25439 rd.Encode(22, 12) | rm.Encode(5, 0));
25440 AdvanceIT();
25441 return;
25442 }
25443 }
25444 } else {
25445 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A1
25446 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() - 1)) {
25447 if (cond.Is(al)) {
25448 uint32_t imm6 = dt.GetSize() + imm;
25449 EmitA32(0xf2800a10U | (encoded_dt.GetTypeEncodingValue() << 24) |
25450 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25451 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25452 return;
25453 }
25454 }
25455 // VSHLL{<c>}{<q>}.<type><size> <Qd>, <Dm>, #<imm> ; A2
25456 if (encoded_dt_2.IsValid() && (imm == dt.GetSize())) {
25457 if (cond.Is(al)) {
25458 EmitA32(0xf3b20300U | (encoded_dt_2.GetEncodingValue() << 18) |
25459 rd.Encode(22, 12) | rm.Encode(5, 0));
25460 return;
25461 }
25462 }
25463 }
25464 }
25465 }
25466 Delegate(kVshll, &Assembler::vshll, cond, dt, rd, rm, operand);
25467}
25468
25469void Assembler::vshr(Condition cond,
25470 DataType dt,
25471 DRegister rd,
25472 DRegister rm,
25473 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025474 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025475 CheckIT(cond);
25476 if (operand.IsImmediate()) {
25477 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25478 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25479 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025480 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025481 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25482 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25483 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25484 uint32_t imm6 = dt.GetSize() - imm;
25485 EmitT32_32(0xef800010U | (encoded_dt.GetTypeEncodingValue() << 28) |
25486 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25487 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25488 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25489 AdvanceIT();
25490 return;
25491 }
25492 }
25493 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; T1
25494 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25495 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25496 EmitT32_32(0xef200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25497 rm.Encode(5, 0));
25498 AdvanceIT();
25499 return;
25500 }
25501 }
25502 } else {
25503 // VSHR{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25504 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25505 if (cond.Is(al)) {
25506 uint32_t imm6 = dt.GetSize() - imm;
25507 EmitA32(0xf2800010U | (encoded_dt.GetTypeEncodingValue() << 24) |
25508 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25509 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25510 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25511 return;
25512 }
25513 }
25514 // VSHR{<c>}{<q>}.<dt> <Dd>, <Dm>, #0 ; A1
25515 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25516 if (cond.Is(al)) {
25517 EmitA32(0xf2200110U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25518 rm.Encode(5, 0));
25519 return;
25520 }
25521 }
25522 }
25523 }
25524 }
25525 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25526}
25527
25528void Assembler::vshr(Condition cond,
25529 DataType dt,
25530 QRegister rd,
25531 QRegister rm,
25532 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025533 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025534 CheckIT(cond);
25535 if (operand.IsImmediate()) {
25536 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25537 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25538 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025539 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025540 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25541 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25542 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25543 uint32_t imm6 = dt.GetSize() - imm;
25544 EmitT32_32(0xef800050U | (encoded_dt.GetTypeEncodingValue() << 28) |
25545 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25546 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25547 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25548 AdvanceIT();
25549 return;
25550 }
25551 }
25552 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; T1
25553 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25554 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25555 EmitT32_32(0xef200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25556 rm.Encode(5, 0));
25557 AdvanceIT();
25558 return;
25559 }
25560 }
25561 } else {
25562 // VSHR{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25563 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25564 if (cond.Is(al)) {
25565 uint32_t imm6 = dt.GetSize() - imm;
25566 EmitA32(0xf2800050U | (encoded_dt.GetTypeEncodingValue() << 24) |
25567 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25568 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25569 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25570 return;
25571 }
25572 }
25573 // VSHR{<c>}{<q>}.<dt> <Qd>, <Qm>, #0 ; A1
25574 if ((dt.Is(kDataTypeS) || dt.Is(kDataTypeU)) && (imm == 0)) {
25575 if (cond.Is(al)) {
25576 EmitA32(0xf2200150U | rd.Encode(22, 12) | rm.Encode(7, 16) |
25577 rm.Encode(5, 0));
25578 return;
25579 }
25580 }
25581 }
25582 }
25583 }
25584 Delegate(kVshr, &Assembler::vshr, cond, dt, rd, rm, operand);
25585}
25586
25587void Assembler::vshrn(Condition cond,
25588 DataType dt,
25589 DRegister rd,
25590 QRegister rm,
25591 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025592 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025593 CheckIT(cond);
25594 if (operand.IsImmediate()) {
25595 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25596 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25597 Dt_imm6_3 encoded_dt(dt);
25598 Dt_size_3 encoded_dt_2(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025599 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025600 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; T1
25601 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25602 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25603 uint32_t imm6 = dt.GetSize() / 2 - imm;
25604 EmitT32_32(0xef800810U |
25605 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25606 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25607 AdvanceIT();
25608 return;
25609 }
25610 }
25611 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; T1
25612 if (encoded_dt_2.IsValid() && (imm == 0)) {
25613 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25614 EmitT32_32(0xffb20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25615 rd.Encode(22, 12) | rm.Encode(5, 0));
25616 AdvanceIT();
25617 return;
25618 }
25619 }
25620 } else {
25621 // VSHRN{<c>}{<q>}.I<size> <Dd>, <Qm>, #<imm> ; A1
25622 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize() / 2)) {
25623 if (cond.Is(al)) {
25624 uint32_t imm6 = dt.GetSize() / 2 - imm;
25625 EmitA32(0xf2800810U |
25626 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25627 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25628 return;
25629 }
25630 }
25631 // VSHRN{<c>}{<q>}.<dt> <Dd>, <Qm>, #0 ; A1
25632 if (encoded_dt_2.IsValid() && (imm == 0)) {
25633 if (cond.Is(al)) {
25634 EmitA32(0xf3b20200U | (encoded_dt_2.GetEncodingValue() << 18) |
25635 rd.Encode(22, 12) | rm.Encode(5, 0));
25636 return;
25637 }
25638 }
25639 }
25640 }
25641 }
25642 Delegate(kVshrn, &Assembler::vshrn, cond, dt, rd, rm, operand);
25643}
25644
25645void Assembler::vsli(Condition cond,
25646 DataType dt,
25647 DRegister rd,
25648 DRegister rm,
25649 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025650 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025651 CheckIT(cond);
25652 if (operand.IsImmediate()) {
25653 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25654 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25655 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025656 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025657 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25658 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25659 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25660 uint32_t imm6 = imm;
25661 EmitT32_32(0xff800510U |
25662 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25663 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25664 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25665 AdvanceIT();
25666 return;
25667 }
25668 }
25669 } else {
25670 // VSLI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25671 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25672 if (cond.Is(al)) {
25673 uint32_t imm6 = imm;
25674 EmitA32(0xf3800510U |
25675 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25676 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25677 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25678 return;
25679 }
25680 }
25681 }
25682 }
25683 }
25684 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25685}
25686
25687void Assembler::vsli(Condition cond,
25688 DataType dt,
25689 QRegister rd,
25690 QRegister rm,
25691 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025692 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025693 CheckIT(cond);
25694 if (operand.IsImmediate()) {
25695 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25696 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25697 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025698 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025699 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25700 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25701 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25702 uint32_t imm6 = imm;
25703 EmitT32_32(0xff800550U |
25704 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25705 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25706 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25707 AdvanceIT();
25708 return;
25709 }
25710 }
25711 } else {
25712 // VSLI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25713 if (encoded_dt.IsValid() && (imm <= dt.GetSize() - 1)) {
25714 if (cond.Is(al)) {
25715 uint32_t imm6 = imm;
25716 EmitA32(0xf3800550U |
25717 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25718 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25719 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25720 return;
25721 }
25722 }
25723 }
25724 }
25725 }
25726 Delegate(kVsli, &Assembler::vsli, cond, dt, rd, rm, operand);
25727}
25728
25729void Assembler::vsqrt(Condition cond, DataType dt, SRegister rd, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025730 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025731 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025732 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025733 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
25734 if (dt.Is(F32)) {
25735 EmitT32_32(0xeeb10ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25736 AdvanceIT();
25737 return;
25738 }
25739 } else {
25740 // VSQRT{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
25741 if (dt.Is(F32) && cond.IsNotNever()) {
25742 EmitA32(0x0eb10ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25743 rm.Encode(5, 0));
25744 return;
25745 }
25746 }
25747 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25748}
25749
25750void Assembler::vsqrt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025751 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025752 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025753 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025754 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
25755 if (dt.Is(F64)) {
25756 EmitT32_32(0xeeb10bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
25757 AdvanceIT();
25758 return;
25759 }
25760 } else {
25761 // VSQRT{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
25762 if (dt.Is(F64) && cond.IsNotNever()) {
25763 EmitA32(0x0eb10bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
25764 rm.Encode(5, 0));
25765 return;
25766 }
25767 }
25768 Delegate(kVsqrt, &Assembler::vsqrt, cond, dt, rd, rm);
25769}
25770
25771void Assembler::vsra(Condition cond,
25772 DataType dt,
25773 DRegister rd,
25774 DRegister rm,
25775 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025776 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025777 CheckIT(cond);
25778 if (operand.IsImmediate()) {
25779 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25780 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25781 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025782 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025783 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; T1
25784 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25785 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25786 uint32_t imm6 = dt.GetSize() - imm;
25787 EmitT32_32(0xef800110U | (encoded_dt.GetTypeEncodingValue() << 28) |
25788 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25789 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25790 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25791 AdvanceIT();
25792 return;
25793 }
25794 }
25795 } else {
25796 // VSRA{<c>}{<q>}.<type><size> {<Dd>}, <Dm>, #<imm> ; A1
25797 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25798 if (cond.Is(al)) {
25799 uint32_t imm6 = dt.GetSize() - imm;
25800 EmitA32(0xf2800110U | (encoded_dt.GetTypeEncodingValue() << 24) |
25801 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25802 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25803 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25804 return;
25805 }
25806 }
25807 }
25808 }
25809 }
25810 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25811}
25812
25813void Assembler::vsra(Condition cond,
25814 DataType dt,
25815 QRegister rd,
25816 QRegister rm,
25817 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025818 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025819 CheckIT(cond);
25820 if (operand.IsImmediate()) {
25821 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25822 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25823 Dt_L_imm6_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025824 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025825 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; T1
25826 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25827 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25828 uint32_t imm6 = dt.GetSize() - imm;
25829 EmitT32_32(0xef800150U | (encoded_dt.GetTypeEncodingValue() << 28) |
25830 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25831 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25832 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25833 AdvanceIT();
25834 return;
25835 }
25836 }
25837 } else {
25838 // VSRA{<c>}{<q>}.<type><size> {<Qd>}, <Qm>, #<imm> ; A1
25839 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25840 if (cond.Is(al)) {
25841 uint32_t imm6 = dt.GetSize() - imm;
25842 EmitA32(0xf2800150U | (encoded_dt.GetTypeEncodingValue() << 24) |
25843 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25844 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25845 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25846 return;
25847 }
25848 }
25849 }
25850 }
25851 }
25852 Delegate(kVsra, &Assembler::vsra, cond, dt, rd, rm, operand);
25853}
25854
25855void Assembler::vsri(Condition cond,
25856 DataType dt,
25857 DRegister rd,
25858 DRegister rm,
25859 const DOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025860 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025861 CheckIT(cond);
25862 if (operand.IsImmediate()) {
25863 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25864 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25865 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025866 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025867 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; T1
25868 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25869 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25870 uint32_t imm6 = dt.GetSize() - imm;
25871 EmitT32_32(0xff800410U |
25872 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25873 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25874 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25875 AdvanceIT();
25876 return;
25877 }
25878 }
25879 } else {
25880 // VSRI{<c>}{<q>}.<dt> {<Dd>}, <Dm>, #<imm> ; A1
25881 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25882 if (cond.Is(al)) {
25883 uint32_t imm6 = dt.GetSize() - imm;
25884 EmitA32(0xf3800410U |
25885 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25886 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25887 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25888 return;
25889 }
25890 }
25891 }
25892 }
25893 }
25894 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
25895}
25896
25897void Assembler::vsri(Condition cond,
25898 DataType dt,
25899 QRegister rd,
25900 QRegister rm,
25901 const QOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025902 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025903 CheckIT(cond);
25904 if (operand.IsImmediate()) {
25905 if (operand.GetNeonImmediate().CanConvert<uint32_t>()) {
25906 uint32_t imm = operand.GetNeonImmediate().GetImmediate<uint32_t>();
25907 Dt_L_imm6_4 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025908 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025909 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; T1
25910 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25911 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25912 uint32_t imm6 = dt.GetSize() - imm;
25913 EmitT32_32(0xff800450U |
25914 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25915 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25916 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25917 AdvanceIT();
25918 return;
25919 }
25920 }
25921 } else {
25922 // VSRI{<c>}{<q>}.<dt> {<Qd>}, <Qm>, #<imm> ; A1
25923 if (encoded_dt.IsValid() && (imm >= 1) && (imm <= dt.GetSize())) {
25924 if (cond.Is(al)) {
25925 uint32_t imm6 = dt.GetSize() - imm;
25926 EmitA32(0xf3800450U |
25927 ((encoded_dt.GetEncodingValue() & 0x7) << 19) |
25928 ((encoded_dt.GetEncodingValue() & 0x8) << 4) |
25929 rd.Encode(22, 12) | rm.Encode(5, 0) | (imm6 << 16));
25930 return;
25931 }
25932 }
25933 }
25934 }
25935 }
25936 Delegate(kVsri, &Assembler::vsri, cond, dt, rd, rm, operand);
25937}
25938
25939void Assembler::vst1(Condition cond,
25940 DataType dt,
25941 const NeonRegisterList& nreglist,
25942 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070025943 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010025944 CheckIT(cond);
25945 if (operand.IsImmediateZero()) {
25946 Register rn = operand.GetBaseRegister();
25947 Alignment align = operand.GetAlignment();
25948 Dt_size_6 encoded_dt(dt);
25949 Dt_size_7 encoded_dt_2(dt);
25950 Align_align_5 encoded_align_1(align, nreglist);
25951 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010025952 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025953 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
25954 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25955 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080025956 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080025957 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025958 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25959 const DRegister& first = nreglist.GetFirstDRegister();
25960 uint32_t len_encoding;
25961 switch (nreglist.GetLength()) {
25962 default:
25963 VIXL_UNREACHABLE_OR_FALLTHROUGH();
25964 case 1:
25965 len_encoding = 0x7;
25966 break;
25967 case 2:
25968 len_encoding = 0xa;
25969 break;
25970 case 3:
25971 len_encoding = 0x6;
25972 break;
25973 case 4:
25974 len_encoding = 0x2;
25975 break;
25976 }
25977 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
25978 (encoded_align_1.GetEncodingValue() << 4) |
25979 first.Encode(22, 12) | (len_encoding << 8) |
25980 (rn.GetCode() << 16));
25981 AdvanceIT();
25982 return;
25983 }
25984 }
25985 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
25986 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
25987 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080025988 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080025989 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010025990 if (cond.Is(al) || AllowStronglyDiscouraged()) {
25991 const DRegister& first = nreglist.GetFirstDRegister();
25992 uint32_t len_encoding;
25993 switch (nreglist.GetLength()) {
25994 default:
25995 VIXL_UNREACHABLE_OR_FALLTHROUGH();
25996 case 1:
25997 len_encoding = 0x7;
25998 break;
25999 case 2:
26000 len_encoding = 0xa;
26001 break;
26002 case 3:
26003 len_encoding = 0x6;
26004 break;
26005 case 4:
26006 len_encoding = 0x2;
26007 break;
26008 }
26009 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26010 (encoded_align_1.GetEncodingValue() << 4) |
26011 first.Encode(22, 12) | (len_encoding << 8) |
26012 (rn.GetCode() << 16));
26013 AdvanceIT();
26014 return;
26015 }
26016 }
26017 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26018 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026019 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026020 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026021 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26022 const DRegister& first = nreglist.GetFirstDRegister();
26023 EmitT32_32(0xf980000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26024 (encoded_align_2.GetEncodingValue() << 4) |
26025 first.Encode(22, 12) | (rn.GetCode() << 16));
26026 AdvanceIT();
26027 return;
26028 }
26029 }
26030 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26031 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026032 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026033 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026034 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26035 const DRegister& first = nreglist.GetFirstDRegister();
26036 EmitT32_32(0xf980000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26037 (encoded_align_2.GetEncodingValue() << 4) |
26038 first.Encode(22, 12) | (rn.GetCode() << 16));
26039 AdvanceIT();
26040 return;
26041 }
26042 }
26043 } else {
26044 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26045 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26046 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026047 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026048 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026049 if (cond.Is(al)) {
26050 const DRegister& first = nreglist.GetFirstDRegister();
26051 uint32_t len_encoding;
26052 switch (nreglist.GetLength()) {
26053 default:
26054 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26055 case 1:
26056 len_encoding = 0x7;
26057 break;
26058 case 2:
26059 len_encoding = 0xa;
26060 break;
26061 case 3:
26062 len_encoding = 0x6;
26063 break;
26064 case 4:
26065 len_encoding = 0x2;
26066 break;
26067 }
26068 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26069 (encoded_align_1.GetEncodingValue() << 4) |
26070 first.Encode(22, 12) | (len_encoding << 8) |
26071 (rn.GetCode() << 16));
26072 return;
26073 }
26074 }
26075 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26076 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26077 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026078 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026079 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026080 if (cond.Is(al)) {
26081 const DRegister& first = nreglist.GetFirstDRegister();
26082 uint32_t len_encoding;
26083 switch (nreglist.GetLength()) {
26084 default:
26085 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26086 case 1:
26087 len_encoding = 0x7;
26088 break;
26089 case 2:
26090 len_encoding = 0xa;
26091 break;
26092 case 3:
26093 len_encoding = 0x6;
26094 break;
26095 case 4:
26096 len_encoding = 0x2;
26097 break;
26098 }
26099 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26100 (encoded_align_1.GetEncodingValue() << 4) |
26101 first.Encode(22, 12) | (len_encoding << 8) |
26102 (rn.GetCode() << 16));
26103 return;
26104 }
26105 }
26106 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26107 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026108 (nreglist.GetLength() == 1) && operand.IsOffset() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026109 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026110 if (cond.Is(al)) {
26111 const DRegister& first = nreglist.GetFirstDRegister();
26112 EmitA32(0xf480000fU | (encoded_dt_2.GetEncodingValue() << 10) |
26113 (encoded_align_2.GetEncodingValue() << 4) |
26114 first.Encode(22, 12) | (rn.GetCode() << 16));
26115 return;
26116 }
26117 }
26118 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26119 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026120 (nreglist.GetLength() == 1) && operand.IsPostIndex() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026121 encoded_align_2.IsValid() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026122 if (cond.Is(al)) {
26123 const DRegister& first = nreglist.GetFirstDRegister();
26124 EmitA32(0xf480000dU | (encoded_dt_2.GetEncodingValue() << 10) |
26125 (encoded_align_2.GetEncodingValue() << 4) |
26126 first.Encode(22, 12) | (rn.GetCode() << 16));
26127 return;
26128 }
26129 }
26130 }
26131 }
26132 if (operand.IsPlainRegister()) {
26133 Register rn = operand.GetBaseRegister();
26134 Alignment align = operand.GetAlignment();
26135 Register rm = operand.GetOffsetRegister();
26136 Dt_size_6 encoded_dt(dt);
26137 Dt_size_7 encoded_dt_2(dt);
26138 Align_align_5 encoded_align_1(align, nreglist);
26139 Align_index_align_1 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026140 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026141 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26142 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26143 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026144 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026145 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26146 const DRegister& first = nreglist.GetFirstDRegister();
26147 uint32_t len_encoding;
26148 switch (nreglist.GetLength()) {
26149 default:
26150 VIXL_UNREACHABLE_OR_FALLTHROUGH();
26151 case 1:
26152 len_encoding = 0x7;
26153 break;
26154 case 2:
26155 len_encoding = 0xa;
26156 break;
26157 case 3:
26158 len_encoding = 0x6;
26159 break;
26160 case 4:
26161 len_encoding = 0x2;
26162 break;
26163 }
26164 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26165 (encoded_align_1.GetEncodingValue() << 4) |
26166 first.Encode(22, 12) | (len_encoding << 8) |
26167 (rn.GetCode() << 16) | rm.GetCode());
26168 AdvanceIT();
26169 return;
26170 }
26171 }
26172 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26173 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026174 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26175 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026176 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26177 const DRegister& first = nreglist.GetFirstDRegister();
26178 EmitT32_32(0xf9800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26179 (encoded_align_2.GetEncodingValue() << 4) |
26180 first.Encode(22, 12) | (rn.GetCode() << 16) |
26181 rm.GetCode());
26182 AdvanceIT();
26183 return;
26184 }
26185 }
26186 } else {
26187 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26188 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26189 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026190 !rm.IsPC() && !rm.IsSP() && (!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(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26211 (encoded_align_1.GetEncodingValue() << 4) |
26212 first.Encode(22, 12) | (len_encoding << 8) |
26213 (rn.GetCode() << 16) | rm.GetCode());
26214 return;
26215 }
26216 }
26217 // VST1{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26218 if (encoded_dt_2.IsValid() && nreglist.IsTransferOneLane() &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026219 (nreglist.GetLength() == 1) && !rm.IsPC() && !rm.IsSP() &&
26220 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026221 if (cond.Is(al)) {
26222 const DRegister& first = nreglist.GetFirstDRegister();
26223 EmitA32(0xf4800000U | (encoded_dt_2.GetEncodingValue() << 10) |
26224 (encoded_align_2.GetEncodingValue() << 4) |
26225 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26226 return;
26227 }
26228 }
26229 }
26230 }
26231 Delegate(kVst1, &Assembler::vst1, cond, dt, nreglist, operand);
26232}
26233
26234void Assembler::vst2(Condition cond,
26235 DataType dt,
26236 const NeonRegisterList& nreglist,
26237 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026238 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026239 CheckIT(cond);
26240 if (operand.IsImmediateZero()) {
26241 Register rn = operand.GetBaseRegister();
26242 Alignment align = operand.GetAlignment();
26243 Dt_size_7 encoded_dt(dt);
26244 Align_align_2 encoded_align_1(align, nreglist);
26245 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026246 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026247 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26248 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26249 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26250 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26251 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026252 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026253 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026254 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26255 const DRegister& first = nreglist.GetFirstDRegister();
26256 uint32_t len_encoding;
26257 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26258 len_encoding = 0x8;
26259 }
26260 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26261 len_encoding = 0x9;
26262 }
26263 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26264 len_encoding = 0x3;
26265 }
26266 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26267 (encoded_align_1.GetEncodingValue() << 4) |
26268 first.Encode(22, 12) | (len_encoding << 8) |
26269 (rn.GetCode() << 16));
26270 AdvanceIT();
26271 return;
26272 }
26273 }
26274 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26275 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26276 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26277 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26278 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026279 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026280 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026281 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26282 const DRegister& first = nreglist.GetFirstDRegister();
26283 uint32_t len_encoding;
26284 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26285 len_encoding = 0x8;
26286 }
26287 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26288 len_encoding = 0x9;
26289 }
26290 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26291 len_encoding = 0x3;
26292 }
26293 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26294 (encoded_align_1.GetEncodingValue() << 4) |
26295 first.Encode(22, 12) | (len_encoding << 8) |
26296 (rn.GetCode() << 16));
26297 AdvanceIT();
26298 return;
26299 }
26300 }
26301 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26302 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26303 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26304 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026305 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026306 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026307 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26308 const DRegister& first = nreglist.GetFirstDRegister();
26309 EmitT32_32(0xf980010fU | (encoded_dt.GetEncodingValue() << 10) |
26310 (encoded_align_2.GetEncodingValue() << 4) |
26311 first.Encode(22, 12) | (rn.GetCode() << 16));
26312 AdvanceIT();
26313 return;
26314 }
26315 }
26316 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26317 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26318 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26319 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026320 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026321 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026322 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26323 const DRegister& first = nreglist.GetFirstDRegister();
26324 EmitT32_32(0xf980010dU | (encoded_dt.GetEncodingValue() << 10) |
26325 (encoded_align_2.GetEncodingValue() << 4) |
26326 first.Encode(22, 12) | (rn.GetCode() << 16));
26327 AdvanceIT();
26328 return;
26329 }
26330 }
26331 } else {
26332 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26333 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26334 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26335 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26336 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026337 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026338 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026339 if (cond.Is(al)) {
26340 const DRegister& first = nreglist.GetFirstDRegister();
26341 uint32_t len_encoding;
26342 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26343 len_encoding = 0x8;
26344 }
26345 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26346 len_encoding = 0x9;
26347 }
26348 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26349 len_encoding = 0x3;
26350 }
26351 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26352 (encoded_align_1.GetEncodingValue() << 4) |
26353 first.Encode(22, 12) | (len_encoding << 8) |
26354 (rn.GetCode() << 16));
26355 return;
26356 }
26357 }
26358 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
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.IsPostIndex() && 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)) {
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 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26378 (encoded_align_1.GetEncodingValue() << 4) |
26379 first.Encode(22, 12) | (len_encoding << 8) |
26380 (rn.GetCode() << 16));
26381 return;
26382 }
26383 }
26384 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26385 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26386 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26387 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026388 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026389 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026390 if (cond.Is(al)) {
26391 const DRegister& first = nreglist.GetFirstDRegister();
26392 EmitA32(0xf480010fU | (encoded_dt.GetEncodingValue() << 10) |
26393 (encoded_align_2.GetEncodingValue() << 4) |
26394 first.Encode(22, 12) | (rn.GetCode() << 16));
26395 return;
26396 }
26397 }
26398 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26399 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26400 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26401 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026402 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026403 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026404 if (cond.Is(al)) {
26405 const DRegister& first = nreglist.GetFirstDRegister();
26406 EmitA32(0xf480010dU | (encoded_dt.GetEncodingValue() << 10) |
26407 (encoded_align_2.GetEncodingValue() << 4) |
26408 first.Encode(22, 12) | (rn.GetCode() << 16));
26409 return;
26410 }
26411 }
26412 }
26413 }
26414 if (operand.IsPlainRegister()) {
26415 Register rn = operand.GetBaseRegister();
26416 Alignment align = operand.GetAlignment();
26417 Register rm = operand.GetOffsetRegister();
26418 Dt_size_7 encoded_dt(dt);
26419 Align_align_2 encoded_align_1(align, nreglist);
26420 Align_index_align_2 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026421 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026422 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26423 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26424 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26425 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26426 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026427 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026428 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26429 const DRegister& first = nreglist.GetFirstDRegister();
26430 uint32_t len_encoding;
26431 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26432 len_encoding = 0x8;
26433 }
26434 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26435 len_encoding = 0x9;
26436 }
26437 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26438 len_encoding = 0x3;
26439 }
26440 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26441 (encoded_align_1.GetEncodingValue() << 4) |
26442 first.Encode(22, 12) | (len_encoding << 8) |
26443 (rn.GetCode() << 16) | rm.GetCode());
26444 AdvanceIT();
26445 return;
26446 }
26447 }
26448 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26449 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26450 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26451 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026452 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026453 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26454 const DRegister& first = nreglist.GetFirstDRegister();
26455 EmitT32_32(0xf9800100U | (encoded_dt.GetEncodingValue() << 10) |
26456 (encoded_align_2.GetEncodingValue() << 4) |
26457 first.Encode(22, 12) | (rn.GetCode() << 16) |
26458 rm.GetCode());
26459 AdvanceIT();
26460 return;
26461 }
26462 }
26463 } else {
26464 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26465 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26466 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26467 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) ||
26468 (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026469 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026470 if (cond.Is(al)) {
26471 const DRegister& first = nreglist.GetFirstDRegister();
26472 uint32_t len_encoding;
26473 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) {
26474 len_encoding = 0x8;
26475 }
26476 if (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2)) {
26477 len_encoding = 0x9;
26478 }
26479 if (nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) {
26480 len_encoding = 0x3;
26481 }
26482 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26483 (encoded_align_1.GetEncodingValue() << 4) |
26484 first.Encode(22, 12) | (len_encoding << 8) |
26485 (rn.GetCode() << 16) | rm.GetCode());
26486 return;
26487 }
26488 }
26489 // VST2{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26490 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26491 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 2)) ||
26492 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 2))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026493 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026494 if (cond.Is(al)) {
26495 const DRegister& first = nreglist.GetFirstDRegister();
26496 EmitA32(0xf4800100U | (encoded_dt.GetEncodingValue() << 10) |
26497 (encoded_align_2.GetEncodingValue() << 4) |
26498 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26499 return;
26500 }
26501 }
26502 }
26503 }
26504 Delegate(kVst2, &Assembler::vst2, cond, dt, nreglist, operand);
26505}
26506
26507void Assembler::vst3(Condition cond,
26508 DataType dt,
26509 const NeonRegisterList& nreglist,
26510 const AlignedMemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026511 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026512 CheckIT(cond);
26513 if (operand.IsImmediateZero()) {
26514 Register rn = operand.GetBaseRegister();
26515 Alignment align = operand.GetAlignment();
26516 Dt_size_7 encoded_dt(dt);
26517 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026518 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026519 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26520 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26521 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26522 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026523 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026524 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026525 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26526 const DRegister& first = nreglist.GetFirstDRegister();
26527 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26528 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26529 (encoded_align_1.GetEncodingValue() << 4) |
26530 first.Encode(22, 12) | (len_encoding << 8) |
26531 (rn.GetCode() << 16));
26532 AdvanceIT();
26533 return;
26534 }
26535 }
26536 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26537 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26538 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26539 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026540 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026541 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026542 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26543 const DRegister& first = nreglist.GetFirstDRegister();
26544 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26545 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26546 (encoded_align_1.GetEncodingValue() << 4) |
26547 first.Encode(22, 12) | (len_encoding << 8) |
26548 (rn.GetCode() << 16));
26549 AdvanceIT();
26550 return;
26551 }
26552 }
26553 } else {
26554 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26555 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26556 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26557 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026558 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026559 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026560 if (cond.Is(al)) {
26561 const DRegister& first = nreglist.GetFirstDRegister();
26562 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26563 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26564 (encoded_align_1.GetEncodingValue() << 4) |
26565 first.Encode(22, 12) | (len_encoding << 8) |
26566 (rn.GetCode() << 16));
26567 return;
26568 }
26569 }
26570 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26571 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26572 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26573 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026574 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026575 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026576 if (cond.Is(al)) {
26577 const DRegister& first = nreglist.GetFirstDRegister();
26578 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26579 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26580 (encoded_align_1.GetEncodingValue() << 4) |
26581 first.Encode(22, 12) | (len_encoding << 8) |
26582 (rn.GetCode() << 16));
26583 return;
26584 }
26585 }
26586 }
26587 }
26588 if (operand.IsPlainRegister()) {
26589 Register rn = operand.GetBaseRegister();
26590 Alignment align = operand.GetAlignment();
26591 Register rm = operand.GetOffsetRegister();
26592 Dt_size_7 encoded_dt(dt);
26593 Align_align_3 encoded_align_1(align);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026594 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026595 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26596 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26597 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26598 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026599 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026600 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26601 const DRegister& first = nreglist.GetFirstDRegister();
26602 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26603 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26604 (encoded_align_1.GetEncodingValue() << 4) |
26605 first.Encode(22, 12) | (len_encoding << 8) |
26606 (rn.GetCode() << 16) | rm.GetCode());
26607 AdvanceIT();
26608 return;
26609 }
26610 }
26611 } else {
26612 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26613 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26614 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26615 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026616 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026617 if (cond.Is(al)) {
26618 const DRegister& first = nreglist.GetFirstDRegister();
26619 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x4 : 0x5;
26620 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26621 (encoded_align_1.GetEncodingValue() << 4) |
26622 first.Encode(22, 12) | (len_encoding << 8) |
26623 (rn.GetCode() << 16) | rm.GetCode());
26624 return;
26625 }
26626 }
26627 }
26628 }
26629 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26630}
26631
26632void Assembler::vst3(Condition cond,
26633 DataType dt,
26634 const NeonRegisterList& nreglist,
26635 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026636 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026637 CheckIT(cond);
26638 if (operand.IsImmediateZero()) {
26639 Register rn = operand.GetBaseRegister();
26640 Dt_size_7 encoded_dt(dt);
26641 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026642 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026643 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; T1
26644 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26645 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26646 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026647 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026648 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26649 const DRegister& first = nreglist.GetFirstDRegister();
26650 EmitT32_32(0xf980020fU | (encoded_dt.GetEncodingValue() << 10) |
26651 (encoded_align_1.GetEncodingValue() << 4) |
26652 first.Encode(22, 12) | (rn.GetCode() << 16));
26653 AdvanceIT();
26654 return;
26655 }
26656 }
26657 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; T1
26658 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26659 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26660 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026661 operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026662 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26663 const DRegister& first = nreglist.GetFirstDRegister();
26664 EmitT32_32(0xf980020dU | (encoded_dt.GetEncodingValue() << 10) |
26665 (encoded_align_1.GetEncodingValue() << 4) |
26666 first.Encode(22, 12) | (rn.GetCode() << 16));
26667 AdvanceIT();
26668 return;
26669 }
26670 }
26671 } else {
26672 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>] ; A1
26673 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26674 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26675 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026676 operand.IsOffset() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026677 if (cond.Is(al)) {
26678 const DRegister& first = nreglist.GetFirstDRegister();
26679 EmitA32(0xf480020fU | (encoded_dt.GetEncodingValue() << 10) |
26680 (encoded_align_1.GetEncodingValue() << 4) |
26681 first.Encode(22, 12) | (rn.GetCode() << 16));
26682 return;
26683 }
26684 }
26685 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>]! ; A1
26686 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26687 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26688 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026689 operand.IsPreIndex() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026690 if (cond.Is(al)) {
26691 const DRegister& first = nreglist.GetFirstDRegister();
26692 EmitA32(0xf480020dU | (encoded_dt.GetEncodingValue() << 10) |
26693 (encoded_align_1.GetEncodingValue() << 4) |
26694 first.Encode(22, 12) | (rn.GetCode() << 16));
26695 return;
26696 }
26697 }
26698 }
26699 }
26700 if (operand.IsPlainRegister()) {
26701 Register rn = operand.GetBaseRegister();
26702 Sign sign = operand.GetSign();
26703 Register rm = operand.GetOffsetRegister();
26704 Dt_size_7 encoded_dt(dt);
26705 Index_1 encoded_align_1(nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026706 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026707 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; T1
26708 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26709 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26710 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026711 sign.IsPlus() && operand.IsPostIndex() &&
26712 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026713 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26714 const DRegister& first = nreglist.GetFirstDRegister();
26715 EmitT32_32(0xf9800200U | (encoded_dt.GetEncodingValue() << 10) |
26716 (encoded_align_1.GetEncodingValue() << 4) |
26717 first.Encode(22, 12) | (rn.GetCode() << 16) |
26718 rm.GetCode());
26719 AdvanceIT();
26720 return;
26721 }
26722 }
26723 } else {
26724 // VST3{<c>}{<q>}.<dt> <list>, [<Rn>], #<Rm> ; A1
26725 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26726 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 3)) ||
26727 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 3))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026728 sign.IsPlus() && operand.IsPostIndex() &&
26729 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026730 if (cond.Is(al)) {
26731 const DRegister& first = nreglist.GetFirstDRegister();
26732 EmitA32(0xf4800200U | (encoded_dt.GetEncodingValue() << 10) |
26733 (encoded_align_1.GetEncodingValue() << 4) |
26734 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26735 return;
26736 }
26737 }
26738 }
26739 }
26740 Delegate(kVst3, &Assembler::vst3, cond, dt, nreglist, operand);
26741}
26742
26743void Assembler::vst4(Condition cond,
26744 DataType dt,
26745 const NeonRegisterList& nreglist,
26746 const AlignedMemOperand& 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 Alignment align = operand.GetAlignment();
26752 Dt_size_7 encoded_dt(dt);
26753 Align_align_4 encoded_align_1(align);
26754 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026755 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026756 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26757 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26758 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26759 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026760 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026761 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026762 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26763 const DRegister& first = nreglist.GetFirstDRegister();
26764 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26765 EmitT32_32(0xf900000fU | (encoded_dt.GetEncodingValue() << 6) |
26766 (encoded_align_1.GetEncodingValue() << 4) |
26767 first.Encode(22, 12) | (len_encoding << 8) |
26768 (rn.GetCode() << 16));
26769 AdvanceIT();
26770 return;
26771 }
26772 }
26773 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26774 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26775 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26776 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026777 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026778 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026779 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26780 const DRegister& first = nreglist.GetFirstDRegister();
26781 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26782 EmitT32_32(0xf900000dU | (encoded_dt.GetEncodingValue() << 6) |
26783 (encoded_align_1.GetEncodingValue() << 4) |
26784 first.Encode(22, 12) | (len_encoding << 8) |
26785 (rn.GetCode() << 16));
26786 AdvanceIT();
26787 return;
26788 }
26789 }
26790 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; T1
26791 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26792 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26793 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026794 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026795 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026796 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26797 const DRegister& first = nreglist.GetFirstDRegister();
26798 EmitT32_32(0xf980030fU | (encoded_dt.GetEncodingValue() << 10) |
26799 (encoded_align_2.GetEncodingValue() << 4) |
26800 first.Encode(22, 12) | (rn.GetCode() << 16));
26801 AdvanceIT();
26802 return;
26803 }
26804 }
26805 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; T1
26806 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26807 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26808 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026809 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026810 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026811 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26812 const DRegister& first = nreglist.GetFirstDRegister();
26813 EmitT32_32(0xf980030dU | (encoded_dt.GetEncodingValue() << 10) |
26814 (encoded_align_2.GetEncodingValue() << 4) |
26815 first.Encode(22, 12) | (rn.GetCode() << 16));
26816 AdvanceIT();
26817 return;
26818 }
26819 }
26820 } else {
26821 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26822 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26823 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26824 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026825 operand.IsOffset() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026826 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026827 if (cond.Is(al)) {
26828 const DRegister& first = nreglist.GetFirstDRegister();
26829 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26830 EmitA32(0xf400000fU | (encoded_dt.GetEncodingValue() << 6) |
26831 (encoded_align_1.GetEncodingValue() << 4) |
26832 first.Encode(22, 12) | (len_encoding << 8) |
26833 (rn.GetCode() << 16));
26834 return;
26835 }
26836 }
26837 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26838 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26839 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26840 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026841 operand.IsPostIndex() && encoded_align_1.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026842 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026843 if (cond.Is(al)) {
26844 const DRegister& first = nreglist.GetFirstDRegister();
26845 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26846 EmitA32(0xf400000dU | (encoded_dt.GetEncodingValue() << 6) |
26847 (encoded_align_1.GetEncodingValue() << 4) |
26848 first.Encode(22, 12) | (len_encoding << 8) |
26849 (rn.GetCode() << 16));
26850 return;
26851 }
26852 }
26853 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}] ; A1
26854 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26855 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26856 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026857 operand.IsOffset() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026858 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026859 if (cond.Is(al)) {
26860 const DRegister& first = nreglist.GetFirstDRegister();
26861 EmitA32(0xf480030fU | (encoded_dt.GetEncodingValue() << 10) |
26862 (encoded_align_2.GetEncodingValue() << 4) |
26863 first.Encode(22, 12) | (rn.GetCode() << 16));
26864 return;
26865 }
26866 }
26867 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}]! ; A1
26868 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26869 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26870 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080026871 operand.IsPostIndex() && encoded_align_2.IsValid() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026872 (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026873 if (cond.Is(al)) {
26874 const DRegister& first = nreglist.GetFirstDRegister();
26875 EmitA32(0xf480030dU | (encoded_dt.GetEncodingValue() << 10) |
26876 (encoded_align_2.GetEncodingValue() << 4) |
26877 first.Encode(22, 12) | (rn.GetCode() << 16));
26878 return;
26879 }
26880 }
26881 }
26882 }
26883 if (operand.IsPlainRegister()) {
26884 Register rn = operand.GetBaseRegister();
26885 Alignment align = operand.GetAlignment();
26886 Register rm = operand.GetOffsetRegister();
26887 Dt_size_7 encoded_dt(dt);
26888 Align_align_4 encoded_align_1(align);
26889 Align_index_align_3 encoded_align_2(align, nreglist, dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026890 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026891 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26892 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26893 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26894 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026895 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026896 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26897 const DRegister& first = nreglist.GetFirstDRegister();
26898 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26899 EmitT32_32(0xf9000000U | (encoded_dt.GetEncodingValue() << 6) |
26900 (encoded_align_1.GetEncodingValue() << 4) |
26901 first.Encode(22, 12) | (len_encoding << 8) |
26902 (rn.GetCode() << 16) | rm.GetCode());
26903 AdvanceIT();
26904 return;
26905 }
26906 }
26907 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; T1
26908 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26909 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26910 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026911 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026912 if (cond.Is(al) || AllowStronglyDiscouraged()) {
26913 const DRegister& first = nreglist.GetFirstDRegister();
26914 EmitT32_32(0xf9800300U | (encoded_dt.GetEncodingValue() << 10) |
26915 (encoded_align_2.GetEncodingValue() << 4) |
26916 first.Encode(22, 12) | (rn.GetCode() << 16) |
26917 rm.GetCode());
26918 AdvanceIT();
26919 return;
26920 }
26921 }
26922 } else {
26923 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26924 if (encoded_dt.IsValid() && nreglist.IsTransferMultipleLanes() &&
26925 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26926 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026927 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026928 if (cond.Is(al)) {
26929 const DRegister& first = nreglist.GetFirstDRegister();
26930 uint32_t len_encoding = nreglist.IsSingleSpaced() ? 0x0 : 0x1;
26931 EmitA32(0xf4000000U | (encoded_dt.GetEncodingValue() << 6) |
26932 (encoded_align_1.GetEncodingValue() << 4) |
26933 first.Encode(22, 12) | (len_encoding << 8) |
26934 (rn.GetCode() << 16) | rm.GetCode());
26935 return;
26936 }
26937 }
26938 // VST4{<c>}{<q>}.<dt> <list>, [<Rn>{:<align>}], <Rm> ; A1
26939 if (encoded_dt.IsValid() && nreglist.IsTransferOneLane() &&
26940 ((nreglist.IsSingleSpaced() && (nreglist.GetLength() == 4)) ||
26941 (nreglist.IsDoubleSpaced() && (nreglist.GetLength() == 4))) &&
Pierre Langlois960d28b2017-02-15 13:06:01 +000026942 !rm.IsPC() && !rm.IsSP() && (!rn.IsPC() || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026943 if (cond.Is(al)) {
26944 const DRegister& first = nreglist.GetFirstDRegister();
26945 EmitA32(0xf4800300U | (encoded_dt.GetEncodingValue() << 10) |
26946 (encoded_align_2.GetEncodingValue() << 4) |
26947 first.Encode(22, 12) | (rn.GetCode() << 16) | rm.GetCode());
26948 return;
26949 }
26950 }
26951 }
26952 }
26953 Delegate(kVst4, &Assembler::vst4, cond, dt, nreglist, operand);
26954}
26955
26956void Assembler::vstm(Condition cond,
26957 DataType dt,
26958 Register rn,
26959 WriteBack write_back,
26960 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026961 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026962 CheckIT(cond);
26963 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026964 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026965 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080026966 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026967 const DRegister& dreg = dreglist.GetFirstDRegister();
26968 unsigned len = dreglist.GetLength() * 2;
26969 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
26970 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
26971 (len & 0xff));
26972 AdvanceIT();
26973 return;
26974 }
26975 } else {
26976 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
26977 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080026978 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026979 const DRegister& dreg = dreglist.GetFirstDRegister();
26980 unsigned len = dreglist.GetLength() * 2;
26981 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
26982 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
26983 (len & 0xff));
26984 return;
26985 }
26986 }
26987 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, dreglist);
26988}
26989
26990void Assembler::vstm(Condition cond,
26991 DataType dt,
26992 Register rn,
26993 WriteBack write_back,
26994 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070026995 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010026996 CheckIT(cond);
26997 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010026998 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010026999 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
27000 const SRegister& sreg = sreglist.GetFirstSRegister();
27001 unsigned len = sreglist.GetLength();
27002 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27003 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27004 (len & 0xff));
27005 AdvanceIT();
27006 return;
27007 } else {
27008 // VSTM{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
27009 if (cond.IsNotNever()) {
27010 const SRegister& sreg = sreglist.GetFirstSRegister();
27011 unsigned len = sreglist.GetLength();
27012 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27013 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27014 (len & 0xff));
27015 return;
27016 }
27017 }
27018 Delegate(kVstm, &Assembler::vstm, cond, dt, rn, write_back, sreglist);
27019}
27020
27021void Assembler::vstmdb(Condition cond,
27022 DataType dt,
27023 Register rn,
27024 WriteBack write_back,
27025 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027026 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027027 CheckIT(cond);
27028 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027029 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027030 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; T1
27031 if (write_back.DoesWriteBack() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080027032 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027033 const DRegister& dreg = dreglist.GetFirstDRegister();
27034 unsigned len = dreglist.GetLength() * 2;
27035 EmitT32_32(0xed200b00U | (rn.GetCode() << 16) | dreg.Encode(22, 12) |
27036 (len & 0xff));
27037 AdvanceIT();
27038 return;
27039 }
27040 } else {
27041 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <dreglist> ; A1
27042 if (write_back.DoesWriteBack() && cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080027043 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027044 const DRegister& dreg = dreglist.GetFirstDRegister();
27045 unsigned len = dreglist.GetLength() * 2;
27046 EmitA32(0x0d200b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27047 dreg.Encode(22, 12) | (len & 0xff));
27048 return;
27049 }
27050 }
27051 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, dreglist);
27052}
27053
27054void Assembler::vstmdb(Condition cond,
27055 DataType dt,
27056 Register rn,
27057 WriteBack write_back,
27058 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027059 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027060 CheckIT(cond);
27061 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027062 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027063 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; T2
27064 if (write_back.DoesWriteBack()) {
27065 const SRegister& sreg = sreglist.GetFirstSRegister();
27066 unsigned len = sreglist.GetLength();
27067 EmitT32_32(0xed200a00U | (rn.GetCode() << 16) | sreg.Encode(22, 12) |
27068 (len & 0xff));
27069 AdvanceIT();
27070 return;
27071 }
27072 } else {
27073 // VSTMDB{<c>}{<q>}{.<size>} <Rn>!, <sreglist> ; A2
27074 if (write_back.DoesWriteBack() && cond.IsNotNever()) {
27075 const SRegister& sreg = sreglist.GetFirstSRegister();
27076 unsigned len = sreglist.GetLength();
27077 EmitA32(0x0d200a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27078 sreg.Encode(22, 12) | (len & 0xff));
27079 return;
27080 }
27081 }
27082 Delegate(kVstmdb, &Assembler::vstmdb, cond, dt, rn, write_back, sreglist);
27083}
27084
27085void Assembler::vstmia(Condition cond,
27086 DataType dt,
27087 Register rn,
27088 WriteBack write_back,
27089 DRegisterList dreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027090 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027091 CheckIT(cond);
27092 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027093 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027094 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; T1
Vincent Belliard942e3b72016-11-29 15:50:14 -080027095 if (((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027096 const DRegister& dreg = dreglist.GetFirstDRegister();
27097 unsigned len = dreglist.GetLength() * 2;
27098 EmitT32_32(0xec800b00U | (rn.GetCode() << 16) |
27099 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27100 (len & 0xff));
27101 AdvanceIT();
27102 return;
27103 }
27104 } else {
27105 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <dreglist> ; A1
27106 if (cond.IsNotNever() &&
Vincent Belliard942e3b72016-11-29 15:50:14 -080027107 ((dreglist.GetLength() <= 16) || AllowUnpredictable())) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027108 const DRegister& dreg = dreglist.GetFirstDRegister();
27109 unsigned len = dreglist.GetLength() * 2;
27110 EmitA32(0x0c800b00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27111 (write_back.GetWriteBackUint32() << 21) | dreg.Encode(22, 12) |
27112 (len & 0xff));
27113 return;
27114 }
27115 }
27116 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, dreglist);
27117}
27118
27119void Assembler::vstmia(Condition cond,
27120 DataType dt,
27121 Register rn,
27122 WriteBack write_back,
27123 SRegisterList sreglist) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027124 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027125 CheckIT(cond);
27126 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027127 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027128 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; T2
27129 const SRegister& sreg = sreglist.GetFirstSRegister();
27130 unsigned len = sreglist.GetLength();
27131 EmitT32_32(0xec800a00U | (rn.GetCode() << 16) |
27132 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27133 (len & 0xff));
27134 AdvanceIT();
27135 return;
27136 } else {
27137 // VSTMIA{<c>}{<q>}{.<size>} <Rn>{!}, <sreglist> ; A2
27138 if (cond.IsNotNever()) {
27139 const SRegister& sreg = sreglist.GetFirstSRegister();
27140 unsigned len = sreglist.GetLength();
27141 EmitA32(0x0c800a00U | (cond.GetCondition() << 28) | (rn.GetCode() << 16) |
27142 (write_back.GetWriteBackUint32() << 21) | sreg.Encode(22, 12) |
27143 (len & 0xff));
27144 return;
27145 }
27146 }
27147 Delegate(kVstmia, &Assembler::vstmia, cond, dt, rn, write_back, sreglist);
27148}
27149
27150void Assembler::vstr(Condition cond,
27151 DataType dt,
27152 DRegister rd,
27153 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027154 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027155 CheckIT(cond);
27156 if (operand.IsImmediate()) {
27157 Register rn = operand.GetBaseRegister();
27158 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027159 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027160 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; T1
27161 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027162 ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027163 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27164 uint32_t offset_ = abs(offset) >> 2;
27165 EmitT32_32(0xed000b00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27166 offset_ | (sign << 23));
27167 AdvanceIT();
27168 return;
27169 }
27170 } else {
27171 // VSTR{<c>}{<q>}{.64} <Dd>, [<Rn>{, #{+/-}<imm>}] ; A1
27172 if (dt.IsNoneOr(Untyped64) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027173 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027174 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27175 uint32_t offset_ = abs(offset) >> 2;
27176 EmitA32(0x0d000b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27177 (rn.GetCode() << 16) | offset_ | (sign << 23));
27178 return;
27179 }
27180 }
27181 }
27182 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27183}
27184
27185void Assembler::vstr(Condition cond,
27186 DataType dt,
27187 SRegister rd,
27188 const MemOperand& operand) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027189 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027190 CheckIT(cond);
27191 if (operand.IsImmediate()) {
27192 Register rn = operand.GetBaseRegister();
27193 int32_t offset = operand.GetOffsetImmediate();
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027194 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027195 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; T2
27196 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027197 ((offset % 4) == 0) && operand.IsOffset()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027198 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27199 uint32_t offset_ = abs(offset) >> 2;
27200 EmitT32_32(0xed000a00U | rd.Encode(22, 12) | (rn.GetCode() << 16) |
27201 offset_ | (sign << 23));
27202 AdvanceIT();
27203 return;
27204 }
27205 } else {
27206 // VSTR{<c>}{<q>}{.32} <Sd>, [<Rn>{, #{+/-}<imm>}] ; A2
27207 if (dt.IsNoneOr(Untyped32) && (offset >= -1020) && (offset <= 1020) &&
Vincent Belliardc0ee83f2016-11-17 15:05:00 -080027208 ((offset % 4) == 0) && operand.IsOffset() && cond.IsNotNever()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027209 uint32_t sign = operand.GetSign().IsPlus() ? 1 : 0;
27210 uint32_t offset_ = abs(offset) >> 2;
27211 EmitA32(0x0d000a00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27212 (rn.GetCode() << 16) | offset_ | (sign << 23));
27213 return;
27214 }
27215 }
27216 }
27217 Delegate(kVstr, &Assembler::vstr, cond, dt, rd, operand);
27218}
27219
27220void Assembler::vsub(
27221 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027222 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027223 CheckIT(cond);
27224 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027225 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027226 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; T1
27227 if (dt.Is(F32)) {
27228 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27229 EmitT32_32(0xef200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27230 rm.Encode(5, 0));
27231 AdvanceIT();
27232 return;
27233 }
27234 }
27235 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; T2
27236 if (dt.Is(F64)) {
27237 EmitT32_32(0xee300b40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27238 rm.Encode(5, 0));
27239 AdvanceIT();
27240 return;
27241 }
27242 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27243 if (encoded_dt.IsValid()) {
27244 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27245 EmitT32_32(0xff000800U | (encoded_dt.GetEncodingValue() << 20) |
27246 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27247 AdvanceIT();
27248 return;
27249 }
27250 }
27251 } else {
27252 // VSUB{<c>}{<q>}.F32 {<Dd>}, <Dn>, <Dm> ; A1
27253 if (dt.Is(F32)) {
27254 if (cond.Is(al)) {
27255 EmitA32(0xf2200d00U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27256 rm.Encode(5, 0));
27257 return;
27258 }
27259 }
27260 // VSUB{<c>}{<q>}.F64 {<Dd>}, <Dn>, <Dm> ; A2
27261 if (dt.Is(F64) && cond.IsNotNever()) {
27262 EmitA32(0x0e300b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27263 rn.Encode(7, 16) | rm.Encode(5, 0));
27264 return;
27265 }
27266 // VSUB{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27267 if (encoded_dt.IsValid()) {
27268 if (cond.Is(al)) {
27269 EmitA32(0xf3000800U | (encoded_dt.GetEncodingValue() << 20) |
27270 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27271 return;
27272 }
27273 }
27274 }
27275 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27276}
27277
27278void Assembler::vsub(
27279 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027280 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027281 CheckIT(cond);
27282 Dt_size_2 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027283 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027284 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; T1
27285 if (dt.Is(F32)) {
27286 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27287 EmitT32_32(0xef200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27288 rm.Encode(5, 0));
27289 AdvanceIT();
27290 return;
27291 }
27292 }
27293 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27294 if (encoded_dt.IsValid()) {
27295 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27296 EmitT32_32(0xff000840U | (encoded_dt.GetEncodingValue() << 20) |
27297 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27298 AdvanceIT();
27299 return;
27300 }
27301 }
27302 } else {
27303 // VSUB{<c>}{<q>}.F32 {<Qd>}, <Qn>, <Qm> ; A1
27304 if (dt.Is(F32)) {
27305 if (cond.Is(al)) {
27306 EmitA32(0xf2200d40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27307 rm.Encode(5, 0));
27308 return;
27309 }
27310 }
27311 // VSUB{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27312 if (encoded_dt.IsValid()) {
27313 if (cond.Is(al)) {
27314 EmitA32(0xf3000840U | (encoded_dt.GetEncodingValue() << 20) |
27315 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27316 return;
27317 }
27318 }
27319 }
27320 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27321}
27322
27323void Assembler::vsub(
27324 Condition cond, DataType dt, SRegister rd, SRegister rn, SRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027325 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027326 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027327 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027328 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; T2
27329 if (dt.Is(F32)) {
27330 EmitT32_32(0xee300a40U | rd.Encode(22, 12) | rn.Encode(7, 16) |
27331 rm.Encode(5, 0));
27332 AdvanceIT();
27333 return;
27334 }
27335 } else {
27336 // VSUB{<c>}{<q>}.F32 {<Sd>}, <Sn>, <Sm> ; A2
27337 if (dt.Is(F32) && cond.IsNotNever()) {
27338 EmitA32(0x0e300a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
27339 rn.Encode(7, 16) | rm.Encode(5, 0));
27340 return;
27341 }
27342 }
27343 Delegate(kVsub, &Assembler::vsub, cond, dt, rd, rn, rm);
27344}
27345
27346void Assembler::vsubhn(
27347 Condition cond, DataType dt, DRegister rd, QRegister rn, QRegister 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_3 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027351 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027352 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; T1
27353 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27354 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27355 EmitT32_32(0xef800600U | (encoded_dt.GetEncodingValue() << 20) |
27356 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27357 AdvanceIT();
27358 return;
27359 }
27360 }
27361 } else {
27362 // VSUBHN{<c>}{<q>}.<dt> <Dd>, <Qn>, <Qm> ; A1
27363 if (encoded_dt.IsValid() && (dt.Is(I16) || dt.Is(I32) || dt.Is(I64))) {
27364 if (cond.Is(al)) {
27365 EmitA32(0xf2800600U | (encoded_dt.GetEncodingValue() << 20) |
27366 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27367 return;
27368 }
27369 }
27370 }
27371 Delegate(kVsubhn, &Assembler::vsubhn, cond, dt, rd, rn, rm);
27372}
27373
27374void Assembler::vsubl(
27375 Condition cond, DataType dt, QRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027376 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027377 CheckIT(cond);
27378 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027379 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027380 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; T1
27381 if (encoded_dt.IsValid()) {
27382 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27383 EmitT32_32(0xef800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27384 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27385 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27386 AdvanceIT();
27387 return;
27388 }
27389 }
27390 } else {
27391 // VSUBL{<c>}{<q>}.<dt> <Qd>, <Dn>, <Dm> ; A1
27392 if (encoded_dt.IsValid()) {
27393 if (cond.Is(al)) {
27394 EmitA32(0xf2800200U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27395 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27396 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27397 return;
27398 }
27399 }
27400 }
27401 Delegate(kVsubl, &Assembler::vsubl, cond, dt, rd, rn, rm);
27402}
27403
27404void Assembler::vsubw(
27405 Condition cond, DataType dt, QRegister rd, QRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027406 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027407 CheckIT(cond);
27408 Dt_U_size_1 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027409 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027410 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; T1
27411 if (encoded_dt.IsValid()) {
27412 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27413 EmitT32_32(0xef800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27414 ((encoded_dt.GetEncodingValue() & 0x4) << 26) |
27415 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27416 AdvanceIT();
27417 return;
27418 }
27419 }
27420 } else {
27421 // VSUBW{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Dm> ; A1
27422 if (encoded_dt.IsValid()) {
27423 if (cond.Is(al)) {
27424 EmitA32(0xf2800300U | ((encoded_dt.GetEncodingValue() & 0x3) << 20) |
27425 ((encoded_dt.GetEncodingValue() & 0x4) << 22) |
27426 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27427 return;
27428 }
27429 }
27430 }
27431 Delegate(kVsubw, &Assembler::vsubw, cond, dt, rd, rn, rm);
27432}
27433
27434void Assembler::vswp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027435 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027436 CheckIT(cond);
27437 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027438 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027439 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; T1
27440 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27441 EmitT32_32(0xffb20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27442 AdvanceIT();
27443 return;
27444 }
27445 } else {
27446 // VSWP{<c>}{<q>}{.<dt>} <Dd>, <Dm> ; A1
27447 if (cond.Is(al)) {
27448 EmitA32(0xf3b20000U | rd.Encode(22, 12) | rm.Encode(5, 0));
27449 return;
27450 }
27451 }
27452 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27453}
27454
27455void Assembler::vswp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027456 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027457 CheckIT(cond);
27458 USE(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027459 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027460 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; T1
27461 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27462 EmitT32_32(0xffb20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27463 AdvanceIT();
27464 return;
27465 }
27466 } else {
27467 // VSWP{<c>}{<q>}{.<dt>} <Qd>, <Qm> ; A1
27468 if (cond.Is(al)) {
27469 EmitA32(0xf3b20040U | rd.Encode(22, 12) | rm.Encode(5, 0));
27470 return;
27471 }
27472 }
27473 Delegate(kVswp, &Assembler::vswp, cond, dt, rd, rm);
27474}
27475
27476void Assembler::vtbl(Condition cond,
27477 DataType dt,
27478 DRegister rd,
27479 const NeonRegisterList& nreglist,
27480 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027481 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027482 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027483 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027484 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27485 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27486 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27487 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27488 const DRegister& first = nreglist.GetFirstDRegister();
27489 uint32_t len_encoding = nreglist.GetLength() - 1;
27490 EmitT32_32(0xffb00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27491 (len_encoding << 8) | rm.Encode(5, 0));
27492 AdvanceIT();
27493 return;
27494 }
27495 }
27496 } else {
27497 // VTBL{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27498 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27499 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27500 if (cond.Is(al)) {
27501 const DRegister& first = nreglist.GetFirstDRegister();
27502 uint32_t len_encoding = nreglist.GetLength() - 1;
27503 EmitA32(0xf3b00800U | rd.Encode(22, 12) | first.Encode(7, 16) |
27504 (len_encoding << 8) | rm.Encode(5, 0));
27505 return;
27506 }
27507 }
27508 }
27509 Delegate(kVtbl, &Assembler::vtbl, cond, dt, rd, nreglist, rm);
27510}
27511
27512void Assembler::vtbx(Condition cond,
27513 DataType dt,
27514 DRegister rd,
27515 const NeonRegisterList& nreglist,
27516 DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027517 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027518 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027519 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027520 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; T1
27521 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27522 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27523 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27524 const DRegister& first = nreglist.GetFirstDRegister();
27525 uint32_t len_encoding = nreglist.GetLength() - 1;
27526 EmitT32_32(0xffb00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27527 (len_encoding << 8) | rm.Encode(5, 0));
27528 AdvanceIT();
27529 return;
27530 }
27531 }
27532 } else {
27533 // VTBX{<c>}{<q>}.8 <Dd>, <list>, <Dm> ; A1
27534 if (dt.Is(Untyped8) && nreglist.IsTransferMultipleLanes() &&
27535 (nreglist.IsSingleSpaced()) && (nreglist.GetLength() <= 4)) {
27536 if (cond.Is(al)) {
27537 const DRegister& first = nreglist.GetFirstDRegister();
27538 uint32_t len_encoding = nreglist.GetLength() - 1;
27539 EmitA32(0xf3b00840U | rd.Encode(22, 12) | first.Encode(7, 16) |
27540 (len_encoding << 8) | rm.Encode(5, 0));
27541 return;
27542 }
27543 }
27544 }
27545 Delegate(kVtbx, &Assembler::vtbx, cond, dt, rd, nreglist, rm);
27546}
27547
27548void Assembler::vtrn(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027549 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027550 CheckIT(cond);
27551 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027552 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027553 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27554 if (encoded_dt.IsValid()) {
27555 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27556 EmitT32_32(0xffb20080U | (encoded_dt.GetEncodingValue() << 18) |
27557 rd.Encode(22, 12) | rm.Encode(5, 0));
27558 AdvanceIT();
27559 return;
27560 }
27561 }
27562 } else {
27563 // VTRN{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27564 if (encoded_dt.IsValid()) {
27565 if (cond.Is(al)) {
27566 EmitA32(0xf3b20080U | (encoded_dt.GetEncodingValue() << 18) |
27567 rd.Encode(22, 12) | rm.Encode(5, 0));
27568 return;
27569 }
27570 }
27571 }
27572 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27573}
27574
27575void Assembler::vtrn(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027576 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027577 CheckIT(cond);
27578 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027579 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027580 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27581 if (encoded_dt.IsValid()) {
27582 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27583 EmitT32_32(0xffb200c0U | (encoded_dt.GetEncodingValue() << 18) |
27584 rd.Encode(22, 12) | rm.Encode(5, 0));
27585 AdvanceIT();
27586 return;
27587 }
27588 }
27589 } else {
27590 // VTRN{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27591 if (encoded_dt.IsValid()) {
27592 if (cond.Is(al)) {
27593 EmitA32(0xf3b200c0U | (encoded_dt.GetEncodingValue() << 18) |
27594 rd.Encode(22, 12) | rm.Encode(5, 0));
27595 return;
27596 }
27597 }
27598 }
27599 Delegate(kVtrn, &Assembler::vtrn, cond, dt, rd, rm);
27600}
27601
27602void Assembler::vtst(
27603 Condition cond, DataType dt, DRegister rd, DRegister rn, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027604 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027605 CheckIT(cond);
27606 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027607 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027608 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; T1
27609 if (encoded_dt.IsValid()) {
27610 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27611 EmitT32_32(0xef000810U | (encoded_dt.GetEncodingValue() << 20) |
27612 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27613 AdvanceIT();
27614 return;
27615 }
27616 }
27617 } else {
27618 // VTST{<c>}{<q>}.<dt> {<Dd>}, <Dn>, <Dm> ; A1
27619 if (encoded_dt.IsValid()) {
27620 if (cond.Is(al)) {
27621 EmitA32(0xf2000810U | (encoded_dt.GetEncodingValue() << 20) |
27622 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27623 return;
27624 }
27625 }
27626 }
27627 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27628}
27629
27630void Assembler::vtst(
27631 Condition cond, DataType dt, QRegister rd, QRegister rn, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027632 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027633 CheckIT(cond);
27634 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027635 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027636 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; T1
27637 if (encoded_dt.IsValid()) {
27638 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27639 EmitT32_32(0xef000850U | (encoded_dt.GetEncodingValue() << 20) |
27640 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27641 AdvanceIT();
27642 return;
27643 }
27644 }
27645 } else {
27646 // VTST{<c>}{<q>}.<dt> {<Qd>}, <Qn>, <Qm> ; A1
27647 if (encoded_dt.IsValid()) {
27648 if (cond.Is(al)) {
27649 EmitA32(0xf2000850U | (encoded_dt.GetEncodingValue() << 20) |
27650 rd.Encode(22, 12) | rn.Encode(7, 16) | rm.Encode(5, 0));
27651 return;
27652 }
27653 }
27654 }
27655 Delegate(kVtst, &Assembler::vtst, cond, dt, rd, rn, rm);
27656}
27657
27658void Assembler::vuzp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027659 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027660 CheckIT(cond);
27661 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027662 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027663 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27664 if (encoded_dt.IsValid()) {
27665 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27666 EmitT32_32(0xffb20100U | (encoded_dt.GetEncodingValue() << 18) |
27667 rd.Encode(22, 12) | rm.Encode(5, 0));
27668 AdvanceIT();
27669 return;
27670 }
27671 }
27672 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27673 if (dt.Is(Untyped32)) {
27674 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27675 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27676 AdvanceIT();
27677 return;
27678 }
27679 }
27680 } else {
27681 // VUZP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27682 if (encoded_dt.IsValid()) {
27683 if (cond.Is(al)) {
27684 EmitA32(0xf3b20100U | (encoded_dt.GetEncodingValue() << 18) |
27685 rd.Encode(22, 12) | rm.Encode(5, 0));
27686 return;
27687 }
27688 }
27689 // VUZP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27690 if (dt.Is(Untyped32)) {
27691 if (cond.Is(al)) {
27692 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27693 return;
27694 }
27695 }
27696 }
27697 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27698}
27699
27700void Assembler::vuzp(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027701 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027702 CheckIT(cond);
27703 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027704 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027705 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27706 if (encoded_dt.IsValid()) {
27707 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27708 EmitT32_32(0xffb20140U | (encoded_dt.GetEncodingValue() << 18) |
27709 rd.Encode(22, 12) | rm.Encode(5, 0));
27710 AdvanceIT();
27711 return;
27712 }
27713 }
27714 } else {
27715 // VUZP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27716 if (encoded_dt.IsValid()) {
27717 if (cond.Is(al)) {
27718 EmitA32(0xf3b20140U | (encoded_dt.GetEncodingValue() << 18) |
27719 rd.Encode(22, 12) | rm.Encode(5, 0));
27720 return;
27721 }
27722 }
27723 }
27724 Delegate(kVuzp, &Assembler::vuzp, cond, dt, rd, rm);
27725}
27726
27727void Assembler::vzip(Condition cond, DataType dt, DRegister rd, DRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027728 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027729 CheckIT(cond);
27730 Dt_size_15 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027731 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027732 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; T1
27733 if (encoded_dt.IsValid()) {
27734 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27735 EmitT32_32(0xffb20180U | (encoded_dt.GetEncodingValue() << 18) |
27736 rd.Encode(22, 12) | rm.Encode(5, 0));
27737 AdvanceIT();
27738 return;
27739 }
27740 }
27741 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; T1
27742 if (dt.Is(Untyped32)) {
27743 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27744 EmitT32_32(0xffba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27745 AdvanceIT();
27746 return;
27747 }
27748 }
27749 } else {
27750 // VZIP{<c>}{<q>}.<dt> <Dd>, <Dm> ; A1
27751 if (encoded_dt.IsValid()) {
27752 if (cond.Is(al)) {
27753 EmitA32(0xf3b20180U | (encoded_dt.GetEncodingValue() << 18) |
27754 rd.Encode(22, 12) | rm.Encode(5, 0));
27755 return;
27756 }
27757 }
27758 // VZIP{<c>}{<q>}.32 <Dd>, <Dm> ; A1
27759 if (dt.Is(Untyped32)) {
27760 if (cond.Is(al)) {
27761 EmitA32(0xf3ba0080U | rd.Encode(22, 12) | rm.Encode(5, 0));
27762 return;
27763 }
27764 }
27765 }
27766 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27767}
27768
27769void Assembler::vzip(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027770 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027771 CheckIT(cond);
27772 Dt_size_7 encoded_dt(dt);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027773 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027774 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; T1
27775 if (encoded_dt.IsValid()) {
27776 if (cond.Is(al) || AllowStronglyDiscouraged()) {
27777 EmitT32_32(0xffb201c0U | (encoded_dt.GetEncodingValue() << 18) |
27778 rd.Encode(22, 12) | rm.Encode(5, 0));
27779 AdvanceIT();
27780 return;
27781 }
27782 }
27783 } else {
27784 // VZIP{<c>}{<q>}.<dt> <Qd>, <Qm> ; A1
27785 if (encoded_dt.IsValid()) {
27786 if (cond.Is(al)) {
27787 EmitA32(0xf3b201c0U | (encoded_dt.GetEncodingValue() << 18) |
27788 rd.Encode(22, 12) | rm.Encode(5, 0));
27789 return;
27790 }
27791 }
27792 }
27793 Delegate(kVzip, &Assembler::vzip, cond, dt, rd, rm);
27794}
27795
27796void Assembler::yield(Condition cond, EncodingSize size) {
Vincent Belliard8885c172016-08-24 11:33:19 -070027797 VIXL_ASSERT(AllowAssembler());
Alexandre Ramesd3832962016-07-04 15:03:43 +010027798 CheckIT(cond);
Jacob Bramley10dae1a2016-07-27 09:45:13 +010027799 if (IsUsingT32()) {
Alexandre Ramesd3832962016-07-04 15:03:43 +010027800 // YIELD{<c>}{<q>} ; T1
27801 if (!size.IsWide()) {
27802 EmitT32_16(0xbf10);
27803 AdvanceIT();
27804 return;
27805 }
27806 // YIELD{<c>}.W ; T2
27807 if (!size.IsNarrow()) {
27808 EmitT32_32(0xf3af8001U);
27809 AdvanceIT();
27810 return;
27811 }
27812 } else {
27813 // YIELD{<c>}{<q>} ; A1
27814 if (cond.IsNotNever()) {
27815 EmitA32(0x0320f001U | (cond.GetCondition() << 28));
27816 return;
27817 }
27818 }
27819 Delegate(kYield, &Assembler::yield, cond, size);
27820}
27821// End of generated code.
27822
27823} // namespace aarch32
27824} // namespace vixl