• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright
10 //     notice, this list of conditions and the following disclaimer in the
11 //     documentation and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may
13 //     be used to endorse or promote products derived from this software
14 //     without 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
18 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 // POSSIBILITY OF SUCH DAMAGE.
27 
28 extern "C" {
29 #include <inttypes.h>
30 #include <stdint.h>
31 }
32 
33 #include <cassert>
34 #include <cmath>
35 #include <cstdio>
36 #include <cstdlib>
37 #include <cstring>
38 #include <iomanip>
39 #include <iostream>
40 
41 #include "utils-vixl.h"
42 #include "aarch32/constants-aarch32.h"
43 #include "aarch32/instructions-aarch32.h"
44 #include "aarch32/operands-aarch32.h"
45 
46 namespace vixl {
47 namespace aarch32 {
48 
49 // Operand
50 
operator <<(std::ostream & os,const Operand & operand)51 std::ostream& operator<<(std::ostream& os, const Operand& operand) {
52   if (operand.IsImmediate()) {
53     return os << "#" << operand.GetImmediate();
54   }
55   if (operand.IsImmediateShiftedRegister()) {
56     if ((operand.GetShift().IsLSL() || operand.GetShift().IsROR()) &&
57         (operand.GetShiftAmount() == 0)) {
58       return os << operand.GetBaseRegister();
59     }
60     if (operand.GetShift().IsRRX()) {
61       return os << operand.GetBaseRegister() << ", rrx";
62     }
63     return os << operand.GetBaseRegister() << ", " << operand.GetShift() << " #"
64               << operand.GetShiftAmount();
65   }
66   if (operand.IsRegisterShiftedRegister()) {
67     return os << operand.GetBaseRegister() << ", " << operand.GetShift() << " "
68               << operand.GetShiftRegister();
69   }
70   VIXL_UNREACHABLE();
71   return os;
72 }
73 
operator <<(std::ostream & os,const NeonImmediate & neon_imm)74 std::ostream& operator<<(std::ostream& os, const NeonImmediate& neon_imm) {
75   if (neon_imm.IsDouble()) {
76     if (neon_imm.imm_.d_ == 0) {
77       if (copysign(1.0, neon_imm.imm_.d_) < 0.0) {
78         return os << "#-0.0";
79       }
80       return os << "#0.0";
81     }
82     return os << "#" << std::setprecision(9) << neon_imm.imm_.d_;
83   }
84   if (neon_imm.IsFloat()) {
85     if (neon_imm.imm_.f_ == 0) {
86       if (copysign(1.0, neon_imm.imm_.d_) < 0.0) return os << "#-0.0";
87       return os << "#0.0";
88     }
89     return os << "#" << std::setprecision(9) << neon_imm.imm_.f_;
90   }
91   if (neon_imm.IsInteger64()) {
92     return os << "#0x" << std::hex << std::setw(16) << std::setfill('0')
93               << neon_imm.imm_.u64_ << std::dec;
94   }
95   return os << "#" << neon_imm.imm_.u32_;
96 }
97 
98 // SOperand
99 
operator <<(std::ostream & os,const SOperand & operand)100 std::ostream& operator<<(std::ostream& os, const SOperand& operand) {
101   if (operand.IsImmediate()) {
102     return os << operand.GetNeonImmediate();
103   }
104   return os << operand.GetRegister();
105 }
106 
107 // DOperand
108 
operator <<(std::ostream & os,const DOperand & operand)109 std::ostream& operator<<(std::ostream& os, const DOperand& operand) {
110   if (operand.IsImmediate()) {
111     return os << operand.GetNeonImmediate();
112   }
113   return os << operand.GetRegister();
114 }
115 
116 // QOperand
117 
operator <<(std::ostream & os,const QOperand & operand)118 std::ostream& operator<<(std::ostream& os, const QOperand& operand) {
119   if (operand.IsImmediate()) {
120     return os << operand.GetNeonImmediate();
121   }
122   return os << operand.GetRegister();
123 }
124 
125 
ImmediateVbic(DataType dt,const NeonImmediate & neon_imm)126 ImmediateVbic::ImmediateVbic(DataType dt, const NeonImmediate& neon_imm) {
127   if (neon_imm.IsInteger32()) {
128     uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
129     if (dt.GetValue() == I16) {
130       if ((immediate & ~0xff) == 0) {
131         SetEncodingValue(0x9);
132         SetEncodedImmediate(immediate);
133       } else if ((immediate & ~0xff00) == 0) {
134         SetEncodingValue(0xb);
135         SetEncodedImmediate(immediate >> 8);
136       }
137     } else if (dt.GetValue() == I32) {
138       if ((immediate & ~0xff) == 0) {
139         SetEncodingValue(0x1);
140         SetEncodedImmediate(immediate);
141       } else if ((immediate & ~0xff00) == 0) {
142         SetEncodingValue(0x3);
143         SetEncodedImmediate(immediate >> 8);
144       } else if ((immediate & ~0xff0000) == 0) {
145         SetEncodingValue(0x5);
146         SetEncodedImmediate(immediate >> 16);
147       } else if ((immediate & ~0xff000000) == 0) {
148         SetEncodingValue(0x7);
149         SetEncodedImmediate(immediate >> 24);
150       }
151     }
152   }
153 }
154 
155 
DecodeDt(uint32_t cmode)156 DataType ImmediateVbic::DecodeDt(uint32_t cmode) {
157   switch (cmode) {
158     case 0x1:
159     case 0x3:
160     case 0x5:
161     case 0x7:
162       return I32;
163     case 0x9:
164     case 0xb:
165       return I16;
166     default:
167       break;
168   }
169   VIXL_UNREACHABLE();
170   return kDataTypeValueInvalid;
171 }
172 
173 
DecodeImmediate(uint32_t cmode,uint32_t immediate)174 NeonImmediate ImmediateVbic::DecodeImmediate(uint32_t cmode,
175                                              uint32_t immediate) {
176   switch (cmode) {
177     case 0x1:
178     case 0x9:
179       return immediate;
180     case 0x3:
181     case 0xb:
182       return immediate << 8;
183     case 0x5:
184       return immediate << 16;
185     case 0x7:
186       return immediate << 24;
187     default:
188       break;
189   }
190   VIXL_UNREACHABLE();
191   return 0;
192 }
193 
194 
ImmediateVmov(DataType dt,const NeonImmediate & neon_imm)195 ImmediateVmov::ImmediateVmov(DataType dt, const NeonImmediate& neon_imm) {
196   if (neon_imm.IsInteger()) {
197     switch (dt.GetValue()) {
198       case I8:
199         if (neon_imm.CanConvert<uint8_t>()) {
200           SetEncodingValue(0xe);
201           SetEncodedImmediate(neon_imm.GetImmediate<uint8_t>());
202         }
203         break;
204       case I16:
205         if (neon_imm.IsInteger32()) {
206           uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
207           if ((immediate & ~0xff) == 0) {
208             SetEncodingValue(0x8);
209             SetEncodedImmediate(immediate);
210           } else if ((immediate & ~0xff00) == 0) {
211             SetEncodingValue(0xa);
212             SetEncodedImmediate(immediate >> 8);
213           }
214         }
215         break;
216       case I32:
217         if (neon_imm.IsInteger32()) {
218           uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
219           if ((immediate & ~0xff) == 0) {
220             SetEncodingValue(0x0);
221             SetEncodedImmediate(immediate);
222           } else if ((immediate & ~0xff00) == 0) {
223             SetEncodingValue(0x2);
224             SetEncodedImmediate(immediate >> 8);
225           } else if ((immediate & ~0xff0000) == 0) {
226             SetEncodingValue(0x4);
227             SetEncodedImmediate(immediate >> 16);
228           } else if ((immediate & ~0xff000000) == 0) {
229             SetEncodingValue(0x6);
230             SetEncodedImmediate(immediate >> 24);
231           } else if ((immediate & ~0xff00) == 0xff) {
232             SetEncodingValue(0xc);
233             SetEncodedImmediate(immediate >> 8);
234           } else if ((immediate & ~0xff0000) == 0xffff) {
235             SetEncodingValue(0xd);
236             SetEncodedImmediate(immediate >> 16);
237           }
238         }
239         break;
240       case I64: {
241         bool is_valid = true;
242         uint32_t encoding = 0;
243         if (neon_imm.IsInteger32()) {
244           uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
245           uint32_t mask = 0xff000000;
246           for (uint32_t set_bit = 1 << 3; set_bit != 0; set_bit >>= 1) {
247             if ((immediate & mask) == mask) {
248               encoding |= set_bit;
249             } else if ((immediate & mask) != 0) {
250               is_valid = false;
251               break;
252             }
253             mask >>= 8;
254           }
255         } else {
256           uint64_t immediate = neon_imm.GetImmediate<uint64_t>();
257           uint64_t mask = UINT64_C(0xff) << 56;
258           for (uint32_t set_bit = 1 << 7; set_bit != 0; set_bit >>= 1) {
259             if ((immediate & mask) == mask) {
260               encoding |= set_bit;
261             } else if ((immediate & mask) != 0) {
262               is_valid = false;
263               break;
264             }
265             mask >>= 8;
266           }
267         }
268         if (is_valid) {
269           SetEncodingValue(0x1e);
270           SetEncodedImmediate(encoding);
271         }
272         break;
273       }
274       default:
275         break;
276     }
277   } else {
278     switch (dt.GetValue()) {
279       case F32:
280         if (neon_imm.IsFloat() || neon_imm.IsDouble()) {
281           ImmediateVFP vfp(neon_imm.GetImmediate<float>());
282           if (vfp.IsValid()) {
283             SetEncodingValue(0xf);
284             SetEncodedImmediate(vfp.GetEncodingValue());
285           }
286         }
287         break;
288       default:
289         break;
290     }
291   }
292 }
293 
294 
DecodeDt(uint32_t cmode)295 DataType ImmediateVmov::DecodeDt(uint32_t cmode) {
296   switch (cmode & 0xf) {
297     case 0x0:
298     case 0x2:
299     case 0x4:
300     case 0x6:
301     case 0xc:
302     case 0xd:
303       return I32;
304     case 0x8:
305     case 0xa:
306       return I16;
307     case 0xe:
308       return ((cmode & 0x10) == 0) ? I8 : I64;
309     case 0xf:
310       if ((cmode & 0x10) == 0) return F32;
311       break;
312     default:
313       break;
314   }
315   VIXL_UNREACHABLE();
316   return kDataTypeValueInvalid;
317 }
318 
319 
DecodeImmediate(uint32_t cmode,uint32_t immediate)320 NeonImmediate ImmediateVmov::DecodeImmediate(uint32_t cmode,
321                                              uint32_t immediate) {
322   switch (cmode & 0xf) {
323     case 0x8:
324     case 0x0:
325       return immediate;
326     case 0x2:
327     case 0xa:
328       return immediate << 8;
329     case 0x4:
330       return immediate << 16;
331     case 0x6:
332       return immediate << 24;
333     case 0xc:
334       return (immediate << 8) | 0xff;
335     case 0xd:
336       return (immediate << 16) | 0xffff;
337     case 0xe: {
338       if (cmode == 0x1e) {
339         uint64_t encoding = 0;
340         for (uint32_t set_bit = 1 << 7; set_bit != 0; set_bit >>= 1) {
341           encoding <<= 8;
342           if ((immediate & set_bit) != 0) {
343             encoding |= 0xff;
344           }
345         }
346         return encoding;
347       } else {
348         return immediate;
349       }
350     }
351     case 0xf: {
352       return ImmediateVFP::Decode<float>(immediate);
353     }
354     default:
355       break;
356   }
357   VIXL_UNREACHABLE();
358   return 0;
359 }
360 
361 
ImmediateVmvn(DataType dt,const NeonImmediate & neon_imm)362 ImmediateVmvn::ImmediateVmvn(DataType dt, const NeonImmediate& neon_imm) {
363   if (neon_imm.IsInteger32()) {
364     uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
365     switch (dt.GetValue()) {
366       case I16:
367         if ((immediate & ~0xff) == 0) {
368           SetEncodingValue(0x8);
369           SetEncodedImmediate(immediate);
370         } else if ((immediate & ~0xff00) == 0) {
371           SetEncodingValue(0xa);
372           SetEncodedImmediate(immediate >> 8);
373         }
374         break;
375       case I32:
376         if ((immediate & ~0xff) == 0) {
377           SetEncodingValue(0x0);
378           SetEncodedImmediate(immediate);
379         } else if ((immediate & ~0xff00) == 0) {
380           SetEncodingValue(0x2);
381           SetEncodedImmediate(immediate >> 8);
382         } else if ((immediate & ~0xff0000) == 0) {
383           SetEncodingValue(0x4);
384           SetEncodedImmediate(immediate >> 16);
385         } else if ((immediate & ~0xff000000) == 0) {
386           SetEncodingValue(0x6);
387           SetEncodedImmediate(immediate >> 24);
388         } else if ((immediate & ~0xff00) == 0xff) {
389           SetEncodingValue(0xc);
390           SetEncodedImmediate(immediate >> 8);
391         } else if ((immediate & ~0xff0000) == 0xffff) {
392           SetEncodingValue(0xd);
393           SetEncodedImmediate(immediate >> 16);
394         }
395         break;
396       default:
397         break;
398     }
399   }
400 }
401 
402 
DecodeDt(uint32_t cmode)403 DataType ImmediateVmvn::DecodeDt(uint32_t cmode) {
404   switch (cmode) {
405     case 0x0:
406     case 0x2:
407     case 0x4:
408     case 0x6:
409     case 0xc:
410     case 0xd:
411       return I32;
412     case 0x8:
413     case 0xa:
414       return I16;
415     default:
416       break;
417   }
418   VIXL_UNREACHABLE();
419   return kDataTypeValueInvalid;
420 }
421 
422 
DecodeImmediate(uint32_t cmode,uint32_t immediate)423 NeonImmediate ImmediateVmvn::DecodeImmediate(uint32_t cmode,
424                                              uint32_t immediate) {
425   switch (cmode) {
426     case 0x0:
427     case 0x8:
428       return immediate;
429     case 0x2:
430     case 0xa:
431       return immediate << 8;
432     case 0x4:
433       return immediate << 16;
434     case 0x6:
435       return immediate << 24;
436     case 0xc:
437       return (immediate << 8) | 0xff;
438     case 0xd:
439       return (immediate << 16) | 0xffff;
440     default:
441       break;
442   }
443   VIXL_UNREACHABLE();
444   return 0;
445 }
446 
447 
ImmediateVorr(DataType dt,const NeonImmediate & neon_imm)448 ImmediateVorr::ImmediateVorr(DataType dt, const NeonImmediate& neon_imm) {
449   if (neon_imm.IsInteger32()) {
450     uint32_t immediate = neon_imm.GetImmediate<uint32_t>();
451     if (dt.GetValue() == I16) {
452       if ((immediate & ~0xff) == 0) {
453         SetEncodingValue(0x9);
454         SetEncodedImmediate(immediate);
455       } else if ((immediate & ~0xff00) == 0) {
456         SetEncodingValue(0xb);
457         SetEncodedImmediate(immediate >> 8);
458       }
459     } else if (dt.GetValue() == I32) {
460       if ((immediate & ~0xff) == 0) {
461         SetEncodingValue(0x1);
462         SetEncodedImmediate(immediate);
463       } else if ((immediate & ~0xff00) == 0) {
464         SetEncodingValue(0x3);
465         SetEncodedImmediate(immediate >> 8);
466       } else if ((immediate & ~0xff0000) == 0) {
467         SetEncodingValue(0x5);
468         SetEncodedImmediate(immediate >> 16);
469       } else if ((immediate & ~0xff000000) == 0) {
470         SetEncodingValue(0x7);
471         SetEncodedImmediate(immediate >> 24);
472       }
473     }
474   }
475 }
476 
477 
DecodeDt(uint32_t cmode)478 DataType ImmediateVorr::DecodeDt(uint32_t cmode) {
479   switch (cmode) {
480     case 0x1:
481     case 0x3:
482     case 0x5:
483     case 0x7:
484       return I32;
485     case 0x9:
486     case 0xb:
487       return I16;
488     default:
489       break;
490   }
491   VIXL_UNREACHABLE();
492   return kDataTypeValueInvalid;
493 }
494 
495 
DecodeImmediate(uint32_t cmode,uint32_t immediate)496 NeonImmediate ImmediateVorr::DecodeImmediate(uint32_t cmode,
497                                              uint32_t immediate) {
498   switch (cmode) {
499     case 0x1:
500     case 0x9:
501       return immediate;
502     case 0x3:
503     case 0xb:
504       return immediate << 8;
505     case 0x5:
506       return immediate << 16;
507     case 0x7:
508       return immediate << 24;
509     default:
510       break;
511   }
512   VIXL_UNREACHABLE();
513   return 0;
514 }
515 
516 // MemOperand
517 
operator <<(std::ostream & os,const MemOperand & operand)518 std::ostream& operator<<(std::ostream& os, const MemOperand& operand) {
519   os << "[" << operand.GetBaseRegister();
520   if (operand.GetAddrMode() == PostIndex) {
521     os << "]";
522     if (operand.IsRegisterOnly()) return os << "!";
523   }
524   if (operand.IsImmediate()) {
525     if ((operand.GetOffsetImmediate() != 0) || operand.GetSign().IsMinus() ||
526         ((operand.GetAddrMode() != Offset) && !operand.IsRegisterOnly())) {
527       if (operand.GetOffsetImmediate() == 0) {
528         os << ", #" << operand.GetSign() << operand.GetOffsetImmediate();
529       } else {
530         os << ", #" << operand.GetOffsetImmediate();
531       }
532     }
533   } else if (operand.IsPlainRegister()) {
534     os << ", " << operand.GetSign() << operand.GetOffsetRegister();
535   } else if (operand.IsShiftedRegister()) {
536     os << ", " << operand.GetSign() << operand.GetOffsetRegister()
537        << ImmediateShiftOperand(operand.GetShift(), operand.GetShiftAmount());
538   } else {
539     VIXL_UNREACHABLE();
540     return os;
541   }
542   if (operand.GetAddrMode() == Offset) {
543     os << "]";
544   } else if (operand.GetAddrMode() == PreIndex) {
545     os << "]!";
546   }
547   return os;
548 }
549 
operator <<(std::ostream & os,const AlignedMemOperand & operand)550 std::ostream& operator<<(std::ostream& os, const AlignedMemOperand& operand) {
551   os << "[" << operand.GetBaseRegister() << operand.GetAlignment() << "]";
552   if (operand.GetAddrMode() == PostIndex) {
553     if (operand.IsPlainRegister()) {
554       os << ", " << operand.GetOffsetRegister();
555     } else {
556       os << "!";
557     }
558   }
559   return os;
560 }
561 
562 }  // namespace aarch32
563 }  // namespace vixl
564