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