1 // Copyright 2017, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 extern "C" {
28 #include <stdint.h>
29 }
30
31 #include <cassert>
32 #include <cstdio>
33 #include <cstdlib>
34 #include <cstring>
35 #include <iostream>
36
37 #include "utils-vixl.h"
38 #include "aarch32/constants-aarch32.h"
39 #include "aarch32/instructions-aarch32.h"
40
41 namespace vixl {
42 namespace aarch32 {
43
44
IsValidAmount(uint32_t amount) const45 bool Shift::IsValidAmount(uint32_t amount) const {
46 switch (GetType()) {
47 case LSL:
48 return amount <= 31;
49 case ROR:
50 return (amount > 0) && (amount <= 31);
51 case LSR:
52 case ASR:
53 return (amount > 0) && (amount <= 32);
54 case RRX:
55 return amount == 0;
56 default:
57 VIXL_UNREACHABLE();
58 return false;
59 }
60 }
61
62
operator <<(std::ostream & os,const Register reg)63 std::ostream& operator<<(std::ostream& os, const Register reg) {
64 switch (reg.GetCode()) {
65 case 12:
66 return os << "ip";
67 case 13:
68 return os << "sp";
69 case 14:
70 return os << "lr";
71 case 15:
72 return os << "pc";
73 default:
74 return os << "r" << reg.GetCode();
75 }
76 }
77
78
S() const79 SRegister VRegister::S() const {
80 VIXL_ASSERT(GetType() == kSRegister);
81 return SRegister(GetCode());
82 }
83
84
D() const85 DRegister VRegister::D() const {
86 VIXL_ASSERT(GetType() == kDRegister);
87 return DRegister(GetCode());
88 }
89
90
Q() const91 QRegister VRegister::Q() const {
92 VIXL_ASSERT(GetType() == kQRegister);
93 return QRegister(GetCode());
94 }
95
96
GetFirstAvailableRegister() const97 Register RegisterList::GetFirstAvailableRegister() const {
98 for (uint32_t i = 0; i < kNumberOfRegisters; i++) {
99 if (((list_ >> i) & 1) != 0) return Register(i);
100 }
101 return Register();
102 }
103
104
PrintRegisterList(std::ostream & os,uint32_t list)105 std::ostream& PrintRegisterList(std::ostream& os, // NOLINT(runtime/references)
106 uint32_t list) {
107 os << "{";
108 bool first = true;
109 int code = 0;
110 while (list != 0) {
111 if ((list & 1) != 0) {
112 if (first) {
113 first = false;
114 } else {
115 os << ",";
116 }
117 os << Register(code);
118 }
119 list >>= 1;
120 code++;
121 }
122 os << "}";
123 return os;
124 }
125
126
operator <<(std::ostream & os,RegisterList registers)127 std::ostream& operator<<(std::ostream& os, RegisterList registers) {
128 return PrintRegisterList(os, registers.GetList());
129 }
130
131
GetFirstAvailableQRegister() const132 QRegister VRegisterList::GetFirstAvailableQRegister() const {
133 for (uint32_t i = 0; i < kNumberOfQRegisters; i++) {
134 if (((list_ >> (i * 4)) & 0xf) == 0xf) return QRegister(i);
135 }
136 return QRegister();
137 }
138
139
GetFirstAvailableDRegister() const140 DRegister VRegisterList::GetFirstAvailableDRegister() const {
141 for (uint32_t i = 0; i < kMaxNumberOfDRegisters; i++) {
142 if (((list_ >> (i * 2)) & 0x3) == 0x3) return DRegister(i);
143 }
144 return DRegister();
145 }
146
147
GetFirstAvailableSRegister() const148 SRegister VRegisterList::GetFirstAvailableSRegister() const {
149 for (uint32_t i = 0; i < kNumberOfSRegisters; i++) {
150 if (((list_ >> i) & 0x1) != 0) return SRegister(i);
151 }
152 return SRegister();
153 }
154
155
operator <<(std::ostream & os,SRegisterList reglist)156 std::ostream& operator<<(std::ostream& os, SRegisterList reglist) {
157 SRegister first = reglist.GetFirstSRegister();
158 SRegister last = reglist.GetLastSRegister();
159 if (first.Is(last))
160 os << "{" << first << "}";
161 else
162 os << "{" << first << "-" << last << "}";
163 return os;
164 }
165
166
operator <<(std::ostream & os,DRegisterList reglist)167 std::ostream& operator<<(std::ostream& os, DRegisterList reglist) {
168 DRegister first = reglist.GetFirstDRegister();
169 DRegister last = reglist.GetLastDRegister();
170 if (first.Is(last))
171 os << "{" << first << "}";
172 else
173 os << "{" << first << "-" << last << "}";
174 return os;
175 }
176
operator <<(std::ostream & os,NeonRegisterList nreglist)177 std::ostream& operator<<(std::ostream& os, NeonRegisterList nreglist) {
178 DRegister first = nreglist.GetFirstDRegister();
179 int increment = nreglist.IsSingleSpaced() ? 1 : 2;
180 int count =
181 nreglist.GetLastDRegister().GetCode() - first.GetCode() + increment;
182 if (count < 0) count += kMaxNumberOfDRegisters;
183 os << "{";
184 bool first_displayed = false;
185 for (;;) {
186 if (first_displayed) {
187 os << ",";
188 } else {
189 first_displayed = true;
190 }
191 os << first;
192 if (nreglist.IsTransferOneLane()) {
193 os << "[" << nreglist.GetTransferLane() << "]";
194 } else if (nreglist.IsTransferAllLanes()) {
195 os << "[]";
196 }
197 count -= increment;
198 if (count <= 0) break;
199 unsigned next = first.GetCode() + increment;
200 if (next >= kMaxNumberOfDRegisters) next -= kMaxNumberOfDRegisters;
201 first = DRegister(next);
202 }
203 os << "}";
204 return os;
205 }
206
207
GetName() const208 const char* SpecialRegister::GetName() const {
209 switch (reg_) {
210 case APSR:
211 return "APSR";
212 case SPSR:
213 return "SPSR";
214 }
215 VIXL_UNREACHABLE();
216 return "??";
217 }
218
219
GetName() const220 const char* MaskedSpecialRegister::GetName() const {
221 switch (reg_) {
222 case APSR_nzcvq:
223 return "APSR_nzcvq";
224 case APSR_g:
225 return "APSR_g";
226 case APSR_nzcvqg:
227 return "APSR_nzcvqg";
228 case CPSR_c:
229 return "CPSR_c";
230 case CPSR_x:
231 return "CPSR_x";
232 case CPSR_xc:
233 return "CPSR_xc";
234 case CPSR_sc:
235 return "CPSR_sc";
236 case CPSR_sx:
237 return "CPSR_sx";
238 case CPSR_sxc:
239 return "CPSR_sxc";
240 case CPSR_fc:
241 return "CPSR_fc";
242 case CPSR_fx:
243 return "CPSR_fx";
244 case CPSR_fxc:
245 return "CPSR_fxc";
246 case CPSR_fsc:
247 return "CPSR_fsc";
248 case CPSR_fsx:
249 return "CPSR_fsx";
250 case CPSR_fsxc:
251 return "CPSR_fsxc";
252 case SPSR_c:
253 return "SPSR_c";
254 case SPSR_x:
255 return "SPSR_x";
256 case SPSR_xc:
257 return "SPSR_xc";
258 case SPSR_s:
259 return "SPSR_s";
260 case SPSR_sc:
261 return "SPSR_sc";
262 case SPSR_sx:
263 return "SPSR_sx";
264 case SPSR_sxc:
265 return "SPSR_sxc";
266 case SPSR_f:
267 return "SPSR_f";
268 case SPSR_fc:
269 return "SPSR_fc";
270 case SPSR_fx:
271 return "SPSR_fx";
272 case SPSR_fxc:
273 return "SPSR_fxc";
274 case SPSR_fs:
275 return "SPSR_fs";
276 case SPSR_fsc:
277 return "SPSR_fsc";
278 case SPSR_fsx:
279 return "SPSR_fsx";
280 case SPSR_fsxc:
281 return "SPSR_fsxc";
282 }
283 VIXL_UNREACHABLE();
284 return "??";
285 }
286
287
GetName() const288 const char* BankedRegister::GetName() const {
289 switch (reg_) {
290 case R8_usr:
291 return "R8_usr";
292 case R9_usr:
293 return "R9_usr";
294 case R10_usr:
295 return "R10_usr";
296 case R11_usr:
297 return "R11_usr";
298 case R12_usr:
299 return "R12_usr";
300 case SP_usr:
301 return "SP_usr";
302 case LR_usr:
303 return "LR_usr";
304 case R8_fiq:
305 return "R8_fiq";
306 case R9_fiq:
307 return "R9_fiq";
308 case R10_fiq:
309 return "R10_fiq";
310 case R11_fiq:
311 return "R11_fiq";
312 case R12_fiq:
313 return "R12_fiq";
314 case SP_fiq:
315 return "SP_fiq";
316 case LR_fiq:
317 return "LR_fiq";
318 case LR_irq:
319 return "LR_irq";
320 case SP_irq:
321 return "SP_irq";
322 case LR_svc:
323 return "LR_svc";
324 case SP_svc:
325 return "SP_svc";
326 case LR_abt:
327 return "LR_abt";
328 case SP_abt:
329 return "SP_abt";
330 case LR_und:
331 return "LR_und";
332 case SP_und:
333 return "SP_und";
334 case LR_mon:
335 return "LR_mon";
336 case SP_mon:
337 return "SP_mon";
338 case ELR_hyp:
339 return "ELR_hyp";
340 case SP_hyp:
341 return "SP_hyp";
342 case SPSR_fiq:
343 return "SPSR_fiq";
344 case SPSR_irq:
345 return "SPSR_irq";
346 case SPSR_svc:
347 return "SPSR_svc";
348 case SPSR_abt:
349 return "SPSR_abt";
350 case SPSR_und:
351 return "SPSR_und";
352 case SPSR_mon:
353 return "SPSR_mon";
354 case SPSR_hyp:
355 return "SPSR_hyp";
356 }
357 VIXL_UNREACHABLE();
358 return "??";
359 }
360
GetName() const361 const char* SpecialFPRegister::GetName() const {
362 switch (reg_) {
363 case FPSID:
364 return "FPSID";
365 case FPSCR:
366 return "FPSCR";
367 case MVFR2:
368 return "MVFR2";
369 case MVFR1:
370 return "MVFR1";
371 case MVFR0:
372 return "MVFR0";
373 case FPEXC:
374 return "FPEXC";
375 }
376 VIXL_UNREACHABLE();
377 return "??";
378 }
379
380
GetName() const381 const char* Condition::GetName() const {
382 switch (condition_) {
383 case eq:
384 return "eq";
385 case ne:
386 return "ne";
387 case cs:
388 return "cs";
389 case cc:
390 return "cc";
391 case mi:
392 return "mi";
393 case pl:
394 return "pl";
395 case vs:
396 return "vs";
397 case vc:
398 return "vc";
399 case hi:
400 return "hi";
401 case ls:
402 return "ls";
403 case ge:
404 return "ge";
405 case lt:
406 return "lt";
407 case gt:
408 return "gt";
409 case le:
410 return "le";
411 case al:
412 return "";
413 case Condition::kNone:
414 return "";
415 }
416 return "<und>";
417 }
418
419
GetName() const420 const char* Shift::GetName() const {
421 switch (shift_) {
422 case LSL:
423 return "lsl";
424 case LSR:
425 return "lsr";
426 case ASR:
427 return "asr";
428 case ROR:
429 return "ror";
430 case RRX:
431 return "rrx";
432 }
433 VIXL_UNREACHABLE();
434 return "??";
435 }
436
437
GetName() const438 const char* EncodingSize::GetName() const {
439 switch (size_) {
440 case Best:
441 case Narrow:
442 return "";
443 case Wide:
444 return ".w";
445 }
446 VIXL_UNREACHABLE();
447 return "??";
448 }
449
450
GetName() const451 const char* DataType::GetName() const {
452 switch (value_) {
453 case kDataTypeValueInvalid:
454 return ".??";
455 case kDataTypeValueNone:
456 return "";
457 case S8:
458 return ".s8";
459 case S16:
460 return ".s16";
461 case S32:
462 return ".s32";
463 case S64:
464 return ".s64";
465 case U8:
466 return ".u8";
467 case U16:
468 return ".u16";
469 case U32:
470 return ".u32";
471 case U64:
472 return ".u64";
473 case F16:
474 return ".f16";
475 case F32:
476 return ".f32";
477 case F64:
478 return ".f64";
479 case I8:
480 return ".i8";
481 case I16:
482 return ".i16";
483 case I32:
484 return ".i32";
485 case I64:
486 return ".i64";
487 case P8:
488 return ".p8";
489 case P64:
490 return ".p64";
491 case Untyped8:
492 return ".8";
493 case Untyped16:
494 return ".16";
495 case Untyped32:
496 return ".32";
497 case Untyped64:
498 return ".64";
499 }
500 VIXL_UNREACHABLE();
501 return ".??";
502 }
503
504
GetName() const505 const char* MemoryBarrier::GetName() const {
506 switch (type_) {
507 case OSHLD:
508 return "oshld";
509 case OSHST:
510 return "oshst";
511 case OSH:
512 return "osh";
513 case NSHLD:
514 return "nshld";
515 case NSHST:
516 return "nshst";
517 case NSH:
518 return "nsh";
519 case ISHLD:
520 return "ishld";
521 case ISHST:
522 return "ishst";
523 case ISH:
524 return "ish";
525 case LD:
526 return "ld";
527 case ST:
528 return "st";
529 case SY:
530 return "sy";
531 }
532 switch (static_cast<int>(type_)) {
533 case 0:
534 return "#0x0";
535 case 4:
536 return "#0x4";
537 case 8:
538 return "#0x8";
539 case 0xc:
540 return "#0xc";
541 }
542 VIXL_UNREACHABLE();
543 return "??";
544 }
545
546
GetName() const547 const char* InterruptFlags::GetName() const {
548 switch (type_) {
549 case F:
550 return "f";
551 case I:
552 return "i";
553 case IF:
554 return "if";
555 case A:
556 return "a";
557 case AF:
558 return "af";
559 case AI:
560 return "ai";
561 case AIF:
562 return "aif";
563 }
564 VIXL_ASSERT(type_ == 0);
565 return "";
566 }
567
568
GetName() const569 const char* Endianness::GetName() const {
570 switch (type_) {
571 case LE:
572 return "le";
573 case BE:
574 return "be";
575 }
576 VIXL_UNREACHABLE();
577 return "??";
578 }
579
580
581 // Constructor used for disassembly.
ImmediateShiftOperand(int shift_value,int amount_value)582 ImmediateShiftOperand::ImmediateShiftOperand(int shift_value, int amount_value)
583 : Shift(shift_value) {
584 switch (shift_value) {
585 case LSL:
586 amount_ = amount_value;
587 break;
588 case LSR:
589 case ASR:
590 amount_ = (amount_value == 0) ? 32 : amount_value;
591 break;
592 case ROR:
593 amount_ = amount_value;
594 if (amount_value == 0) SetType(RRX);
595 break;
596 default:
597 VIXL_UNREACHABLE();
598 SetType(LSL);
599 amount_ = 0;
600 break;
601 }
602 }
603
604
ImmediateT32(uint32_t imm)605 ImmediateT32::ImmediateT32(uint32_t imm) {
606 // 00000000 00000000 00000000 abcdefgh
607 if ((imm & ~0xff) == 0) {
608 SetEncodingValue(imm);
609 return;
610 }
611 if ((imm >> 16) == (imm & 0xffff)) {
612 if ((imm & 0xff00) == 0) {
613 // 00000000 abcdefgh 00000000 abcdefgh
614 SetEncodingValue((imm & 0xff) | (0x1 << 8));
615 return;
616 }
617 if ((imm & 0xff) == 0) {
618 // abcdefgh 00000000 abcdefgh 00000000
619 SetEncodingValue(((imm >> 8) & 0xff) | (0x2 << 8));
620 return;
621 }
622 if (((imm >> 8) & 0xff) == (imm & 0xff)) {
623 // abcdefgh abcdefgh abcdefgh abcdefgh
624 SetEncodingValue((imm & 0xff) | (0x3 << 8));
625 return;
626 }
627 }
628 for (int shift = 0; shift < 24; shift++) {
629 uint32_t imm8 = imm >> (24 - shift);
630 uint32_t overflow = imm << (8 + shift);
631 if ((imm8 <= 0xff) && ((imm8 & 0x80) != 0) && (overflow == 0)) {
632 SetEncodingValue(((shift + 8) << 7) | (imm8 & 0x7F));
633 return;
634 }
635 }
636 }
637
638
ror(uint32_t x,int i)639 static inline uint32_t ror(uint32_t x, int i) {
640 VIXL_ASSERT((0 < i) && (i < 32));
641 return (x >> i) | (x << (32 - i));
642 }
643
644
IsImmediateT32(uint32_t imm)645 bool ImmediateT32::IsImmediateT32(uint32_t imm) {
646 /* abcdefgh abcdefgh abcdefgh abcdefgh */
647 if ((imm ^ ror(imm, 8)) == 0) return true;
648 /* 00000000 abcdefgh 00000000 abcdefgh */
649 /* abcdefgh 00000000 abcdefgh 00000000 */
650 if ((imm ^ ror(imm, 16)) == 0 &&
651 (((imm & 0xff00) == 0) || ((imm & 0xff) == 0)))
652 return true;
653 /* isolate least-significant set bit */
654 uint32_t lsb = imm & -imm;
655 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
656 * avoid overflow (underflow is always a successful case) */
657 return ((imm >> 8) < lsb);
658 }
659
660
Decode(uint32_t value)661 uint32_t ImmediateT32::Decode(uint32_t value) {
662 uint32_t base = value & 0xff;
663 switch (value >> 8) {
664 case 0:
665 return base;
666 case 1:
667 return base | (base << 16);
668 case 2:
669 return (base << 8) | (base << 24);
670 case 3:
671 return base | (base << 8) | (base << 16) | (base << 24);
672 default:
673 base |= 0x80;
674 return base << (32 - (value >> 7));
675 }
676 }
677
678
ImmediateA32(uint32_t imm)679 ImmediateA32::ImmediateA32(uint32_t imm) {
680 // Deal with rot = 0 first to avoid undefined shift by 32.
681 if (imm <= 0xff) {
682 SetEncodingValue(imm);
683 return;
684 }
685 for (int rot = 2; rot < 32; rot += 2) {
686 uint32_t imm8 = (imm << rot) | (imm >> (32 - rot));
687 if (imm8 <= 0xff) {
688 SetEncodingValue((rot << 7) | imm8);
689 return;
690 }
691 }
692 }
693
694
IsImmediateA32(uint32_t imm)695 bool ImmediateA32::IsImmediateA32(uint32_t imm) {
696 /* fast-out */
697 if (imm < 256) return true;
698 /* avoid getting confused by wrapped-around bytes (this transform has no
699 * effect on pass/fail results) */
700 if (imm & 0xff000000) imm = ror(imm, 16);
701 /* copy odd-numbered set bits into even-numbered bits immediately below, so
702 * that the least-significant set bit is always an even bit */
703 imm = imm | ((imm >> 1) & 0x55555555);
704 /* isolate least-significant set bit (always even) */
705 uint32_t lsb = imm & -imm;
706 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
707 * avoid overflow (underflow is always a successful case) */
708 return ((imm >> 8) < lsb);
709 }
710
711
Decode(uint32_t value)712 uint32_t ImmediateA32::Decode(uint32_t value) {
713 int rotation = (value >> 8) * 2;
714 VIXL_ASSERT(rotation >= 0);
715 VIXL_ASSERT(rotation <= 30);
716 value &= 0xff;
717 if (rotation == 0) return value;
718 return (value >> rotation) | (value << (32 - rotation));
719 }
720
721
TypeEncodingValue(Shift shift)722 uint32_t TypeEncodingValue(Shift shift) {
723 return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue();
724 }
725
726
AmountEncodingValue(Shift shift,uint32_t amount)727 uint32_t AmountEncodingValue(Shift shift, uint32_t amount) {
728 switch (shift.GetType()) {
729 case LSL:
730 case ROR:
731 return amount;
732 case LSR:
733 case ASR:
734 return amount % 32;
735 case RRX:
736 return 0;
737 }
738 return 0;
739 }
740
741 } // namespace aarch32
742 } // namespace vixl
743