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