• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   if (list_ == 0) {
99     return Register();
100   }
101   return Register(CountTrailingZeros(list_));
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