instructions-aarch32.cc revision 3c1635a4387a8d19b33d558b75c376e6587c317e
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
27extern "C" {
28#include <stdint.h>
29}
30
31#include <cassert>
32#include <cstdio>
33#include <cstdlib>
34#include <cstring>
35#include <iostream>  // NOLINT
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, uint32_t list) {  // NOLINT
106  os << "{";
107  bool first = true;
108  int code = 0;
109  while (list != 0) {
110    if ((list & 1) != 0) {
111      if (first) {
112        first = false;
113      } else {
114        os << ",";
115      }
116      os << Register(code);
117    }
118    list >>= 1;
119    code++;
120  }
121  os << "}";
122  return os;
123}
124
125
126std::ostream& operator<<(std::ostream& os, RegisterList registers) {
127  return PrintRegisterList(os, registers.GetList());
128}
129
130
131QRegister VRegisterList::GetFirstAvailableQRegister() const {
132  for (uint32_t i = 0; i < kNumberOfQRegisters; i++) {
133    if (((list_ >> (i * 4)) & 0xf) == 0xf) return QRegister(i);
134  }
135  return QRegister();
136}
137
138
139DRegister VRegisterList::GetFirstAvailableDRegister() const {
140  for (uint32_t i = 0; i < kMaxNumberOfDRegisters; i++) {
141    if (((list_ >> (i * 2)) & 0x3) == 0x3) return DRegister(i);
142  }
143  return DRegister();
144}
145
146
147SRegister VRegisterList::GetFirstAvailableSRegister() const {
148  for (uint32_t i = 0; i < kNumberOfSRegisters; i++) {
149    if (((list_ >> i) & 0x1) != 0) return SRegister(i);
150  }
151  return SRegister();
152}
153
154
155std::ostream& operator<<(std::ostream& os, SRegisterList reglist) {
156  SRegister first = reglist.GetFirstSRegister();
157  SRegister last = reglist.GetLastSRegister();
158  if (first.Is(last))
159    os << "{" << first << "}";
160  else
161    os << "{" << first << "-" << last << "}";
162  return os;
163}
164
165
166std::ostream& operator<<(std::ostream& os, DRegisterList reglist) {
167  DRegister first = reglist.GetFirstDRegister();
168  DRegister last = reglist.GetLastDRegister();
169  if (first.Is(last))
170    os << "{" << first << "}";
171  else
172    os << "{" << first << "-" << last << "}";
173  return os;
174}
175
176std::ostream& operator<<(std::ostream& os, NeonRegisterList nreglist) {
177  DRegister first = nreglist.GetFirstDRegister();
178  int increment = nreglist.IsSingleSpaced() ? 1 : 2;
179  int count =
180      nreglist.GetLastDRegister().GetCode() - first.GetCode() + increment;
181  if (count < 0) count += kMaxNumberOfDRegisters;
182  os << "{";
183  bool first_displayed = false;
184  for (;;) {
185    if (first_displayed) {
186      os << ",";
187    } else {
188      first_displayed = true;
189    }
190    os << first;
191    if (nreglist.IsTransferOneLane()) {
192      os << "[" << nreglist.GetTransferLane() << "]";
193    } else if (nreglist.IsTransferAllLanes()) {
194      os << "[]";
195    }
196    count -= increment;
197    if (count <= 0) break;
198    unsigned next = first.GetCode() + increment;
199    if (next >= kMaxNumberOfDRegisters) next -= kMaxNumberOfDRegisters;
200    first = DRegister(next);
201  }
202  os << "}";
203  return os;
204}
205
206
207const char* SpecialRegister::GetName() const {
208  switch (reg_) {
209    case APSR:
210      return "APSR";
211    case SPSR:
212      return "SPSR";
213  }
214  VIXL_UNREACHABLE();
215  return "??";
216}
217
218
219const char* MaskedSpecialRegister::GetName() const {
220  switch (reg_) {
221    case APSR_nzcvq:
222      return "APSR_nzcvq";
223    case APSR_g:
224      return "APSR_g";
225    case APSR_nzcvqg:
226      return "APSR_nzcvqg";
227    case CPSR_c:
228      return "CPSR_c";
229    case CPSR_x:
230      return "CPSR_x";
231    case CPSR_xc:
232      return "CPSR_xc";
233    case CPSR_sc:
234      return "CPSR_sc";
235    case CPSR_sx:
236      return "CPSR_sx";
237    case CPSR_sxc:
238      return "CPSR_sxc";
239    case CPSR_fc:
240      return "CPSR_fc";
241    case CPSR_fx:
242      return "CPSR_fx";
243    case CPSR_fxc:
244      return "CPSR_fxc";
245    case CPSR_fsc:
246      return "CPSR_fsc";
247    case CPSR_fsx:
248      return "CPSR_fsx";
249    case CPSR_fsxc:
250      return "CPSR_fsxc";
251    case SPSR_c:
252      return "SPSR_c";
253    case SPSR_x:
254      return "SPSR_x";
255    case SPSR_xc:
256      return "SPSR_xc";
257    case SPSR_s:
258      return "SPSR_s";
259    case SPSR_sc:
260      return "SPSR_sc";
261    case SPSR_sx:
262      return "SPSR_sx";
263    case SPSR_sxc:
264      return "SPSR_sxc";
265    case SPSR_f:
266      return "SPSR_f";
267    case SPSR_fc:
268      return "SPSR_fc";
269    case SPSR_fx:
270      return "SPSR_fx";
271    case SPSR_fxc:
272      return "SPSR_fxc";
273    case SPSR_fs:
274      return "SPSR_fs";
275    case SPSR_fsc:
276      return "SPSR_fsc";
277    case SPSR_fsx:
278      return "SPSR_fsx";
279    case SPSR_fsxc:
280      return "SPSR_fsxc";
281  }
282  VIXL_UNREACHABLE();
283  return "??";
284}
285
286
287const char* BankedRegister::GetName() const {
288  switch (reg_) {
289    case R8_usr:
290      return "R8_usr";
291    case R9_usr:
292      return "R9_usr";
293    case R10_usr:
294      return "R10_usr";
295    case R11_usr:
296      return "R11_usr";
297    case R12_usr:
298      return "R12_usr";
299    case SP_usr:
300      return "SP_usr";
301    case LR_usr:
302      return "LR_usr";
303    case R8_fiq:
304      return "R8_fiq";
305    case R9_fiq:
306      return "R9_fiq";
307    case R10_fiq:
308      return "R10_fiq";
309    case R11_fiq:
310      return "R11_fiq";
311    case R12_fiq:
312      return "R12_fiq";
313    case SP_fiq:
314      return "SP_fiq";
315    case LR_fiq:
316      return "LR_fiq";
317    case LR_irq:
318      return "LR_irq";
319    case SP_irq:
320      return "SP_irq";
321    case LR_svc:
322      return "LR_svc";
323    case SP_svc:
324      return "SP_svc";
325    case LR_abt:
326      return "LR_abt";
327    case SP_abt:
328      return "SP_abt";
329    case LR_und:
330      return "LR_und";
331    case SP_und:
332      return "SP_und";
333    case LR_mon:
334      return "LR_mon";
335    case SP_mon:
336      return "SP_mon";
337    case ELR_hyp:
338      return "ELR_hyp";
339    case SP_hyp:
340      return "SP_hyp";
341    case SPSR_fiq:
342      return "SPSR_fiq";
343    case SPSR_irq:
344      return "SPSR_irq";
345    case SPSR_svc:
346      return "SPSR_svc";
347    case SPSR_abt:
348      return "SPSR_abt";
349    case SPSR_und:
350      return "SPSR_und";
351    case SPSR_mon:
352      return "SPSR_mon";
353    case SPSR_hyp:
354      return "SPSR_hyp";
355  }
356  VIXL_UNREACHABLE();
357  return "??";
358}
359
360const char* SpecialFPRegister::GetName() const {
361  switch (reg_) {
362    case FPSID:
363      return "FPSID";
364    case FPSCR:
365      return "FPSCR";
366    case MVFR2:
367      return "MVFR2";
368    case MVFR1:
369      return "MVFR1";
370    case MVFR0:
371      return "MVFR0";
372    case FPEXC:
373      return "FPEXC";
374  }
375  VIXL_UNREACHABLE();
376  return "??";
377}
378
379
380const char* Condition::GetName() const {
381  switch (condition_) {
382    case eq:
383      return "eq";
384    case ne:
385      return "ne";
386    case cs:
387      return "cs";
388    case cc:
389      return "cc";
390    case mi:
391      return "mi";
392    case pl:
393      return "pl";
394    case vs:
395      return "vs";
396    case vc:
397      return "vc";
398    case hi:
399      return "hi";
400    case ls:
401      return "ls";
402    case ge:
403      return "ge";
404    case lt:
405      return "lt";
406    case gt:
407      return "gt";
408    case le:
409      return "le";
410    case al:
411      return "";
412    case Condition::kNone:
413      return "";
414  }
415  return "<und>";
416}
417
418
419const char* Shift::GetName() const {
420  switch (shift_) {
421    case LSL:
422      return "lsl";
423    case LSR:
424      return "lsr";
425    case ASR:
426      return "asr";
427    case ROR:
428      return "ror";
429    case RRX:
430      return "rrx";
431  }
432  VIXL_UNREACHABLE();
433  return "??";
434}
435
436
437const char* EncodingSize::GetName() const {
438  switch (size_) {
439    case Best:
440      return "";
441    case Narrow:
442      return ".n";
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