xref: /aosp_15_r20/external/vixl/src/aarch32/instructions-aarch32.cc (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1*f5c631daSSadaf Ebrahimi // Copyright 2017, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi //   * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi //   * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi //     and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi //   * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi //     used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi //     specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi 
27*f5c631daSSadaf Ebrahimi extern "C" {
28*f5c631daSSadaf Ebrahimi #include <stdint.h>
29*f5c631daSSadaf Ebrahimi }
30*f5c631daSSadaf Ebrahimi 
31*f5c631daSSadaf Ebrahimi #include <cassert>
32*f5c631daSSadaf Ebrahimi #include <cstdio>
33*f5c631daSSadaf Ebrahimi #include <cstdlib>
34*f5c631daSSadaf Ebrahimi #include <cstring>
35*f5c631daSSadaf Ebrahimi #include <iostream>
36*f5c631daSSadaf Ebrahimi 
37*f5c631daSSadaf Ebrahimi #include "utils-vixl.h"
38*f5c631daSSadaf Ebrahimi #include "aarch32/constants-aarch32.h"
39*f5c631daSSadaf Ebrahimi #include "aarch32/instructions-aarch32.h"
40*f5c631daSSadaf Ebrahimi 
41*f5c631daSSadaf Ebrahimi namespace vixl {
42*f5c631daSSadaf Ebrahimi namespace aarch32 {
43*f5c631daSSadaf Ebrahimi 
44*f5c631daSSadaf Ebrahimi 
IsValidAmount(uint32_t amount) const45*f5c631daSSadaf Ebrahimi bool Shift::IsValidAmount(uint32_t amount) const {
46*f5c631daSSadaf Ebrahimi   switch (GetType()) {
47*f5c631daSSadaf Ebrahimi     case LSL:
48*f5c631daSSadaf Ebrahimi       return amount <= 31;
49*f5c631daSSadaf Ebrahimi     case ROR:
50*f5c631daSSadaf Ebrahimi       return (amount > 0) && (amount <= 31);
51*f5c631daSSadaf Ebrahimi     case LSR:
52*f5c631daSSadaf Ebrahimi     case ASR:
53*f5c631daSSadaf Ebrahimi       return (amount > 0) && (amount <= 32);
54*f5c631daSSadaf Ebrahimi     case RRX:
55*f5c631daSSadaf Ebrahimi       return amount == 0;
56*f5c631daSSadaf Ebrahimi     default:
57*f5c631daSSadaf Ebrahimi       VIXL_UNREACHABLE();
58*f5c631daSSadaf Ebrahimi       return false;
59*f5c631daSSadaf Ebrahimi   }
60*f5c631daSSadaf Ebrahimi }
61*f5c631daSSadaf Ebrahimi 
62*f5c631daSSadaf Ebrahimi 
operator <<(std::ostream & os,const Register reg)63*f5c631daSSadaf Ebrahimi std::ostream& operator<<(std::ostream& os, const Register reg) {
64*f5c631daSSadaf Ebrahimi   switch (reg.GetCode()) {
65*f5c631daSSadaf Ebrahimi     case 12:
66*f5c631daSSadaf Ebrahimi       return os << "ip";
67*f5c631daSSadaf Ebrahimi     case 13:
68*f5c631daSSadaf Ebrahimi       return os << "sp";
69*f5c631daSSadaf Ebrahimi     case 14:
70*f5c631daSSadaf Ebrahimi       return os << "lr";
71*f5c631daSSadaf Ebrahimi     case 15:
72*f5c631daSSadaf Ebrahimi       return os << "pc";
73*f5c631daSSadaf Ebrahimi     default:
74*f5c631daSSadaf Ebrahimi       return os << "r" << reg.GetCode();
75*f5c631daSSadaf Ebrahimi   }
76*f5c631daSSadaf Ebrahimi }
77*f5c631daSSadaf Ebrahimi 
78*f5c631daSSadaf Ebrahimi 
S() const79*f5c631daSSadaf Ebrahimi SRegister VRegister::S() const {
80*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(GetType() == kSRegister);
81*f5c631daSSadaf Ebrahimi   return SRegister(GetCode());
82*f5c631daSSadaf Ebrahimi }
83*f5c631daSSadaf Ebrahimi 
84*f5c631daSSadaf Ebrahimi 
D() const85*f5c631daSSadaf Ebrahimi DRegister VRegister::D() const {
86*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(GetType() == kDRegister);
87*f5c631daSSadaf Ebrahimi   return DRegister(GetCode());
88*f5c631daSSadaf Ebrahimi }
89*f5c631daSSadaf Ebrahimi 
90*f5c631daSSadaf Ebrahimi 
Q() const91*f5c631daSSadaf Ebrahimi QRegister VRegister::Q() const {
92*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(GetType() == kQRegister);
93*f5c631daSSadaf Ebrahimi   return QRegister(GetCode());
94*f5c631daSSadaf Ebrahimi }
95*f5c631daSSadaf Ebrahimi 
96*f5c631daSSadaf Ebrahimi 
GetFirstAvailableRegister() const97*f5c631daSSadaf Ebrahimi Register RegisterList::GetFirstAvailableRegister() const {
98*f5c631daSSadaf Ebrahimi   if (list_ == 0) {
99*f5c631daSSadaf Ebrahimi     return Register();
100*f5c631daSSadaf Ebrahimi   }
101*f5c631daSSadaf Ebrahimi   return Register(CountTrailingZeros(list_));
102*f5c631daSSadaf Ebrahimi }
103*f5c631daSSadaf Ebrahimi 
104*f5c631daSSadaf Ebrahimi 
PrintRegisterList(std::ostream & os,uint32_t list)105*f5c631daSSadaf Ebrahimi std::ostream& PrintRegisterList(std::ostream& os,  // NOLINT(runtime/references)
106*f5c631daSSadaf Ebrahimi                                 uint32_t list) {
107*f5c631daSSadaf Ebrahimi   os << "{";
108*f5c631daSSadaf Ebrahimi   bool first = true;
109*f5c631daSSadaf Ebrahimi   int code = 0;
110*f5c631daSSadaf Ebrahimi   while (list != 0) {
111*f5c631daSSadaf Ebrahimi     if ((list & 1) != 0) {
112*f5c631daSSadaf Ebrahimi       if (first) {
113*f5c631daSSadaf Ebrahimi         first = false;
114*f5c631daSSadaf Ebrahimi       } else {
115*f5c631daSSadaf Ebrahimi         os << ",";
116*f5c631daSSadaf Ebrahimi       }
117*f5c631daSSadaf Ebrahimi       os << Register(code);
118*f5c631daSSadaf Ebrahimi     }
119*f5c631daSSadaf Ebrahimi     list >>= 1;
120*f5c631daSSadaf Ebrahimi     code++;
121*f5c631daSSadaf Ebrahimi   }
122*f5c631daSSadaf Ebrahimi   os << "}";
123*f5c631daSSadaf Ebrahimi   return os;
124*f5c631daSSadaf Ebrahimi }
125*f5c631daSSadaf Ebrahimi 
126*f5c631daSSadaf Ebrahimi 
operator <<(std::ostream & os,RegisterList registers)127*f5c631daSSadaf Ebrahimi std::ostream& operator<<(std::ostream& os, RegisterList registers) {
128*f5c631daSSadaf Ebrahimi   return PrintRegisterList(os, registers.GetList());
129*f5c631daSSadaf Ebrahimi }
130*f5c631daSSadaf Ebrahimi 
131*f5c631daSSadaf Ebrahimi 
GetFirstAvailableQRegister() const132*f5c631daSSadaf Ebrahimi QRegister VRegisterList::GetFirstAvailableQRegister() const {
133*f5c631daSSadaf Ebrahimi   for (uint32_t i = 0; i < kNumberOfQRegisters; i++) {
134*f5c631daSSadaf Ebrahimi     if (((list_ >> (i * 4)) & 0xf) == 0xf) return QRegister(i);
135*f5c631daSSadaf Ebrahimi   }
136*f5c631daSSadaf Ebrahimi   return QRegister();
137*f5c631daSSadaf Ebrahimi }
138*f5c631daSSadaf Ebrahimi 
139*f5c631daSSadaf Ebrahimi 
GetFirstAvailableDRegister() const140*f5c631daSSadaf Ebrahimi DRegister VRegisterList::GetFirstAvailableDRegister() const {
141*f5c631daSSadaf Ebrahimi   for (uint32_t i = 0; i < kMaxNumberOfDRegisters; i++) {
142*f5c631daSSadaf Ebrahimi     if (((list_ >> (i * 2)) & 0x3) == 0x3) return DRegister(i);
143*f5c631daSSadaf Ebrahimi   }
144*f5c631daSSadaf Ebrahimi   return DRegister();
145*f5c631daSSadaf Ebrahimi }
146*f5c631daSSadaf Ebrahimi 
147*f5c631daSSadaf Ebrahimi 
GetFirstAvailableSRegister() const148*f5c631daSSadaf Ebrahimi SRegister VRegisterList::GetFirstAvailableSRegister() const {
149*f5c631daSSadaf Ebrahimi   for (uint32_t i = 0; i < kNumberOfSRegisters; i++) {
150*f5c631daSSadaf Ebrahimi     if (((list_ >> i) & 0x1) != 0) return SRegister(i);
151*f5c631daSSadaf Ebrahimi   }
152*f5c631daSSadaf Ebrahimi   return SRegister();
153*f5c631daSSadaf Ebrahimi }
154*f5c631daSSadaf Ebrahimi 
155*f5c631daSSadaf Ebrahimi 
operator <<(std::ostream & os,SRegisterList reglist)156*f5c631daSSadaf Ebrahimi std::ostream& operator<<(std::ostream& os, SRegisterList reglist) {
157*f5c631daSSadaf Ebrahimi   SRegister first = reglist.GetFirstSRegister();
158*f5c631daSSadaf Ebrahimi   SRegister last = reglist.GetLastSRegister();
159*f5c631daSSadaf Ebrahimi   if (first.Is(last))
160*f5c631daSSadaf Ebrahimi     os << "{" << first << "}";
161*f5c631daSSadaf Ebrahimi   else
162*f5c631daSSadaf Ebrahimi     os << "{" << first << "-" << last << "}";
163*f5c631daSSadaf Ebrahimi   return os;
164*f5c631daSSadaf Ebrahimi }
165*f5c631daSSadaf Ebrahimi 
166*f5c631daSSadaf Ebrahimi 
operator <<(std::ostream & os,DRegisterList reglist)167*f5c631daSSadaf Ebrahimi std::ostream& operator<<(std::ostream& os, DRegisterList reglist) {
168*f5c631daSSadaf Ebrahimi   DRegister first = reglist.GetFirstDRegister();
169*f5c631daSSadaf Ebrahimi   DRegister last = reglist.GetLastDRegister();
170*f5c631daSSadaf Ebrahimi   if (first.Is(last))
171*f5c631daSSadaf Ebrahimi     os << "{" << first << "}";
172*f5c631daSSadaf Ebrahimi   else
173*f5c631daSSadaf Ebrahimi     os << "{" << first << "-" << last << "}";
174*f5c631daSSadaf Ebrahimi   return os;
175*f5c631daSSadaf Ebrahimi }
176*f5c631daSSadaf Ebrahimi 
operator <<(std::ostream & os,NeonRegisterList nreglist)177*f5c631daSSadaf Ebrahimi std::ostream& operator<<(std::ostream& os, NeonRegisterList nreglist) {
178*f5c631daSSadaf Ebrahimi   DRegister first = nreglist.GetFirstDRegister();
179*f5c631daSSadaf Ebrahimi   int increment = nreglist.IsSingleSpaced() ? 1 : 2;
180*f5c631daSSadaf Ebrahimi   int count =
181*f5c631daSSadaf Ebrahimi       nreglist.GetLastDRegister().GetCode() - first.GetCode() + increment;
182*f5c631daSSadaf Ebrahimi   if (count < 0) count += kMaxNumberOfDRegisters;
183*f5c631daSSadaf Ebrahimi   os << "{";
184*f5c631daSSadaf Ebrahimi   bool first_displayed = false;
185*f5c631daSSadaf Ebrahimi   for (;;) {
186*f5c631daSSadaf Ebrahimi     if (first_displayed) {
187*f5c631daSSadaf Ebrahimi       os << ",";
188*f5c631daSSadaf Ebrahimi     } else {
189*f5c631daSSadaf Ebrahimi       first_displayed = true;
190*f5c631daSSadaf Ebrahimi     }
191*f5c631daSSadaf Ebrahimi     os << first;
192*f5c631daSSadaf Ebrahimi     if (nreglist.IsTransferOneLane()) {
193*f5c631daSSadaf Ebrahimi       os << "[" << nreglist.GetTransferLane() << "]";
194*f5c631daSSadaf Ebrahimi     } else if (nreglist.IsTransferAllLanes()) {
195*f5c631daSSadaf Ebrahimi       os << "[]";
196*f5c631daSSadaf Ebrahimi     }
197*f5c631daSSadaf Ebrahimi     count -= increment;
198*f5c631daSSadaf Ebrahimi     if (count <= 0) break;
199*f5c631daSSadaf Ebrahimi     unsigned next = first.GetCode() + increment;
200*f5c631daSSadaf Ebrahimi     if (next >= kMaxNumberOfDRegisters) next -= kMaxNumberOfDRegisters;
201*f5c631daSSadaf Ebrahimi     first = DRegister(next);
202*f5c631daSSadaf Ebrahimi   }
203*f5c631daSSadaf Ebrahimi   os << "}";
204*f5c631daSSadaf Ebrahimi   return os;
205*f5c631daSSadaf Ebrahimi }
206*f5c631daSSadaf Ebrahimi 
207*f5c631daSSadaf Ebrahimi 
GetName() const208*f5c631daSSadaf Ebrahimi const char* SpecialRegister::GetName() const {
209*f5c631daSSadaf Ebrahimi   switch (reg_) {
210*f5c631daSSadaf Ebrahimi     case APSR:
211*f5c631daSSadaf Ebrahimi       return "APSR";
212*f5c631daSSadaf Ebrahimi     case SPSR:
213*f5c631daSSadaf Ebrahimi       return "SPSR";
214*f5c631daSSadaf Ebrahimi   }
215*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
216*f5c631daSSadaf Ebrahimi   return "??";
217*f5c631daSSadaf Ebrahimi }
218*f5c631daSSadaf Ebrahimi 
219*f5c631daSSadaf Ebrahimi 
GetName() const220*f5c631daSSadaf Ebrahimi const char* MaskedSpecialRegister::GetName() const {
221*f5c631daSSadaf Ebrahimi   switch (reg_) {
222*f5c631daSSadaf Ebrahimi     case APSR_nzcvq:
223*f5c631daSSadaf Ebrahimi       return "APSR_nzcvq";
224*f5c631daSSadaf Ebrahimi     case APSR_g:
225*f5c631daSSadaf Ebrahimi       return "APSR_g";
226*f5c631daSSadaf Ebrahimi     case APSR_nzcvqg:
227*f5c631daSSadaf Ebrahimi       return "APSR_nzcvqg";
228*f5c631daSSadaf Ebrahimi     case CPSR_c:
229*f5c631daSSadaf Ebrahimi       return "CPSR_c";
230*f5c631daSSadaf Ebrahimi     case CPSR_x:
231*f5c631daSSadaf Ebrahimi       return "CPSR_x";
232*f5c631daSSadaf Ebrahimi     case CPSR_xc:
233*f5c631daSSadaf Ebrahimi       return "CPSR_xc";
234*f5c631daSSadaf Ebrahimi     case CPSR_sc:
235*f5c631daSSadaf Ebrahimi       return "CPSR_sc";
236*f5c631daSSadaf Ebrahimi     case CPSR_sx:
237*f5c631daSSadaf Ebrahimi       return "CPSR_sx";
238*f5c631daSSadaf Ebrahimi     case CPSR_sxc:
239*f5c631daSSadaf Ebrahimi       return "CPSR_sxc";
240*f5c631daSSadaf Ebrahimi     case CPSR_fc:
241*f5c631daSSadaf Ebrahimi       return "CPSR_fc";
242*f5c631daSSadaf Ebrahimi     case CPSR_fx:
243*f5c631daSSadaf Ebrahimi       return "CPSR_fx";
244*f5c631daSSadaf Ebrahimi     case CPSR_fxc:
245*f5c631daSSadaf Ebrahimi       return "CPSR_fxc";
246*f5c631daSSadaf Ebrahimi     case CPSR_fsc:
247*f5c631daSSadaf Ebrahimi       return "CPSR_fsc";
248*f5c631daSSadaf Ebrahimi     case CPSR_fsx:
249*f5c631daSSadaf Ebrahimi       return "CPSR_fsx";
250*f5c631daSSadaf Ebrahimi     case CPSR_fsxc:
251*f5c631daSSadaf Ebrahimi       return "CPSR_fsxc";
252*f5c631daSSadaf Ebrahimi     case SPSR_c:
253*f5c631daSSadaf Ebrahimi       return "SPSR_c";
254*f5c631daSSadaf Ebrahimi     case SPSR_x:
255*f5c631daSSadaf Ebrahimi       return "SPSR_x";
256*f5c631daSSadaf Ebrahimi     case SPSR_xc:
257*f5c631daSSadaf Ebrahimi       return "SPSR_xc";
258*f5c631daSSadaf Ebrahimi     case SPSR_s:
259*f5c631daSSadaf Ebrahimi       return "SPSR_s";
260*f5c631daSSadaf Ebrahimi     case SPSR_sc:
261*f5c631daSSadaf Ebrahimi       return "SPSR_sc";
262*f5c631daSSadaf Ebrahimi     case SPSR_sx:
263*f5c631daSSadaf Ebrahimi       return "SPSR_sx";
264*f5c631daSSadaf Ebrahimi     case SPSR_sxc:
265*f5c631daSSadaf Ebrahimi       return "SPSR_sxc";
266*f5c631daSSadaf Ebrahimi     case SPSR_f:
267*f5c631daSSadaf Ebrahimi       return "SPSR_f";
268*f5c631daSSadaf Ebrahimi     case SPSR_fc:
269*f5c631daSSadaf Ebrahimi       return "SPSR_fc";
270*f5c631daSSadaf Ebrahimi     case SPSR_fx:
271*f5c631daSSadaf Ebrahimi       return "SPSR_fx";
272*f5c631daSSadaf Ebrahimi     case SPSR_fxc:
273*f5c631daSSadaf Ebrahimi       return "SPSR_fxc";
274*f5c631daSSadaf Ebrahimi     case SPSR_fs:
275*f5c631daSSadaf Ebrahimi       return "SPSR_fs";
276*f5c631daSSadaf Ebrahimi     case SPSR_fsc:
277*f5c631daSSadaf Ebrahimi       return "SPSR_fsc";
278*f5c631daSSadaf Ebrahimi     case SPSR_fsx:
279*f5c631daSSadaf Ebrahimi       return "SPSR_fsx";
280*f5c631daSSadaf Ebrahimi     case SPSR_fsxc:
281*f5c631daSSadaf Ebrahimi       return "SPSR_fsxc";
282*f5c631daSSadaf Ebrahimi   }
283*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
284*f5c631daSSadaf Ebrahimi   return "??";
285*f5c631daSSadaf Ebrahimi }
286*f5c631daSSadaf Ebrahimi 
287*f5c631daSSadaf Ebrahimi 
GetName() const288*f5c631daSSadaf Ebrahimi const char* BankedRegister::GetName() const {
289*f5c631daSSadaf Ebrahimi   switch (reg_) {
290*f5c631daSSadaf Ebrahimi     case R8_usr:
291*f5c631daSSadaf Ebrahimi       return "R8_usr";
292*f5c631daSSadaf Ebrahimi     case R9_usr:
293*f5c631daSSadaf Ebrahimi       return "R9_usr";
294*f5c631daSSadaf Ebrahimi     case R10_usr:
295*f5c631daSSadaf Ebrahimi       return "R10_usr";
296*f5c631daSSadaf Ebrahimi     case R11_usr:
297*f5c631daSSadaf Ebrahimi       return "R11_usr";
298*f5c631daSSadaf Ebrahimi     case R12_usr:
299*f5c631daSSadaf Ebrahimi       return "R12_usr";
300*f5c631daSSadaf Ebrahimi     case SP_usr:
301*f5c631daSSadaf Ebrahimi       return "SP_usr";
302*f5c631daSSadaf Ebrahimi     case LR_usr:
303*f5c631daSSadaf Ebrahimi       return "LR_usr";
304*f5c631daSSadaf Ebrahimi     case R8_fiq:
305*f5c631daSSadaf Ebrahimi       return "R8_fiq";
306*f5c631daSSadaf Ebrahimi     case R9_fiq:
307*f5c631daSSadaf Ebrahimi       return "R9_fiq";
308*f5c631daSSadaf Ebrahimi     case R10_fiq:
309*f5c631daSSadaf Ebrahimi       return "R10_fiq";
310*f5c631daSSadaf Ebrahimi     case R11_fiq:
311*f5c631daSSadaf Ebrahimi       return "R11_fiq";
312*f5c631daSSadaf Ebrahimi     case R12_fiq:
313*f5c631daSSadaf Ebrahimi       return "R12_fiq";
314*f5c631daSSadaf Ebrahimi     case SP_fiq:
315*f5c631daSSadaf Ebrahimi       return "SP_fiq";
316*f5c631daSSadaf Ebrahimi     case LR_fiq:
317*f5c631daSSadaf Ebrahimi       return "LR_fiq";
318*f5c631daSSadaf Ebrahimi     case LR_irq:
319*f5c631daSSadaf Ebrahimi       return "LR_irq";
320*f5c631daSSadaf Ebrahimi     case SP_irq:
321*f5c631daSSadaf Ebrahimi       return "SP_irq";
322*f5c631daSSadaf Ebrahimi     case LR_svc:
323*f5c631daSSadaf Ebrahimi       return "LR_svc";
324*f5c631daSSadaf Ebrahimi     case SP_svc:
325*f5c631daSSadaf Ebrahimi       return "SP_svc";
326*f5c631daSSadaf Ebrahimi     case LR_abt:
327*f5c631daSSadaf Ebrahimi       return "LR_abt";
328*f5c631daSSadaf Ebrahimi     case SP_abt:
329*f5c631daSSadaf Ebrahimi       return "SP_abt";
330*f5c631daSSadaf Ebrahimi     case LR_und:
331*f5c631daSSadaf Ebrahimi       return "LR_und";
332*f5c631daSSadaf Ebrahimi     case SP_und:
333*f5c631daSSadaf Ebrahimi       return "SP_und";
334*f5c631daSSadaf Ebrahimi     case LR_mon:
335*f5c631daSSadaf Ebrahimi       return "LR_mon";
336*f5c631daSSadaf Ebrahimi     case SP_mon:
337*f5c631daSSadaf Ebrahimi       return "SP_mon";
338*f5c631daSSadaf Ebrahimi     case ELR_hyp:
339*f5c631daSSadaf Ebrahimi       return "ELR_hyp";
340*f5c631daSSadaf Ebrahimi     case SP_hyp:
341*f5c631daSSadaf Ebrahimi       return "SP_hyp";
342*f5c631daSSadaf Ebrahimi     case SPSR_fiq:
343*f5c631daSSadaf Ebrahimi       return "SPSR_fiq";
344*f5c631daSSadaf Ebrahimi     case SPSR_irq:
345*f5c631daSSadaf Ebrahimi       return "SPSR_irq";
346*f5c631daSSadaf Ebrahimi     case SPSR_svc:
347*f5c631daSSadaf Ebrahimi       return "SPSR_svc";
348*f5c631daSSadaf Ebrahimi     case SPSR_abt:
349*f5c631daSSadaf Ebrahimi       return "SPSR_abt";
350*f5c631daSSadaf Ebrahimi     case SPSR_und:
351*f5c631daSSadaf Ebrahimi       return "SPSR_und";
352*f5c631daSSadaf Ebrahimi     case SPSR_mon:
353*f5c631daSSadaf Ebrahimi       return "SPSR_mon";
354*f5c631daSSadaf Ebrahimi     case SPSR_hyp:
355*f5c631daSSadaf Ebrahimi       return "SPSR_hyp";
356*f5c631daSSadaf Ebrahimi   }
357*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
358*f5c631daSSadaf Ebrahimi   return "??";
359*f5c631daSSadaf Ebrahimi }
360*f5c631daSSadaf Ebrahimi 
GetName() const361*f5c631daSSadaf Ebrahimi const char* SpecialFPRegister::GetName() const {
362*f5c631daSSadaf Ebrahimi   switch (reg_) {
363*f5c631daSSadaf Ebrahimi     case FPSID:
364*f5c631daSSadaf Ebrahimi       return "FPSID";
365*f5c631daSSadaf Ebrahimi     case FPSCR:
366*f5c631daSSadaf Ebrahimi       return "FPSCR";
367*f5c631daSSadaf Ebrahimi     case MVFR2:
368*f5c631daSSadaf Ebrahimi       return "MVFR2";
369*f5c631daSSadaf Ebrahimi     case MVFR1:
370*f5c631daSSadaf Ebrahimi       return "MVFR1";
371*f5c631daSSadaf Ebrahimi     case MVFR0:
372*f5c631daSSadaf Ebrahimi       return "MVFR0";
373*f5c631daSSadaf Ebrahimi     case FPEXC:
374*f5c631daSSadaf Ebrahimi       return "FPEXC";
375*f5c631daSSadaf Ebrahimi   }
376*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
377*f5c631daSSadaf Ebrahimi   return "??";
378*f5c631daSSadaf Ebrahimi }
379*f5c631daSSadaf Ebrahimi 
380*f5c631daSSadaf Ebrahimi 
GetName() const381*f5c631daSSadaf Ebrahimi const char* Condition::GetName() const {
382*f5c631daSSadaf Ebrahimi   switch (condition_) {
383*f5c631daSSadaf Ebrahimi     case eq:
384*f5c631daSSadaf Ebrahimi       return "eq";
385*f5c631daSSadaf Ebrahimi     case ne:
386*f5c631daSSadaf Ebrahimi       return "ne";
387*f5c631daSSadaf Ebrahimi     case cs:
388*f5c631daSSadaf Ebrahimi       return "cs";
389*f5c631daSSadaf Ebrahimi     case cc:
390*f5c631daSSadaf Ebrahimi       return "cc";
391*f5c631daSSadaf Ebrahimi     case mi:
392*f5c631daSSadaf Ebrahimi       return "mi";
393*f5c631daSSadaf Ebrahimi     case pl:
394*f5c631daSSadaf Ebrahimi       return "pl";
395*f5c631daSSadaf Ebrahimi     case vs:
396*f5c631daSSadaf Ebrahimi       return "vs";
397*f5c631daSSadaf Ebrahimi     case vc:
398*f5c631daSSadaf Ebrahimi       return "vc";
399*f5c631daSSadaf Ebrahimi     case hi:
400*f5c631daSSadaf Ebrahimi       return "hi";
401*f5c631daSSadaf Ebrahimi     case ls:
402*f5c631daSSadaf Ebrahimi       return "ls";
403*f5c631daSSadaf Ebrahimi     case ge:
404*f5c631daSSadaf Ebrahimi       return "ge";
405*f5c631daSSadaf Ebrahimi     case lt:
406*f5c631daSSadaf Ebrahimi       return "lt";
407*f5c631daSSadaf Ebrahimi     case gt:
408*f5c631daSSadaf Ebrahimi       return "gt";
409*f5c631daSSadaf Ebrahimi     case le:
410*f5c631daSSadaf Ebrahimi       return "le";
411*f5c631daSSadaf Ebrahimi     case al:
412*f5c631daSSadaf Ebrahimi       return "";
413*f5c631daSSadaf Ebrahimi     case Condition::kNone:
414*f5c631daSSadaf Ebrahimi       return "";
415*f5c631daSSadaf Ebrahimi   }
416*f5c631daSSadaf Ebrahimi   return "<und>";
417*f5c631daSSadaf Ebrahimi }
418*f5c631daSSadaf Ebrahimi 
419*f5c631daSSadaf Ebrahimi 
GetName() const420*f5c631daSSadaf Ebrahimi const char* Shift::GetName() const {
421*f5c631daSSadaf Ebrahimi   switch (shift_) {
422*f5c631daSSadaf Ebrahimi     case LSL:
423*f5c631daSSadaf Ebrahimi       return "lsl";
424*f5c631daSSadaf Ebrahimi     case LSR:
425*f5c631daSSadaf Ebrahimi       return "lsr";
426*f5c631daSSadaf Ebrahimi     case ASR:
427*f5c631daSSadaf Ebrahimi       return "asr";
428*f5c631daSSadaf Ebrahimi     case ROR:
429*f5c631daSSadaf Ebrahimi       return "ror";
430*f5c631daSSadaf Ebrahimi     case RRX:
431*f5c631daSSadaf Ebrahimi       return "rrx";
432*f5c631daSSadaf Ebrahimi   }
433*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
434*f5c631daSSadaf Ebrahimi   return "??";
435*f5c631daSSadaf Ebrahimi }
436*f5c631daSSadaf Ebrahimi 
437*f5c631daSSadaf Ebrahimi 
GetName() const438*f5c631daSSadaf Ebrahimi const char* EncodingSize::GetName() const {
439*f5c631daSSadaf Ebrahimi   switch (size_) {
440*f5c631daSSadaf Ebrahimi     case Best:
441*f5c631daSSadaf Ebrahimi     case Narrow:
442*f5c631daSSadaf Ebrahimi       return "";
443*f5c631daSSadaf Ebrahimi     case Wide:
444*f5c631daSSadaf Ebrahimi       return ".w";
445*f5c631daSSadaf Ebrahimi   }
446*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
447*f5c631daSSadaf Ebrahimi   return "??";
448*f5c631daSSadaf Ebrahimi }
449*f5c631daSSadaf Ebrahimi 
450*f5c631daSSadaf Ebrahimi 
GetName() const451*f5c631daSSadaf Ebrahimi const char* DataType::GetName() const {
452*f5c631daSSadaf Ebrahimi   switch (value_) {
453*f5c631daSSadaf Ebrahimi     case kDataTypeValueInvalid:
454*f5c631daSSadaf Ebrahimi       return ".??";
455*f5c631daSSadaf Ebrahimi     case kDataTypeValueNone:
456*f5c631daSSadaf Ebrahimi       return "";
457*f5c631daSSadaf Ebrahimi     case S8:
458*f5c631daSSadaf Ebrahimi       return ".s8";
459*f5c631daSSadaf Ebrahimi     case S16:
460*f5c631daSSadaf Ebrahimi       return ".s16";
461*f5c631daSSadaf Ebrahimi     case S32:
462*f5c631daSSadaf Ebrahimi       return ".s32";
463*f5c631daSSadaf Ebrahimi     case S64:
464*f5c631daSSadaf Ebrahimi       return ".s64";
465*f5c631daSSadaf Ebrahimi     case U8:
466*f5c631daSSadaf Ebrahimi       return ".u8";
467*f5c631daSSadaf Ebrahimi     case U16:
468*f5c631daSSadaf Ebrahimi       return ".u16";
469*f5c631daSSadaf Ebrahimi     case U32:
470*f5c631daSSadaf Ebrahimi       return ".u32";
471*f5c631daSSadaf Ebrahimi     case U64:
472*f5c631daSSadaf Ebrahimi       return ".u64";
473*f5c631daSSadaf Ebrahimi     case F16:
474*f5c631daSSadaf Ebrahimi       return ".f16";
475*f5c631daSSadaf Ebrahimi     case F32:
476*f5c631daSSadaf Ebrahimi       return ".f32";
477*f5c631daSSadaf Ebrahimi     case F64:
478*f5c631daSSadaf Ebrahimi       return ".f64";
479*f5c631daSSadaf Ebrahimi     case I8:
480*f5c631daSSadaf Ebrahimi       return ".i8";
481*f5c631daSSadaf Ebrahimi     case I16:
482*f5c631daSSadaf Ebrahimi       return ".i16";
483*f5c631daSSadaf Ebrahimi     case I32:
484*f5c631daSSadaf Ebrahimi       return ".i32";
485*f5c631daSSadaf Ebrahimi     case I64:
486*f5c631daSSadaf Ebrahimi       return ".i64";
487*f5c631daSSadaf Ebrahimi     case P8:
488*f5c631daSSadaf Ebrahimi       return ".p8";
489*f5c631daSSadaf Ebrahimi     case P64:
490*f5c631daSSadaf Ebrahimi       return ".p64";
491*f5c631daSSadaf Ebrahimi     case Untyped8:
492*f5c631daSSadaf Ebrahimi       return ".8";
493*f5c631daSSadaf Ebrahimi     case Untyped16:
494*f5c631daSSadaf Ebrahimi       return ".16";
495*f5c631daSSadaf Ebrahimi     case Untyped32:
496*f5c631daSSadaf Ebrahimi       return ".32";
497*f5c631daSSadaf Ebrahimi     case Untyped64:
498*f5c631daSSadaf Ebrahimi       return ".64";
499*f5c631daSSadaf Ebrahimi   }
500*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
501*f5c631daSSadaf Ebrahimi   return ".??";
502*f5c631daSSadaf Ebrahimi }
503*f5c631daSSadaf Ebrahimi 
504*f5c631daSSadaf Ebrahimi 
GetName() const505*f5c631daSSadaf Ebrahimi const char* MemoryBarrier::GetName() const {
506*f5c631daSSadaf Ebrahimi   switch (type_) {
507*f5c631daSSadaf Ebrahimi     case OSHLD:
508*f5c631daSSadaf Ebrahimi       return "oshld";
509*f5c631daSSadaf Ebrahimi     case OSHST:
510*f5c631daSSadaf Ebrahimi       return "oshst";
511*f5c631daSSadaf Ebrahimi     case OSH:
512*f5c631daSSadaf Ebrahimi       return "osh";
513*f5c631daSSadaf Ebrahimi     case NSHLD:
514*f5c631daSSadaf Ebrahimi       return "nshld";
515*f5c631daSSadaf Ebrahimi     case NSHST:
516*f5c631daSSadaf Ebrahimi       return "nshst";
517*f5c631daSSadaf Ebrahimi     case NSH:
518*f5c631daSSadaf Ebrahimi       return "nsh";
519*f5c631daSSadaf Ebrahimi     case ISHLD:
520*f5c631daSSadaf Ebrahimi       return "ishld";
521*f5c631daSSadaf Ebrahimi     case ISHST:
522*f5c631daSSadaf Ebrahimi       return "ishst";
523*f5c631daSSadaf Ebrahimi     case ISH:
524*f5c631daSSadaf Ebrahimi       return "ish";
525*f5c631daSSadaf Ebrahimi     case LD:
526*f5c631daSSadaf Ebrahimi       return "ld";
527*f5c631daSSadaf Ebrahimi     case ST:
528*f5c631daSSadaf Ebrahimi       return "st";
529*f5c631daSSadaf Ebrahimi     case SY:
530*f5c631daSSadaf Ebrahimi       return "sy";
531*f5c631daSSadaf Ebrahimi   }
532*f5c631daSSadaf Ebrahimi   switch (static_cast<int>(type_)) {
533*f5c631daSSadaf Ebrahimi     case 0:
534*f5c631daSSadaf Ebrahimi       return "#0x0";
535*f5c631daSSadaf Ebrahimi     case 4:
536*f5c631daSSadaf Ebrahimi       return "#0x4";
537*f5c631daSSadaf Ebrahimi     case 8:
538*f5c631daSSadaf Ebrahimi       return "#0x8";
539*f5c631daSSadaf Ebrahimi     case 0xc:
540*f5c631daSSadaf Ebrahimi       return "#0xc";
541*f5c631daSSadaf Ebrahimi   }
542*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
543*f5c631daSSadaf Ebrahimi   return "??";
544*f5c631daSSadaf Ebrahimi }
545*f5c631daSSadaf Ebrahimi 
546*f5c631daSSadaf Ebrahimi 
GetName() const547*f5c631daSSadaf Ebrahimi const char* InterruptFlags::GetName() const {
548*f5c631daSSadaf Ebrahimi   switch (type_) {
549*f5c631daSSadaf Ebrahimi     case F:
550*f5c631daSSadaf Ebrahimi       return "f";
551*f5c631daSSadaf Ebrahimi     case I:
552*f5c631daSSadaf Ebrahimi       return "i";
553*f5c631daSSadaf Ebrahimi     case IF:
554*f5c631daSSadaf Ebrahimi       return "if";
555*f5c631daSSadaf Ebrahimi     case A:
556*f5c631daSSadaf Ebrahimi       return "a";
557*f5c631daSSadaf Ebrahimi     case AF:
558*f5c631daSSadaf Ebrahimi       return "af";
559*f5c631daSSadaf Ebrahimi     case AI:
560*f5c631daSSadaf Ebrahimi       return "ai";
561*f5c631daSSadaf Ebrahimi     case AIF:
562*f5c631daSSadaf Ebrahimi       return "aif";
563*f5c631daSSadaf Ebrahimi   }
564*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(type_ == 0);
565*f5c631daSSadaf Ebrahimi   return "";
566*f5c631daSSadaf Ebrahimi }
567*f5c631daSSadaf Ebrahimi 
568*f5c631daSSadaf Ebrahimi 
GetName() const569*f5c631daSSadaf Ebrahimi const char* Endianness::GetName() const {
570*f5c631daSSadaf Ebrahimi   switch (type_) {
571*f5c631daSSadaf Ebrahimi     case LE:
572*f5c631daSSadaf Ebrahimi       return "le";
573*f5c631daSSadaf Ebrahimi     case BE:
574*f5c631daSSadaf Ebrahimi       return "be";
575*f5c631daSSadaf Ebrahimi   }
576*f5c631daSSadaf Ebrahimi   VIXL_UNREACHABLE();
577*f5c631daSSadaf Ebrahimi   return "??";
578*f5c631daSSadaf Ebrahimi }
579*f5c631daSSadaf Ebrahimi 
580*f5c631daSSadaf Ebrahimi 
581*f5c631daSSadaf Ebrahimi // Constructor used for disassembly.
ImmediateShiftOperand(int shift_value,int amount_value)582*f5c631daSSadaf Ebrahimi ImmediateShiftOperand::ImmediateShiftOperand(int shift_value, int amount_value)
583*f5c631daSSadaf Ebrahimi     : Shift(shift_value) {
584*f5c631daSSadaf Ebrahimi   switch (shift_value) {
585*f5c631daSSadaf Ebrahimi     case LSL:
586*f5c631daSSadaf Ebrahimi       amount_ = amount_value;
587*f5c631daSSadaf Ebrahimi       break;
588*f5c631daSSadaf Ebrahimi     case LSR:
589*f5c631daSSadaf Ebrahimi     case ASR:
590*f5c631daSSadaf Ebrahimi       amount_ = (amount_value == 0) ? 32 : amount_value;
591*f5c631daSSadaf Ebrahimi       break;
592*f5c631daSSadaf Ebrahimi     case ROR:
593*f5c631daSSadaf Ebrahimi       amount_ = amount_value;
594*f5c631daSSadaf Ebrahimi       if (amount_value == 0) SetType(RRX);
595*f5c631daSSadaf Ebrahimi       break;
596*f5c631daSSadaf Ebrahimi     default:
597*f5c631daSSadaf Ebrahimi       VIXL_UNREACHABLE();
598*f5c631daSSadaf Ebrahimi       SetType(LSL);
599*f5c631daSSadaf Ebrahimi       amount_ = 0;
600*f5c631daSSadaf Ebrahimi       break;
601*f5c631daSSadaf Ebrahimi   }
602*f5c631daSSadaf Ebrahimi }
603*f5c631daSSadaf Ebrahimi 
604*f5c631daSSadaf Ebrahimi 
ImmediateT32(uint32_t imm)605*f5c631daSSadaf Ebrahimi ImmediateT32::ImmediateT32(uint32_t imm) {
606*f5c631daSSadaf Ebrahimi   // 00000000 00000000 00000000 abcdefgh
607*f5c631daSSadaf Ebrahimi   if ((imm & ~0xff) == 0) {
608*f5c631daSSadaf Ebrahimi     SetEncodingValue(imm);
609*f5c631daSSadaf Ebrahimi     return;
610*f5c631daSSadaf Ebrahimi   }
611*f5c631daSSadaf Ebrahimi   if ((imm >> 16) == (imm & 0xffff)) {
612*f5c631daSSadaf Ebrahimi     if ((imm & 0xff00) == 0) {
613*f5c631daSSadaf Ebrahimi       // 00000000 abcdefgh 00000000 abcdefgh
614*f5c631daSSadaf Ebrahimi       SetEncodingValue((imm & 0xff) | (0x1 << 8));
615*f5c631daSSadaf Ebrahimi       return;
616*f5c631daSSadaf Ebrahimi     }
617*f5c631daSSadaf Ebrahimi     if ((imm & 0xff) == 0) {
618*f5c631daSSadaf Ebrahimi       // abcdefgh 00000000 abcdefgh 00000000
619*f5c631daSSadaf Ebrahimi       SetEncodingValue(((imm >> 8) & 0xff) | (0x2 << 8));
620*f5c631daSSadaf Ebrahimi       return;
621*f5c631daSSadaf Ebrahimi     }
622*f5c631daSSadaf Ebrahimi     if (((imm >> 8) & 0xff) == (imm & 0xff)) {
623*f5c631daSSadaf Ebrahimi       // abcdefgh abcdefgh abcdefgh abcdefgh
624*f5c631daSSadaf Ebrahimi       SetEncodingValue((imm & 0xff) | (0x3 << 8));
625*f5c631daSSadaf Ebrahimi       return;
626*f5c631daSSadaf Ebrahimi     }
627*f5c631daSSadaf Ebrahimi   }
628*f5c631daSSadaf Ebrahimi   for (int shift = 0; shift < 24; shift++) {
629*f5c631daSSadaf Ebrahimi     uint32_t imm8 = imm >> (24 - shift);
630*f5c631daSSadaf Ebrahimi     uint32_t overflow = imm << (8 + shift);
631*f5c631daSSadaf Ebrahimi     if ((imm8 <= 0xff) && ((imm8 & 0x80) != 0) && (overflow == 0)) {
632*f5c631daSSadaf Ebrahimi       SetEncodingValue(((shift + 8) << 7) | (imm8 & 0x7F));
633*f5c631daSSadaf Ebrahimi       return;
634*f5c631daSSadaf Ebrahimi     }
635*f5c631daSSadaf Ebrahimi   }
636*f5c631daSSadaf Ebrahimi }
637*f5c631daSSadaf Ebrahimi 
638*f5c631daSSadaf Ebrahimi 
ror(uint32_t x,int i)639*f5c631daSSadaf Ebrahimi static inline uint32_t ror(uint32_t x, int i) {
640*f5c631daSSadaf Ebrahimi   VIXL_ASSERT((0 < i) && (i < 32));
641*f5c631daSSadaf Ebrahimi   return (x >> i) | (x << (32 - i));
642*f5c631daSSadaf Ebrahimi }
643*f5c631daSSadaf Ebrahimi 
644*f5c631daSSadaf Ebrahimi 
IsImmediateT32(uint32_t imm)645*f5c631daSSadaf Ebrahimi bool ImmediateT32::IsImmediateT32(uint32_t imm) {
646*f5c631daSSadaf Ebrahimi   /* abcdefgh abcdefgh abcdefgh abcdefgh */
647*f5c631daSSadaf Ebrahimi   if ((imm ^ ror(imm, 8)) == 0) return true;
648*f5c631daSSadaf Ebrahimi   /* 00000000 abcdefgh 00000000 abcdefgh */
649*f5c631daSSadaf Ebrahimi   /* abcdefgh 00000000 abcdefgh 00000000 */
650*f5c631daSSadaf Ebrahimi   if ((imm ^ ror(imm, 16)) == 0 &&
651*f5c631daSSadaf Ebrahimi       (((imm & 0xff00) == 0) || ((imm & 0xff) == 0)))
652*f5c631daSSadaf Ebrahimi     return true;
653*f5c631daSSadaf Ebrahimi   /* isolate least-significant set bit */
654*f5c631daSSadaf Ebrahimi   uint32_t lsb = imm & -imm;
655*f5c631daSSadaf Ebrahimi   /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
656*f5c631daSSadaf Ebrahimi   * avoid overflow (underflow is always a successful case) */
657*f5c631daSSadaf Ebrahimi   return ((imm >> 8) < lsb);
658*f5c631daSSadaf Ebrahimi }
659*f5c631daSSadaf Ebrahimi 
660*f5c631daSSadaf Ebrahimi 
Decode(uint32_t value)661*f5c631daSSadaf Ebrahimi uint32_t ImmediateT32::Decode(uint32_t value) {
662*f5c631daSSadaf Ebrahimi   uint32_t base = value & 0xff;
663*f5c631daSSadaf Ebrahimi   switch (value >> 8) {
664*f5c631daSSadaf Ebrahimi     case 0:
665*f5c631daSSadaf Ebrahimi       return base;
666*f5c631daSSadaf Ebrahimi     case 1:
667*f5c631daSSadaf Ebrahimi       return base | (base << 16);
668*f5c631daSSadaf Ebrahimi     case 2:
669*f5c631daSSadaf Ebrahimi       return (base << 8) | (base << 24);
670*f5c631daSSadaf Ebrahimi     case 3:
671*f5c631daSSadaf Ebrahimi       return base | (base << 8) | (base << 16) | (base << 24);
672*f5c631daSSadaf Ebrahimi     default:
673*f5c631daSSadaf Ebrahimi       base |= 0x80;
674*f5c631daSSadaf Ebrahimi       return base << (32 - (value >> 7));
675*f5c631daSSadaf Ebrahimi   }
676*f5c631daSSadaf Ebrahimi }
677*f5c631daSSadaf Ebrahimi 
678*f5c631daSSadaf Ebrahimi 
ImmediateA32(uint32_t imm)679*f5c631daSSadaf Ebrahimi ImmediateA32::ImmediateA32(uint32_t imm) {
680*f5c631daSSadaf Ebrahimi   // Deal with rot = 0 first to avoid undefined shift by 32.
681*f5c631daSSadaf Ebrahimi   if (imm <= 0xff) {
682*f5c631daSSadaf Ebrahimi     SetEncodingValue(imm);
683*f5c631daSSadaf Ebrahimi     return;
684*f5c631daSSadaf Ebrahimi   }
685*f5c631daSSadaf Ebrahimi   for (int rot = 2; rot < 32; rot += 2) {
686*f5c631daSSadaf Ebrahimi     uint32_t imm8 = (imm << rot) | (imm >> (32 - rot));
687*f5c631daSSadaf Ebrahimi     if (imm8 <= 0xff) {
688*f5c631daSSadaf Ebrahimi       SetEncodingValue((rot << 7) | imm8);
689*f5c631daSSadaf Ebrahimi       return;
690*f5c631daSSadaf Ebrahimi     }
691*f5c631daSSadaf Ebrahimi   }
692*f5c631daSSadaf Ebrahimi }
693*f5c631daSSadaf Ebrahimi 
694*f5c631daSSadaf Ebrahimi 
IsImmediateA32(uint32_t imm)695*f5c631daSSadaf Ebrahimi bool ImmediateA32::IsImmediateA32(uint32_t imm) {
696*f5c631daSSadaf Ebrahimi   /* fast-out */
697*f5c631daSSadaf Ebrahimi   if (imm < 256) return true;
698*f5c631daSSadaf Ebrahimi   /* avoid getting confused by wrapped-around bytes (this transform has no
699*f5c631daSSadaf Ebrahimi    * effect on pass/fail results) */
700*f5c631daSSadaf Ebrahimi   if (imm & 0xff000000) imm = ror(imm, 16);
701*f5c631daSSadaf Ebrahimi   /* copy odd-numbered set bits into even-numbered bits immediately below, so
702*f5c631daSSadaf Ebrahimi    * that the least-significant set bit is always an even bit */
703*f5c631daSSadaf Ebrahimi   imm = imm | ((imm >> 1) & 0x55555555);
704*f5c631daSSadaf Ebrahimi   /* isolate least-significant set bit (always even) */
705*f5c631daSSadaf Ebrahimi   uint32_t lsb = imm & -imm;
706*f5c631daSSadaf Ebrahimi   /* if imm is less than lsb*256 then it fits, but instead we test imm/256 to
707*f5c631daSSadaf Ebrahimi    * avoid overflow (underflow is always a successful case) */
708*f5c631daSSadaf Ebrahimi   return ((imm >> 8) < lsb);
709*f5c631daSSadaf Ebrahimi }
710*f5c631daSSadaf Ebrahimi 
711*f5c631daSSadaf Ebrahimi 
Decode(uint32_t value)712*f5c631daSSadaf Ebrahimi uint32_t ImmediateA32::Decode(uint32_t value) {
713*f5c631daSSadaf Ebrahimi   int rotation = (value >> 8) * 2;
714*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(rotation >= 0);
715*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(rotation <= 30);
716*f5c631daSSadaf Ebrahimi   value &= 0xff;
717*f5c631daSSadaf Ebrahimi   if (rotation == 0) return value;
718*f5c631daSSadaf Ebrahimi   return (value >> rotation) | (value << (32 - rotation));
719*f5c631daSSadaf Ebrahimi }
720*f5c631daSSadaf Ebrahimi 
721*f5c631daSSadaf Ebrahimi 
TypeEncodingValue(Shift shift)722*f5c631daSSadaf Ebrahimi uint32_t TypeEncodingValue(Shift shift) {
723*f5c631daSSadaf Ebrahimi   return shift.IsRRX() ? kRRXEncodedValue : shift.GetValue();
724*f5c631daSSadaf Ebrahimi }
725*f5c631daSSadaf Ebrahimi 
726*f5c631daSSadaf Ebrahimi 
AmountEncodingValue(Shift shift,uint32_t amount)727*f5c631daSSadaf Ebrahimi uint32_t AmountEncodingValue(Shift shift, uint32_t amount) {
728*f5c631daSSadaf Ebrahimi   switch (shift.GetType()) {
729*f5c631daSSadaf Ebrahimi     case LSL:
730*f5c631daSSadaf Ebrahimi     case ROR:
731*f5c631daSSadaf Ebrahimi       return amount;
732*f5c631daSSadaf Ebrahimi     case LSR:
733*f5c631daSSadaf Ebrahimi     case ASR:
734*f5c631daSSadaf Ebrahimi       return amount % 32;
735*f5c631daSSadaf Ebrahimi     case RRX:
736*f5c631daSSadaf Ebrahimi       return 0;
737*f5c631daSSadaf Ebrahimi   }
738*f5c631daSSadaf Ebrahimi   return 0;
739*f5c631daSSadaf Ebrahimi }
740*f5c631daSSadaf Ebrahimi 
741*f5c631daSSadaf Ebrahimi }  // namespace aarch32
742*f5c631daSSadaf Ebrahimi }  // namespace vixl
743