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
27extern "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
41namespace vixl {
42namespace aarch32 {
43
44
45bool 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
63std::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
79SRegister VRegister::S() const {
80  VIXL_ASSERT(GetType() == kSRegister);
81  return SRegister(GetCode());
82}
83
84
85DRegister VRegister::D() const {
86  VIXL_ASSERT(GetType() == kDRegister);
87  return DRegister(GetCode());
88}
89
90
91QRegister VRegister::Q() const {
92  VIXL_ASSERT(GetType() == kQRegister);
93  return QRegister(GetCode());
94}
95
96
97Register 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
105std::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
127std::ostream& operator<<(std::ostream& os, RegisterList registers) {
128  return PrintRegisterList(os, registers.GetList());
129}
130
131
132QRegister 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
140DRegister 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
148SRegister 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
156std::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
167std::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
177std::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
208const 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
220const 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
288const 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
361const 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
381const 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
420const 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
438const 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
451const 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
505const 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
547const 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
569const 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.
582ImmediateShiftOperand::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
605ImmediateT32::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
639static 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
645bool 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
661uint32_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
679ImmediateA32::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
695bool 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
712uint32_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
722uint32_t TypeEncodingValue(Shift shift) {
723  return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue();
724}
725
726
727uint32_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