1 // Copyright 2014, 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 notice,
10 // this list of conditions and the following disclaimer in the documentation
11 // and/or other materials provided with the distribution.
12 // * Neither the name of ARM Limited nor the names of its contributors may be
13 // used to endorse or promote products derived from this software without
14 // 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 IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 #include "../globals-vixl.h"
28 #include "../utils-vixl.h"
29
30 #include "decoder-aarch64.h"
31
32 namespace vixl {
33 namespace aarch64 {
34
DecodeInstruction(const Instruction * instr)35 void Decoder::DecodeInstruction(const Instruction* instr) {
36 if (instr->ExtractBits(28, 27) == 0) {
37 VisitUnallocated(instr);
38 } else {
39 switch (instr->ExtractBits(27, 24)) {
40 // 0: PC relative addressing.
41 case 0x0:
42 DecodePCRelAddressing(instr);
43 break;
44
45 // 1: Add/sub immediate.
46 case 0x1:
47 DecodeAddSubImmediate(instr);
48 break;
49
50 // A: Logical shifted register.
51 // Add/sub with carry.
52 // Conditional compare register.
53 // Conditional compare immediate.
54 // Conditional select.
55 // Data processing 1 source.
56 // Data processing 2 source.
57 // B: Add/sub shifted register.
58 // Add/sub extended register.
59 // Data processing 3 source.
60 case 0xA:
61 case 0xB:
62 DecodeDataProcessing(instr);
63 break;
64
65 // 2: Logical immediate.
66 // Move wide immediate.
67 case 0x2:
68 DecodeLogical(instr);
69 break;
70
71 // 3: Bitfield.
72 // Extract.
73 case 0x3:
74 DecodeBitfieldExtract(instr);
75 break;
76
77 // 4: Unconditional branch immediate.
78 // Exception generation.
79 // Compare and branch immediate.
80 // 5: Compare and branch immediate.
81 // Conditional branch.
82 // System.
83 // 6,7: Unconditional branch.
84 // Test and branch immediate.
85 case 0x4:
86 case 0x5:
87 case 0x6:
88 case 0x7:
89 DecodeBranchSystemException(instr);
90 break;
91
92 // 8,9: Load/store register pair post-index.
93 // Load register literal.
94 // Load/store register unscaled immediate.
95 // Load/store register immediate post-index.
96 // Load/store register immediate pre-index.
97 // Load/store register offset.
98 // Load/store exclusive.
99 // C,D: Load/store register pair offset.
100 // Load/store register pair pre-index.
101 // Load/store register unsigned immediate.
102 // Advanced SIMD.
103 case 0x8:
104 case 0x9:
105 case 0xC:
106 case 0xD:
107 DecodeLoadStore(instr);
108 break;
109
110 // E: FP fixed point conversion.
111 // FP integer conversion.
112 // FP data processing 1 source.
113 // FP compare.
114 // FP immediate.
115 // FP data processing 2 source.
116 // FP conditional compare.
117 // FP conditional select.
118 // Advanced SIMD.
119 // F: FP data processing 3 source.
120 // Advanced SIMD.
121 case 0xE:
122 case 0xF:
123 DecodeFP(instr);
124 break;
125 }
126 }
127 }
128
AppendVisitor(DecoderVisitor * new_visitor)129 void Decoder::AppendVisitor(DecoderVisitor* new_visitor) {
130 visitors_.push_back(new_visitor);
131 }
132
133
PrependVisitor(DecoderVisitor * new_visitor)134 void Decoder::PrependVisitor(DecoderVisitor* new_visitor) {
135 visitors_.push_front(new_visitor);
136 }
137
138
InsertVisitorBefore(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)139 void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
140 DecoderVisitor* registered_visitor) {
141 std::list<DecoderVisitor*>::iterator it;
142 for (it = visitors_.begin(); it != visitors_.end(); it++) {
143 if (*it == registered_visitor) {
144 visitors_.insert(it, new_visitor);
145 return;
146 }
147 }
148 // We reached the end of the list. The last element must be
149 // registered_visitor.
150 VIXL_ASSERT(*it == registered_visitor);
151 visitors_.insert(it, new_visitor);
152 }
153
154
InsertVisitorAfter(DecoderVisitor * new_visitor,DecoderVisitor * registered_visitor)155 void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
156 DecoderVisitor* registered_visitor) {
157 std::list<DecoderVisitor*>::iterator it;
158 for (it = visitors_.begin(); it != visitors_.end(); it++) {
159 if (*it == registered_visitor) {
160 it++;
161 visitors_.insert(it, new_visitor);
162 return;
163 }
164 }
165 // We reached the end of the list. The last element must be
166 // registered_visitor.
167 VIXL_ASSERT(*it == registered_visitor);
168 visitors_.push_back(new_visitor);
169 }
170
171
RemoveVisitor(DecoderVisitor * visitor)172 void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
173 visitors_.remove(visitor);
174 }
175
176
DecodePCRelAddressing(const Instruction * instr)177 void Decoder::DecodePCRelAddressing(const Instruction* instr) {
178 VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x0);
179 // We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
180 // decode.
181 VIXL_ASSERT(instr->ExtractBit(28) == 0x1);
182 VisitPCRelAddressing(instr);
183 }
184
185
DecodeBranchSystemException(const Instruction * instr)186 void Decoder::DecodeBranchSystemException(const Instruction* instr) {
187 VIXL_ASSERT((instr->ExtractBits(27, 24) == 0x4) ||
188 (instr->ExtractBits(27, 24) == 0x5) ||
189 (instr->ExtractBits(27, 24) == 0x6) ||
190 (instr->ExtractBits(27, 24) == 0x7));
191
192 switch (instr->ExtractBits(31, 29)) {
193 case 0:
194 case 4: {
195 VisitUnconditionalBranch(instr);
196 break;
197 }
198 case 1:
199 case 5: {
200 if (instr->ExtractBit(25) == 0) {
201 VisitCompareBranch(instr);
202 } else {
203 VisitTestBranch(instr);
204 }
205 break;
206 }
207 case 2: {
208 if (instr->ExtractBit(25) == 0) {
209 if ((instr->ExtractBit(24) == 0x1) ||
210 (instr->Mask(0x01000010) == 0x00000010)) {
211 VisitUnallocated(instr);
212 } else {
213 VisitConditionalBranch(instr);
214 }
215 } else {
216 VisitUnallocated(instr);
217 }
218 break;
219 }
220 case 6: {
221 if (instr->ExtractBit(25) == 0) {
222 if (instr->ExtractBit(24) == 0) {
223 if ((instr->ExtractBits(4, 2) != 0) ||
224 (instr->Mask(0x00E0001D) == 0x00200001) ||
225 (instr->Mask(0x00E0001D) == 0x00400001) ||
226 (instr->Mask(0x00E0001E) == 0x00200002) ||
227 (instr->Mask(0x00E0001E) == 0x00400002) ||
228 (instr->Mask(0x00E0001C) == 0x00600000) ||
229 (instr->Mask(0x00E0001C) == 0x00800000) ||
230 (instr->Mask(0x00E0001F) == 0x00A00000) ||
231 (instr->Mask(0x00C0001C) == 0x00C00000)) {
232 VisitUnallocated(instr);
233 } else {
234 VisitException(instr);
235 }
236 } else {
237 if (instr->ExtractBits(23, 22) == 0) {
238 const Instr masked_003FF0E0 = instr->Mask(0x003FF0E0);
239 if ((instr->ExtractBits(21, 19) == 0x4) ||
240 (masked_003FF0E0 == 0x00033000) ||
241 (masked_003FF0E0 == 0x003FF020) ||
242 (masked_003FF0E0 == 0x003FF060) ||
243 (masked_003FF0E0 == 0x003FF0E0) ||
244 (instr->Mask(0x00388000) == 0x00008000) ||
245 (instr->Mask(0x0038E000) == 0x00000000) ||
246 (instr->Mask(0x0039E000) == 0x00002000) ||
247 (instr->Mask(0x003AE000) == 0x00002000) ||
248 (instr->Mask(0x003CE000) == 0x00042000) ||
249 (instr->Mask(0x0038F000) == 0x00005000) ||
250 (instr->Mask(0x0038E000) == 0x00006000)) {
251 VisitUnallocated(instr);
252 } else {
253 VisitSystem(instr);
254 }
255 } else {
256 VisitUnallocated(instr);
257 }
258 }
259 } else {
260 if (((instr->ExtractBit(24) == 0x1) &&
261 (instr->ExtractBits(23, 21) > 0x1)) ||
262 (instr->ExtractBits(20, 16) != 0x1F) ||
263 (instr->ExtractBits(15, 10) == 0x1) ||
264 (instr->ExtractBits(15, 10) > 0x3) ||
265 (instr->ExtractBits(24, 21) == 0x3) ||
266 (instr->ExtractBits(24, 22) == 0x3)) {
267 VisitUnallocated(instr);
268 } else {
269 VisitUnconditionalBranchToRegister(instr);
270 }
271 }
272 break;
273 }
274 case 3:
275 case 7: {
276 VisitUnallocated(instr);
277 break;
278 }
279 }
280 }
281
282
DecodeLoadStore(const Instruction * instr)283 void Decoder::DecodeLoadStore(const Instruction* instr) {
284 VIXL_ASSERT((instr->ExtractBits(27, 24) == 0x8) ||
285 (instr->ExtractBits(27, 24) == 0x9) ||
286 (instr->ExtractBits(27, 24) == 0xC) ||
287 (instr->ExtractBits(27, 24) == 0xD));
288 // TODO(all): rearrange the tree to integrate this branch.
289 if ((instr->ExtractBit(28) == 0) && (instr->ExtractBit(29) == 0) &&
290 (instr->ExtractBit(26) == 1)) {
291 DecodeNEONLoadStore(instr);
292 return;
293 }
294
295 if (instr->ExtractBit(24) == 0) {
296 if (instr->ExtractBit(28) == 0) {
297 if (instr->ExtractBit(29) == 0) {
298 if (instr->ExtractBit(26) == 0) {
299 VisitLoadStoreExclusive(instr);
300 } else {
301 VIXL_UNREACHABLE();
302 }
303 } else {
304 if ((instr->ExtractBits(31, 30) == 0x3) ||
305 (instr->Mask(0xC4400000) == 0x40000000)) {
306 VisitUnallocated(instr);
307 } else {
308 if (instr->ExtractBit(23) == 0) {
309 if (instr->Mask(0xC4400000) == 0xC0400000) {
310 VisitUnallocated(instr);
311 } else {
312 VisitLoadStorePairNonTemporal(instr);
313 }
314 } else {
315 VisitLoadStorePairPostIndex(instr);
316 }
317 }
318 }
319 } else {
320 if (instr->ExtractBit(29) == 0) {
321 if (instr->Mask(0xC4000000) == 0xC4000000) {
322 VisitUnallocated(instr);
323 } else {
324 VisitLoadLiteral(instr);
325 }
326 } else {
327 if ((instr->Mask(0x44800000) == 0x44800000) ||
328 (instr->Mask(0x84800000) == 0x84800000)) {
329 VisitUnallocated(instr);
330 } else {
331 if (instr->ExtractBit(21) == 0) {
332 switch (instr->ExtractBits(11, 10)) {
333 case 0: {
334 VisitLoadStoreUnscaledOffset(instr);
335 break;
336 }
337 case 1: {
338 if (instr->Mask(0xC4C00000) == 0xC0800000) {
339 VisitUnallocated(instr);
340 } else {
341 VisitLoadStorePostIndex(instr);
342 }
343 break;
344 }
345 case 2: {
346 // TODO: VisitLoadStoreRegisterOffsetUnpriv.
347 VisitUnimplemented(instr);
348 break;
349 }
350 case 3: {
351 if (instr->Mask(0xC4C00000) == 0xC0800000) {
352 VisitUnallocated(instr);
353 } else {
354 VisitLoadStorePreIndex(instr);
355 }
356 break;
357 }
358 }
359 } else {
360 if (instr->ExtractBits(11, 10) == 0x2) {
361 if (instr->ExtractBit(14) == 0) {
362 VisitUnallocated(instr);
363 } else {
364 VisitLoadStoreRegisterOffset(instr);
365 }
366 } else {
367 if (instr->ExtractBits(11, 10) == 0x0) {
368 if (instr->ExtractBit(25) == 0) {
369 if (instr->ExtractBit(26) == 0) {
370 if ((instr->ExtractBit(15) == 1) &&
371 ((instr->ExtractBits(14, 12) == 0x1) ||
372 (instr->ExtractBit(13) == 1) ||
373 (instr->ExtractBits(14, 12) == 0x5) ||
374 ((instr->ExtractBits(14, 12) == 0x4) &&
375 ((instr->ExtractBit(23) == 0) ||
376 (instr->ExtractBits(23, 22) == 0x3))))) {
377 VisitUnallocated(instr);
378 } else {
379 VisitAtomicMemory(instr);
380 }
381 } else {
382 VisitUnallocated(instr);
383 }
384 } else {
385 VisitUnallocated(instr);
386 }
387 } else {
388 VisitUnallocated(instr);
389 }
390 }
391 }
392 }
393 }
394 }
395 } else {
396 if (instr->ExtractBit(28) == 0) {
397 if (instr->ExtractBit(29) == 0) {
398 VisitUnallocated(instr);
399 } else {
400 if ((instr->ExtractBits(31, 30) == 0x3) ||
401 (instr->Mask(0xC4400000) == 0x40000000)) {
402 VisitUnallocated(instr);
403 } else {
404 if (instr->ExtractBit(23) == 0) {
405 VisitLoadStorePairOffset(instr);
406 } else {
407 VisitLoadStorePairPreIndex(instr);
408 }
409 }
410 }
411 } else {
412 if (instr->ExtractBit(29) == 0) {
413 VisitUnallocated(instr);
414 } else {
415 if ((instr->Mask(0x84C00000) == 0x80C00000) ||
416 (instr->Mask(0x44800000) == 0x44800000) ||
417 (instr->Mask(0x84800000) == 0x84800000)) {
418 VisitUnallocated(instr);
419 } else {
420 VisitLoadStoreUnsignedOffset(instr);
421 }
422 }
423 }
424 }
425 }
426
427
DecodeLogical(const Instruction * instr)428 void Decoder::DecodeLogical(const Instruction* instr) {
429 VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x2);
430
431 if (instr->Mask(0x80400000) == 0x00400000) {
432 VisitUnallocated(instr);
433 } else {
434 if (instr->ExtractBit(23) == 0) {
435 VisitLogicalImmediate(instr);
436 } else {
437 if (instr->ExtractBits(30, 29) == 0x1) {
438 VisitUnallocated(instr);
439 } else {
440 VisitMoveWideImmediate(instr);
441 }
442 }
443 }
444 }
445
446
DecodeBitfieldExtract(const Instruction * instr)447 void Decoder::DecodeBitfieldExtract(const Instruction* instr) {
448 VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x3);
449
450 if ((instr->Mask(0x80400000) == 0x80000000) ||
451 (instr->Mask(0x80400000) == 0x00400000) ||
452 (instr->Mask(0x80008000) == 0x00008000)) {
453 VisitUnallocated(instr);
454 } else if (instr->ExtractBit(23) == 0) {
455 if ((instr->Mask(0x80200000) == 0x00200000) ||
456 (instr->Mask(0x60000000) == 0x60000000)) {
457 VisitUnallocated(instr);
458 } else {
459 VisitBitfield(instr);
460 }
461 } else {
462 if ((instr->Mask(0x60200000) == 0x00200000) ||
463 (instr->Mask(0x60000000) != 0x00000000)) {
464 VisitUnallocated(instr);
465 } else {
466 VisitExtract(instr);
467 }
468 }
469 }
470
471
DecodeAddSubImmediate(const Instruction * instr)472 void Decoder::DecodeAddSubImmediate(const Instruction* instr) {
473 VIXL_ASSERT(instr->ExtractBits(27, 24) == 0x1);
474 if (instr->ExtractBit(23) == 1) {
475 VisitUnallocated(instr);
476 } else {
477 VisitAddSubImmediate(instr);
478 }
479 }
480
481
DecodeDataProcessing(const Instruction * instr)482 void Decoder::DecodeDataProcessing(const Instruction* instr) {
483 VIXL_ASSERT((instr->ExtractBits(27, 24) == 0xA) ||
484 (instr->ExtractBits(27, 24) == 0xB));
485
486 if (instr->ExtractBit(24) == 0) {
487 if (instr->ExtractBit(28) == 0) {
488 if (instr->Mask(0x80008000) == 0x00008000) {
489 VisitUnallocated(instr);
490 } else {
491 VisitLogicalShifted(instr);
492 }
493 } else {
494 switch (instr->ExtractBits(23, 21)) {
495 case 0: {
496 if (instr->Mask(0x0000FC00) != 0) {
497 VisitUnallocated(instr);
498 } else {
499 VisitAddSubWithCarry(instr);
500 }
501 break;
502 }
503 case 2: {
504 if ((instr->ExtractBit(29) == 0) || (instr->Mask(0x00000410) != 0)) {
505 VisitUnallocated(instr);
506 } else {
507 if (instr->ExtractBit(11) == 0) {
508 VisitConditionalCompareRegister(instr);
509 } else {
510 VisitConditionalCompareImmediate(instr);
511 }
512 }
513 break;
514 }
515 case 4: {
516 if (instr->Mask(0x20000800) != 0x00000000) {
517 VisitUnallocated(instr);
518 } else {
519 VisitConditionalSelect(instr);
520 }
521 break;
522 }
523 case 6: {
524 if (instr->ExtractBit(29) == 0x1) {
525 VisitUnallocated(instr);
526 VIXL_FALLTHROUGH();
527 } else {
528 if (instr->ExtractBit(30) == 0) {
529 if ((instr->ExtractBit(15) == 0x1) ||
530 (instr->ExtractBits(15, 11) == 0) ||
531 (instr->ExtractBits(15, 12) == 0x1) ||
532 ((instr->ExtractBits(15, 12) == 0x3) &&
533 (instr->ExtractBit(31) == 0)) ||
534 (instr->ExtractBits(15, 13) == 0x3) ||
535 (instr->Mask(0x8000EC00) == 0x00004C00) ||
536 (instr->Mask(0x8000E800) == 0x80004000) ||
537 (instr->Mask(0x8000E400) == 0x80004000)) {
538 VisitUnallocated(instr);
539 } else {
540 VisitDataProcessing2Source(instr);
541 }
542 } else {
543 if ((instr->ExtractBits(20, 17) != 0) ||
544 (instr->ExtractBit(15) == 1) ||
545 ((instr->ExtractBit(16) == 1) &&
546 ((instr->ExtractBits(14, 10) > 17) ||
547 (instr->ExtractBit(31) == 0))) ||
548 ((instr->ExtractBit(16) == 0) &&
549 ((instr->ExtractBits(14, 13) != 0) ||
550 (instr->Mask(0xA01FFC00) == 0x00000C00) ||
551 (instr->Mask(0x201FF800) == 0x00001800)))) {
552 VisitUnallocated(instr);
553 } else {
554 VisitDataProcessing1Source(instr);
555 }
556 }
557 break;
558 }
559 }
560 case 1:
561 case 3:
562 case 5:
563 case 7:
564 VisitUnallocated(instr);
565 break;
566 }
567 }
568 } else {
569 if (instr->ExtractBit(28) == 0) {
570 if (instr->ExtractBit(21) == 0) {
571 if ((instr->ExtractBits(23, 22) == 0x3) ||
572 (instr->Mask(0x80008000) == 0x00008000)) {
573 VisitUnallocated(instr);
574 } else {
575 VisitAddSubShifted(instr);
576 }
577 } else {
578 if ((instr->Mask(0x00C00000) != 0x00000000) ||
579 (instr->Mask(0x00001400) == 0x00001400) ||
580 (instr->Mask(0x00001800) == 0x00001800)) {
581 VisitUnallocated(instr);
582 } else {
583 VisitAddSubExtended(instr);
584 }
585 }
586 } else {
587 if ((instr->ExtractBit(30) == 0x1) ||
588 (instr->ExtractBits(30, 29) == 0x1) ||
589 (instr->Mask(0xE0600000) == 0x00200000) ||
590 (instr->Mask(0xE0608000) == 0x00400000) ||
591 (instr->Mask(0x60608000) == 0x00408000) ||
592 (instr->Mask(0x60E00000) == 0x00E00000) ||
593 (instr->Mask(0x60E00000) == 0x00800000) ||
594 (instr->Mask(0x60E00000) == 0x00600000)) {
595 VisitUnallocated(instr);
596 } else {
597 VisitDataProcessing3Source(instr);
598 }
599 }
600 }
601 }
602
603
DecodeFP(const Instruction * instr)604 void Decoder::DecodeFP(const Instruction* instr) {
605 VIXL_ASSERT((instr->ExtractBits(27, 24) == 0xE) ||
606 (instr->ExtractBits(27, 24) == 0xF));
607 if (instr->ExtractBit(28) == 0) {
608 DecodeNEONVectorDataProcessing(instr);
609 } else {
610 if (instr->ExtractBits(31, 30) == 0x3) {
611 VisitUnallocated(instr);
612 } else if (instr->ExtractBits(31, 30) == 0x1) {
613 DecodeNEONScalarDataProcessing(instr);
614 } else {
615 if (instr->ExtractBit(29) == 0) {
616 if (instr->ExtractBit(24) == 0) {
617 if (instr->ExtractBit(21) == 0) {
618 if ((instr->ExtractBits(23, 22) == 0x2) ||
619 (instr->ExtractBit(18) == 1) ||
620 (instr->Mask(0x80008000) == 0x00000000) ||
621 (instr->Mask(0x000E0000) == 0x00000000) ||
622 (instr->Mask(0x000E0000) == 0x000A0000) ||
623 (instr->Mask(0x00160000) == 0x00000000) ||
624 (instr->Mask(0x00160000) == 0x00120000)) {
625 VisitUnallocated(instr);
626 } else {
627 VisitFPFixedPointConvert(instr);
628 }
629 } else {
630 if (instr->ExtractBits(15, 10) == 32) {
631 VisitUnallocated(instr);
632 } else if (instr->ExtractBits(15, 10) == 0) {
633 if ((instr->Mask(0x000E0000) == 0x000A0000) ||
634 (instr->Mask(0x000E0000) == 0x000C0000) ||
635 (instr->Mask(0x00160000) == 0x00120000) ||
636 (instr->Mask(0x00160000) == 0x00140000) ||
637 (instr->Mask(0x20C40000) == 0x00800000) ||
638 (instr->Mask(0x20C60000) == 0x00840000) ||
639 (instr->Mask(0xA0C60000) == 0x80060000) ||
640 (instr->Mask(0xA0C60000) == 0x00860000) ||
641 (instr->Mask(0xA0CE0000) == 0x80860000) ||
642 (instr->Mask(0xA0CE0000) == 0x804E0000) ||
643 (instr->Mask(0xA0CE0000) == 0x000E0000) ||
644 (instr->Mask(0xA0D60000) == 0x00160000) ||
645 (instr->Mask(0xA0D60000) == 0x80560000) ||
646 (instr->Mask(0xA0D60000) == 0x80960000)) {
647 VisitUnallocated(instr);
648 } else {
649 VisitFPIntegerConvert(instr);
650 }
651 } else if (instr->ExtractBits(14, 10) == 16) {
652 const Instr masked_A0DF8000 = instr->Mask(0xA0DF8000);
653 if ((instr->Mask(0x80180000) != 0) ||
654 (masked_A0DF8000 == 0x00020000) ||
655 (masked_A0DF8000 == 0x00030000) ||
656 (masked_A0DF8000 == 0x00068000) ||
657 (masked_A0DF8000 == 0x00428000) ||
658 (masked_A0DF8000 == 0x00430000) ||
659 (masked_A0DF8000 == 0x00468000) ||
660 (instr->Mask(0xA0D80000) == 0x00800000) ||
661 (instr->Mask(0xA0DF0000) == 0x00C30000) ||
662 (instr->Mask(0xA0DF8000) == 0x00C68000)) {
663 VisitUnallocated(instr);
664 } else {
665 VisitFPDataProcessing1Source(instr);
666 }
667 } else if (instr->ExtractBits(13, 10) == 8) {
668 if ((instr->ExtractBits(15, 14) != 0) ||
669 (instr->ExtractBits(2, 0) != 0) ||
670 (instr->ExtractBit(31) == 1) ||
671 (instr->ExtractBits(23, 22) == 0x2)) {
672 VisitUnallocated(instr);
673 } else {
674 VisitFPCompare(instr);
675 }
676 } else if (instr->ExtractBits(12, 10) == 4) {
677 if ((instr->ExtractBits(9, 5) != 0) ||
678 // Valid enc: 01d, 00s, 11h.
679 (instr->ExtractBits(23, 22) == 0x2) ||
680 (instr->ExtractBit(31) == 1)) {
681 VisitUnallocated(instr);
682 } else {
683 VisitFPImmediate(instr);
684 }
685 } else {
686 if ((instr->ExtractBits(23, 22) == 0x2) ||
687 (instr->ExtractBit(31) == 1)) {
688 VisitUnallocated(instr);
689 } else {
690 switch (instr->ExtractBits(11, 10)) {
691 case 1: {
692 VisitFPConditionalCompare(instr);
693 break;
694 }
695 case 2: {
696 if (instr->ExtractBits(15, 12) > 0x8) {
697 VisitUnallocated(instr);
698 } else {
699 VisitFPDataProcessing2Source(instr);
700 }
701 break;
702 }
703 case 3: {
704 VisitFPConditionalSelect(instr);
705 break;
706 }
707 default:
708 VIXL_UNREACHABLE();
709 }
710 }
711 }
712 }
713 } else {
714 // Bit 30 == 1 has been handled earlier.
715 VIXL_ASSERT(instr->ExtractBit(30) == 0);
716 if ((instr->Mask(0xA0000000) != 0) ||
717 (instr->ExtractBits(23, 22) == 0x2)) {
718 VisitUnallocated(instr);
719 } else {
720 VisitFPDataProcessing3Source(instr);
721 }
722 }
723 } else {
724 VisitUnallocated(instr);
725 }
726 }
727 }
728 }
729
730
DecodeNEONLoadStore(const Instruction * instr)731 void Decoder::DecodeNEONLoadStore(const Instruction* instr) {
732 VIXL_ASSERT(instr->ExtractBits(29, 25) == 0x6);
733 if (instr->ExtractBit(31) == 0) {
734 if ((instr->ExtractBit(24) == 0) && (instr->ExtractBit(21) == 1)) {
735 VisitUnallocated(instr);
736 return;
737 }
738
739 if (instr->ExtractBit(23) == 0) {
740 if (instr->ExtractBits(20, 16) == 0) {
741 if (instr->ExtractBit(24) == 0) {
742 VisitNEONLoadStoreMultiStruct(instr);
743 } else {
744 VisitNEONLoadStoreSingleStruct(instr);
745 }
746 } else {
747 VisitUnallocated(instr);
748 }
749 } else {
750 if (instr->ExtractBit(24) == 0) {
751 VisitNEONLoadStoreMultiStructPostIndex(instr);
752 } else {
753 VisitNEONLoadStoreSingleStructPostIndex(instr);
754 }
755 }
756 } else {
757 VisitUnallocated(instr);
758 }
759 }
760
761
DecodeNEONVectorDataProcessing(const Instruction * instr)762 void Decoder::DecodeNEONVectorDataProcessing(const Instruction* instr) {
763 VIXL_ASSERT(instr->ExtractBits(28, 25) == 0x7);
764 if (instr->ExtractBit(31) == 0) {
765 if (instr->ExtractBit(24) == 0) {
766 if (instr->ExtractBit(21) == 0) {
767 if (instr->ExtractBit(15) == 0) {
768 if (instr->ExtractBit(10) == 0) {
769 if (instr->ExtractBit(29) == 0) {
770 if (instr->ExtractBit(11) == 0) {
771 VisitNEONTable(instr);
772 } else {
773 VisitNEONPerm(instr);
774 }
775 } else {
776 VisitNEONExtract(instr);
777 }
778 } else {
779 if (instr->ExtractBits(23, 22) == 0) {
780 VisitNEONCopy(instr);
781 } else if (instr->ExtractBit(14) == 0x0 &&
782 instr->ExtractBit(22) == 0x1) {
783 // U + a + opcode.
784 uint8_t decode_field =
785 (instr->ExtractBit(29) << 1) | instr->ExtractBit(23);
786 decode_field = (decode_field << 3) | instr->ExtractBits(13, 11);
787 switch (decode_field) {
788 case 0x5:
789 case 0xB:
790 case 0xC:
791 case 0xD:
792 case 0x11:
793 case 0x19:
794 case 0x1B:
795 case 0x1F:
796 VisitUnallocated(instr);
797 break;
798 default:
799 VisitNEON3SameFP16(instr);
800 break;
801 }
802 } else {
803 VisitUnallocated(instr);
804 }
805 }
806 } else if (instr->ExtractBit(10) == 0) {
807 VisitUnallocated(instr);
808 } else if ((instr->ExtractBits(14, 11) == 0x3) ||
809 (instr->ExtractBits(14, 13) == 0x1)) {
810 // opcode = 0b0011
811 // opcode = 0b01xx
812 VisitUnallocated(instr);
813 } else if (instr->ExtractBit(29) == 0) {
814 // U == 0
815 if (instr->ExtractBits(14, 11) == 0x2) {
816 // opcode = 0b0010
817 VisitNEON3SameExtra(instr);
818 } else {
819 VisitUnallocated(instr);
820 }
821 } else {
822 // U == 1
823 if ((instr->ExtractBits(14, 11) == 0xd) ||
824 (instr->ExtractBits(14, 11) == 0xf)) {
825 // opcode = 0b11x1
826 VisitUnallocated(instr);
827 } else {
828 VisitNEON3SameExtra(instr);
829 }
830 }
831 } else {
832 if (instr->ExtractBit(10) == 0) {
833 if (instr->ExtractBit(11) == 0) {
834 VisitNEON3Different(instr);
835 } else {
836 if (instr->ExtractBits(18, 17) == 0) {
837 if (instr->ExtractBit(20) == 0) {
838 if (instr->ExtractBit(19) == 0) {
839 VisitNEON2RegMisc(instr);
840 } else {
841 if (instr->ExtractBits(30, 29) == 0x2) {
842 VisitCryptoAES(instr);
843 } else {
844 VisitUnallocated(instr);
845 }
846 }
847 } else {
848 if (instr->ExtractBit(19) == 0) {
849 VisitNEONAcrossLanes(instr);
850 } else {
851 if (instr->ExtractBit(22) == 0) {
852 VisitUnallocated(instr);
853 } else {
854 if ((instr->ExtractBits(16, 15) == 0x0) ||
855 (instr->ExtractBits(16, 14) == 0x2) ||
856 (instr->ExtractBits(16, 15) == 0x2) ||
857 (instr->ExtractBits(16, 12) == 0x1e) ||
858 ((instr->ExtractBit(23) == 0) &&
859 ((instr->ExtractBits(16, 14) == 0x3) ||
860 (instr->ExtractBits(16, 12) == 0x1f))) ||
861 ((instr->ExtractBit(23) == 1) &&
862 (instr->ExtractBits(16, 12) == 0x1c))) {
863 VisitUnallocated(instr);
864 } else {
865 VisitNEON2RegMiscFP16(instr);
866 }
867 }
868 }
869 }
870 } else {
871 VisitUnallocated(instr);
872 }
873 }
874 } else {
875 VisitNEON3Same(instr);
876 }
877 }
878 } else {
879 if (instr->ExtractBit(10) == 0) {
880 VisitNEONByIndexedElement(instr);
881 } else {
882 if (instr->ExtractBit(23) == 0) {
883 if (instr->ExtractBits(22, 19) == 0) {
884 VisitNEONModifiedImmediate(instr);
885 } else {
886 VisitNEONShiftImmediate(instr);
887 }
888 } else {
889 VisitUnallocated(instr);
890 }
891 }
892 }
893 } else {
894 VisitUnallocated(instr);
895 }
896 }
897
898
DecodeNEONScalarDataProcessing(const Instruction * instr)899 void Decoder::DecodeNEONScalarDataProcessing(const Instruction* instr) {
900 VIXL_ASSERT(instr->ExtractBits(28, 25) == 0xF);
901 if (instr->ExtractBit(24) == 0) {
902 if (instr->ExtractBit(21) == 0) {
903 if (instr->ExtractBit(15) == 0) {
904 if (instr->ExtractBit(10) == 0) {
905 if (instr->ExtractBit(29) == 0) {
906 if (instr->ExtractBit(11) == 0) {
907 VisitCrypto3RegSHA(instr);
908 } else {
909 VisitUnallocated(instr);
910 }
911 } else {
912 VisitUnallocated(instr);
913 }
914 } else {
915 if (instr->ExtractBits(23, 22) == 0) {
916 VisitNEONScalarCopy(instr);
917 } else {
918 if (instr->Mask(0x00404000) == 0x00400000) {
919 if ((instr->ExtractBits(13, 11) == 0x6) ||
920 (instr->ExtractBits(13, 11) < 2) ||
921 ((instr->Mask(0x20800000) == 0x00000000) &&
922 ((instr->ExtractBits(13, 11) < 0x3) ||
923 (instr->ExtractBits(13, 11) == 0x5))) ||
924 ((instr->Mask(0x20800000) == 0x00800000) &&
925 (instr->ExtractBits(13, 11) < 0x7)) ||
926 ((instr->Mask(0x20800000) == 0x20000000) &&
927 ((instr->ExtractBits(13, 11) < 0x4) ||
928 (instr->ExtractBits(13, 11) == 0x7))) ||
929 ((instr->Mask(0x20800000) == 0x20800000) &&
930 (instr->ExtractBits(12, 11) == 0x3))) {
931 VisitUnallocated(instr);
932 } else {
933 VisitNEONScalar3SameFP16(instr);
934 }
935 } else {
936 VisitUnallocated(instr);
937 }
938 }
939 }
940 } else {
941 if (instr->ExtractBit(29) == 0) {
942 VisitUnallocated(instr);
943 } else {
944 if (instr->ExtractBit(10) == 0) {
945 VisitUnallocated(instr);
946 } else {
947 VisitNEONScalar3SameExtra(instr);
948 }
949 }
950 }
951 } else {
952 if (instr->ExtractBit(10) == 0) {
953 if (instr->ExtractBit(11) == 0) {
954 VisitNEONScalar3Diff(instr);
955 } else {
956 if (instr->ExtractBits(18, 17) == 0) {
957 if (instr->ExtractBit(20) == 0) {
958 if (instr->ExtractBit(19) == 0) {
959 VisitNEONScalar2RegMisc(instr);
960 } else {
961 if (instr->ExtractBit(29) == 0) {
962 VisitCrypto2RegSHA(instr);
963 } else {
964 VisitUnallocated(instr);
965 }
966 }
967 } else {
968 if (instr->ExtractBit(19) == 0) {
969 VisitNEONScalarPairwise(instr);
970 } else {
971 if (instr->ExtractBit(22) == 0) {
972 VisitUnallocated(instr);
973 } else {
974 if ((instr->ExtractBits(16, 15) == 0x0) ||
975 (instr->ExtractBits(16, 14) == 0x2) ||
976 (instr->ExtractBits(16, 15) == 0x2) ||
977 (instr->ExtractBits(16, 13) == 0xc) ||
978 (instr->ExtractBits(16, 12) == 0x1e) ||
979 ((instr->ExtractBit(23) == 0) &&
980 ((instr->ExtractBits(16, 14) == 0x3) ||
981 (instr->ExtractBits(16, 12) == 0x1f))) ||
982 ((instr->ExtractBit(23) == 1) &&
983 ((instr->ExtractBits(16, 12) == 0xf) ||
984 (instr->ExtractBits(16, 12) == 0x1c) ||
985 ((instr->ExtractBit(29) == 1) &&
986 ((instr->ExtractBits(16, 12) == 0xe) ||
987 (instr->ExtractBits(16, 12) == 0x1f)))))) {
988 VisitUnallocated(instr);
989 } else {
990 VisitNEONScalar2RegMiscFP16(instr);
991 }
992 }
993 }
994 }
995 } else {
996 VisitUnallocated(instr);
997 }
998 }
999 } else {
1000 VisitNEONScalar3Same(instr);
1001 }
1002 }
1003 } else {
1004 if (instr->ExtractBit(10) == 0) {
1005 VisitNEONScalarByIndexedElement(instr);
1006 } else {
1007 if (instr->ExtractBit(23) == 0) {
1008 VisitNEONScalarShiftImmediate(instr);
1009 } else {
1010 VisitUnallocated(instr);
1011 }
1012 }
1013 }
1014 }
1015
1016
1017 #define DEFINE_VISITOR_CALLERS(A) \
1018 void Decoder::Visit##A(const Instruction* instr) { \
1019 VIXL_ASSERT(((A##FMask == 0) && (A##Fixed == 0)) || \
1020 (instr->Mask(A##FMask) == A##Fixed)); \
1021 std::list<DecoderVisitor*>::iterator it; \
1022 for (it = visitors_.begin(); it != visitors_.end(); it++) { \
1023 (*it)->Visit##A(instr); \
1024 } \
1025 }
1026 VISITOR_LIST(DEFINE_VISITOR_CALLERS)
1027 #undef DEFINE_VISITOR_CALLERS
1028 } // namespace aarch64
1029 } // namespace vixl
1030