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