1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright notice,
8 // this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above copyright notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
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 return "";
442 case Narrow:
443 return ".n";
444 case Wide:
445 return ".w";
446 }
447 VIXL_UNREACHABLE();
448 return "??";
449 }
450
451
GetName() const452 const char* DataType::GetName() const {
453 switch (value_) {
454 case kDataTypeValueInvalid:
455 return ".??";
456 case kDataTypeValueNone:
457 return "";
458 case S8:
459 return ".s8";
460 case S16:
461 return ".s16";
462 case S32:
463 return ".s32";
464 case S64:
465 return ".s64";
466 case U8:
467 return ".u8";
468 case U16:
469 return ".u16";
470 case U32:
471 return ".u32";
472 case U64:
473 return ".u64";
474 case F16:
475 return ".f16";
476 case F32:
477 return ".f32";
478 case F64:
479 return ".f64";
480 case I8:
481 return ".i8";
482 case I16:
483 return ".i16";
484 case I32:
485 return ".i32";
486 case I64:
487 return ".i64";
488 case P8:
489 return ".p8";
490 case P64:
491 return ".p64";
492 case Untyped8:
493 return ".8";
494 case Untyped16:
495 return ".16";
496 case Untyped32:
497 return ".32";
498 case Untyped64:
499 return ".64";
500 }
501 VIXL_UNREACHABLE();
502 return ".??";
503 }
504
505
GetName() const506 const char* MemoryBarrier::GetName() const {
507 switch (type_) {
508 case OSHLD:
509 return "oshld";
510 case OSHST:
511 return "oshst";
512 case OSH:
513 return "osh";
514 case NSHLD:
515 return "nshld";
516 case NSHST:
517 return "nshst";
518 case NSH:
519 return "nsh";
520 case ISHLD:
521 return "ishld";
522 case ISHST:
523 return "ishst";
524 case ISH:
525 return "ish";
526 case LD:
527 return "ld";
528 case ST:
529 return "st";
530 case SY:
531 return "sy";
532 }
533 switch (static_cast<int>(type_)) {
534 case 0:
535 return "#0x0";
536 case 4:
537 return "#0x4";
538 case 8:
539 return "#0x8";
540 case 0xc:
541 return "#0xc";
542 }
543 VIXL_UNREACHABLE();
544 return "??";
545 }
546
547
GetName() const548 const char* InterruptFlags::GetName() const {
549 switch (type_) {
550 case F:
551 return "f";
552 case I:
553 return "i";
554 case IF:
555 return "if";
556 case A:
557 return "a";
558 case AF:
559 return "af";
560 case AI:
561 return "ai";
562 case AIF:
563 return "aif";
564 }
565 VIXL_ASSERT(type_ == 0);
566 return "";
567 }
568
569
GetName() const570 const char* Endianness::GetName() const {
571 switch (type_) {
572 case LE:
573 return "le";
574 case BE:
575 return "be";
576 }
577 VIXL_UNREACHABLE();
578 return "??";
579 }
580
581
582 // Constructor used for disassembly.
ImmediateShiftOperand(int shift_value,int amount_value)583 ImmediateShiftOperand::ImmediateShiftOperand(int shift_value, int amount_value)
584 : Shift(shift_value) {
585 switch (shift_value) {
586 case LSL:
587 amount_ = amount_value;
588 break;
589 case LSR:
590 case ASR:
591 amount_ = (amount_value == 0) ? 32 : amount_value;
592 break;
593 case ROR:
594 amount_ = amount_value;
595 if (amount_value == 0) SetType(RRX);
596 break;
597 default:
598 VIXL_UNREACHABLE();
599 SetType(LSL);
600 amount_ = 0;
601 break;
602 }
603 }
604
605
ImmediateT32(uint32_t imm)606 ImmediateT32::ImmediateT32(uint32_t imm) {
607 // 00000000 00000000 00000000 abcdefgh
608 if ((imm & ~0xff) == 0) {
609 SetEncodingValue(imm);
610 return;
611 }
612 if ((imm >> 16) == (imm & 0xffff)) {
613 if ((imm & 0xff00) == 0) {
614 // 00000000 abcdefgh 00000000 abcdefgh
615 SetEncodingValue((imm & 0xff) | (0x1 << 8));
616 return;
617 }
618 if ((imm & 0xff) == 0) {
619 // abcdefgh 00000000 abcdefgh 00000000
620 SetEncodingValue(((imm >> 8) & 0xff) | (0x2 << 8));
621 return;
622 }
623 if (((imm >> 8) & 0xff) == (imm & 0xff)) {
624 // abcdefgh abcdefgh abcdefgh abcdefgh
625 SetEncodingValue((imm & 0xff) | (0x3 << 8));
626 return;
627 }
628 }
629 for (int shift = 0; shift < 24; shift++) {
630 uint32_t imm8 = imm >> (24 - shift);
631 uint32_t overflow = imm << (8 + shift);
632 if ((imm8 <= 0xff) && ((imm8 & 0x80) != 0) && (overflow == 0)) {
633 SetEncodingValue(((shift + 8) << 7) | (imm8 & 0x7F));
634 return;
635 }
636 }
637 }
638
639
ror(uint32_t x,int i)640 static inline uint32_t ror(uint32_t x, int i) {
641 VIXL_ASSERT((0 < i) && (i < 32));
642 return (x >> i) | (x << (32 - i));
643 }
644
645
IsImmediateT32(uint32_t imm)646 bool ImmediateT32::IsImmediateT32(uint32_t imm) {
647 /* abcdefgh abcdefgh abcdefgh abcdefgh */
648 if ((imm ^ ror(imm, 8)) == 0) return true;
649 /* 00000000 abcdefgh 00000000 abcdefgh */
650 /* abcdefgh 00000000 abcdefgh 00000000 */
651 if ((imm ^ ror(imm, 16)) == 0 &&
652 (((imm & 0xff00) == 0) || ((imm & 0xff) == 0)))
653 return true;
654 /* isolate least-significant set bit */
655 uint32_t lsb = imm & -imm;
656 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
657 * avoid overflow (underflow is always a successful case) */
658 return ((imm >> 8) < lsb);
659 }
660
661
Decode(uint32_t value)662 uint32_t ImmediateT32::Decode(uint32_t value) {
663 uint32_t base = value & 0xff;
664 switch (value >> 8) {
665 case 0:
666 return base;
667 case 1:
668 return base | (base << 16);
669 case 2:
670 return (base << 8) | (base << 24);
671 case 3:
672 return base | (base << 8) | (base << 16) | (base << 24);
673 default:
674 base |= 0x80;
675 return base << (32 - (value >> 7));
676 }
677 }
678
679
ImmediateA32(uint32_t imm)680 ImmediateA32::ImmediateA32(uint32_t imm) {
681 // Deal with rot = 0 first to avoid undefined shift by 32.
682 if (imm <= 0xff) {
683 SetEncodingValue(imm);
684 return;
685 }
686 for (int rot = 2; rot < 32; rot += 2) {
687 uint32_t imm8 = (imm << rot) | (imm >> (32 - rot));
688 if (imm8 <= 0xff) {
689 SetEncodingValue((rot << 7) | imm8);
690 return;
691 }
692 }
693 }
694
695
IsImmediateA32(uint32_t imm)696 bool ImmediateA32::IsImmediateA32(uint32_t imm) {
697 /* fast-out */
698 if (imm < 256) return true;
699 /* avoid getting confused by wrapped-around bytes (this transform has no
700 * effect on pass/fail results) */
701 if (imm & 0xff000000) imm = ror(imm, 16);
702 /* copy odd-numbered set bits into even-numbered bits immediately below, so
703 * that the least-significant set bit is always an even bit */
704 imm = imm | ((imm >> 1) & 0x55555555);
705 /* isolate least-significant set bit (always even) */
706 uint32_t lsb = imm & -imm;
707 /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
708 * avoid overflow (underflow is always a successful case) */
709 return ((imm >> 8) < lsb);
710 }
711
712
Decode(uint32_t value)713 uint32_t ImmediateA32::Decode(uint32_t value) {
714 int rotation = (value >> 8) * 2;
715 VIXL_ASSERT(rotation >= 0);
716 VIXL_ASSERT(rotation <= 30);
717 value &= 0xff;
718 if (rotation == 0) return value;
719 return (value >> rotation) | (value << (32 - rotation));
720 }
721
722
TypeEncodingValue(Shift shift)723 uint32_t TypeEncodingValue(Shift shift) {
724 return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue();
725 }
726
727
AmountEncodingValue(Shift shift,uint32_t amount)728 uint32_t AmountEncodingValue(Shift shift, uint32_t amount) {
729 switch (shift.GetType()) {
730 case LSL:
731 case ROR:
732 return amount;
733 case LSR:
734 case ASR:
735 return amount % 32;
736 case RRX:
737 return 0;
738 }
739 return 0;
740 }
741
742 } // namespace aarch32
743 } // namespace vixl
744