• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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