]> git.saurik.com Git - apple/javascriptcore.git/blob - disassembler/ARMv7/ARMv7DOpcode.h
JavaScriptCore-1218.0.1.tar.gz
[apple/javascriptcore.git] / disassembler / ARMv7 / ARMv7DOpcode.h
1 /*
2 * Copyright (C) 2013 Apple Inc. 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. 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 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef ARMv7DOpcode_h
27 #define ARMv7DOpcode_h
28
29 #if USE(ARMV7_DISASSEMBLER)
30
31 #include <stdint.h>
32 #include <wtf/Assertions.h>
33
34 namespace JSC { namespace ARMv7Disassembler {
35
36 class ARMv7DOpcode {
37 public:
38 static void init();
39
40 ARMv7DOpcode()
41 : m_opcode(0)
42 , m_bufferOffset(0)
43 {
44 init();
45
46 for (unsigned i = 0; i < 4; i++)
47 m_ifThenConditions[i] = CondNone;
48
49 endITBlock();
50
51 m_formatBuffer[0] = '\0';
52 }
53
54 const char* disassemble(uint16_t*& currentPC);
55
56 protected:
57 const unsigned RegSP = 0xd;
58 const unsigned RegLR = 0xe;
59 const unsigned RegPC = 0xf;
60
61 void fetchOpcode(uint16_t*&);
62 bool is32BitInstruction() { return (m_opcode & 0xfffff800) > 0xe000; }
63 bool isFPInstruction() { return (m_opcode & 0xfc000e00) == 0xec000a00; }
64
65 static const char* const s_conditionNames[16];
66 static const char* const s_shiftNames[4];
67 static const char* const s_optionName[8];
68 static const char* const s_specialRegisterNames[3];
69
70 static const char* conditionName(unsigned condition) { return s_conditionNames[condition & 0xf]; }
71 static const char* shiftName(unsigned shiftValue) { return s_shiftNames[shiftValue & 0x3]; }
72
73 bool inITBlock() { return m_ITConditionIndex < m_ITBlocksize; }
74 bool startingITBlock() { return m_ITConditionIndex == m_ITBlocksize + 1; }
75
76 void startITBlock(unsigned, unsigned);
77 void saveITConditionAt(unsigned, unsigned);
78 void endITBlock()
79 {
80 m_currentITCondition = CondNone;
81 m_ITConditionIndex = 0;
82 m_ITBlocksize = 0;
83 }
84
85 void bufferPrintf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
86 void appendInstructionName(const char*, bool addS = false);
87
88 void appendInstructionNameNoITBlock(const char* instructionName)
89 {
90 bufferPrintf(" %-7.7s", instructionName);
91 }
92
93 void appendRegisterName(unsigned);
94 void appendRegisterList(unsigned);
95 void appendFPRegisterName(char, unsigned);
96
97 void appendSeparator()
98 {
99 bufferPrintf(", ");
100 }
101
102 void appendCharacter(const char c)
103 {
104 bufferPrintf("%c", c);
105 }
106
107 void appendString(const char* string)
108 {
109 bufferPrintf("%s", string);
110 }
111
112 void appendShiftType(unsigned shiftValue)
113 {
114 bufferPrintf("%s ", shiftName(shiftValue));
115 }
116
117 void appendSignedImmediate(int immediate)
118 {
119 bufferPrintf("#%d", immediate);
120 }
121
122 void appendUnsignedImmediate(unsigned immediate)
123 {
124 bufferPrintf("#%u", immediate);
125 }
126
127 void appendPCRelativeOffset(int32_t immediate)
128 {
129 bufferPrintf("0x%x", reinterpret_cast<uint32_t>(m_currentPC + immediate));
130 }
131
132 void appendShiftAmount(unsigned amount)
133 {
134 bufferPrintf("lsl #%u", 16 * amount);
135 }
136
137 static const int bufferSize = 81;
138 static const unsigned char CondNone = 0xe;
139 static const unsigned MaxITBlockSize = 4;
140
141 char m_formatBuffer[bufferSize];
142 unsigned char m_ifThenConditions[MaxITBlockSize];
143 uint16_t* m_currentPC;
144 uint32_t m_opcode;
145 int m_bufferOffset;
146 int m_currentITCondition;
147 unsigned m_ITConditionIndex;
148 unsigned m_ITBlocksize;
149
150 private:
151 static bool s_initialized;
152 };
153
154 #define DEFINE_STATIC_FORMAT16(klass, thisObj) \
155 static const char* format(ARMv7D16BitOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); }
156
157 class ARMv7D16BitOpcode : public ARMv7DOpcode {
158 private:
159 class OpcodeGroup {
160 public:
161 OpcodeGroup(uint16_t opcodeMask, uint16_t opcodePattern, const char* (*format)(ARMv7D16BitOpcode*))
162 : m_opcodeMask(opcodeMask)
163 , m_opcodePattern(opcodePattern)
164 , m_format(format)
165 , m_next(0)
166 {
167 }
168
169 void setNext(OpcodeGroup* next)
170 {
171 m_next = next;
172 }
173
174 OpcodeGroup* next()
175 {
176 return m_next;
177 }
178
179 bool matches(uint16_t opcode)
180 {
181 return (opcode & m_opcodeMask) == m_opcodePattern;
182 }
183
184 const char* format(ARMv7D16BitOpcode* thisObj)
185 {
186 return m_format(thisObj);
187 }
188
189 public:
190 static const unsigned opcodeTableSize = 32;
191 static const unsigned opcodeTableMask = opcodeTableSize-1;
192
193 // private:
194 uint16_t m_opcodeMask;
195 uint16_t m_opcodePattern;
196 const char* (*m_format)(ARMv7D16BitOpcode*);
197 OpcodeGroup* m_next;
198 };
199
200 public:
201 static void init();
202
203 const char* defaultFormat();
204 const char* doDisassemble();
205
206 protected:
207 unsigned rm() { return (m_opcode >> 3) & 0x7; }
208 unsigned rd() { return m_opcode & 0x7; }
209 unsigned opcodeGroupNumber(unsigned opcode) { return (opcode >> 11) & OpcodeGroup::opcodeTableMask; }
210
211 private:
212 static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize];
213 };
214
215 class ARMv7DOpcodeAddRegisterT2 : public ARMv7D16BitOpcode {
216 public:
217 static const uint16_t s_mask = 0xff00;
218 static const uint16_t s_pattern = 0x4400;
219
220 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddRegisterT2, thisObj);
221
222 protected:
223 const char* format();
224
225 unsigned rdn() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); }
226 unsigned rm() { return ((m_opcode >> 3) & 0xf); }
227 };
228
229 class ARMv7DOpcodeAddSPPlusImmediate : public ARMv7D16BitOpcode {
230 public:
231 static const uint16_t s_mask = 0xf800;
232 static const uint16_t s_pattern = 0xc800;
233
234 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSPPlusImmediate, thisObj);
235
236 protected:
237 const char* format();
238
239 unsigned rd() { return (m_opcode >> 8) & 0x7; }
240 unsigned immediate8() { return m_opcode & 0x0ff; }
241 };
242
243 class ARMv7DOpcodeAddSubtract : public ARMv7D16BitOpcode {
244 protected:
245 static const char* const s_opNames[2];
246 };
247
248 class ARMv7DOpcodeAddSubtractT1 : public ARMv7DOpcodeAddSubtract {
249 public:
250 static const uint16_t s_mask = 0xfc00;
251 static const uint16_t s_pattern = 0x1800;
252
253 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractT1, thisObj);
254
255 protected:
256 const char* format();
257
258 const char* opName() { return s_opNames[op()]; }
259
260 unsigned op() { return (m_opcode >> 9) & 0x1; }
261 unsigned rm() { return (m_opcode >> 6) & 0x7; }
262 unsigned rn() { return (m_opcode >> 3) & 0x7; }
263 };
264
265 class ARMv7DOpcodeAddSubtractImmediate3 : public ARMv7DOpcodeAddSubtract {
266 public:
267 static const uint16_t s_mask = 0xfc00;
268 static const uint16_t s_pattern = 0x1c00;
269
270 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate3, thisObj);
271
272 protected:
273 const char* format();
274
275 const char* opName() { return s_opNames[op()]; }
276
277 unsigned op() { return (m_opcode >> 9) & 0x1; }
278 unsigned immediate3() { return (m_opcode >> 6) & 0x3; }
279 unsigned rn() { return (m_opcode >> 3) & 0x7; }
280 };
281
282 class ARMv7DOpcodeAddSubtractImmediate8 : public ARMv7DOpcodeAddSubtract {
283 public:
284 static const uint16_t s_mask = 0xf000;
285 static const uint16_t s_pattern = 0x3000;
286
287 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate8, thisObj);
288
289 protected:
290 const char* format();
291
292 const char* opName() { return s_opNames[op()]; }
293
294 unsigned op() { return (m_opcode >> 11) & 0x1; }
295 unsigned rdn() { return (m_opcode >> 8) & 0x7; }
296 unsigned immediate8() { return m_opcode & 0xff; }
297 };
298
299 class ARMv7DOpcodeBranchConditionalT1 : public ARMv7D16BitOpcode {
300 public:
301 static const uint16_t s_mask = 0xf000;
302 static const uint16_t s_pattern = 0xd000;
303
304 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchConditionalT1, thisObj);
305
306 protected:
307 const char* format();
308
309 unsigned condition() { return (m_opcode >> 8) & 0xf; }
310 int offset() { return static_cast<int>(m_opcode & 0xff); }
311 };
312
313 class ARMv7DOpcodeBranchExchangeT1 : public ARMv7D16BitOpcode {
314 public:
315 static const uint16_t s_mask = 0xff00;
316 static const uint16_t s_pattern = 0x4700;
317
318 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchExchangeT1, thisObj);
319
320 protected:
321 const char* format();
322
323 const char* opName() { return (m_opcode & 0x80) ? "blx" : "bx"; }
324 unsigned rm() { return ((m_opcode >> 3) & 0xf); }
325 };
326
327 class ARMv7DOpcodeBranchT2 : public ARMv7D16BitOpcode {
328 public:
329 static const uint16_t s_mask = 0xf800;
330 static const uint16_t s_pattern = 0xe000;
331
332 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchT2, thisObj);
333
334 protected:
335 const char* format();
336
337 int immediate11() { return static_cast<int>(m_opcode & 0x7ff); }
338 };
339
340 class ARMv7DOpcodeCompareImmediateT1 : public ARMv7D16BitOpcode {
341 public:
342 static const uint16_t s_mask = 0xf800;
343 static const uint16_t s_pattern = 0x2800;
344
345 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareImmediateT1, thisObj);
346
347 protected:
348 const char* format();
349
350 unsigned rn() { return (m_opcode >> 8) & 0x3; }
351 unsigned immediate8() { return m_opcode & 0xff; }
352 };
353
354 class ARMv7DOpcodeCompareRegisterT1 : public ARMv7D16BitOpcode {
355 public:
356 static const uint16_t s_mask = 0xffc0;
357 static const uint16_t s_pattern = 0x4280;
358
359 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT1, thisObj);
360
361 protected:
362 const char* format();
363
364 unsigned rn() { return m_opcode & 0x7; }
365 };
366
367 class ARMv7DOpcodeCompareRegisterT2 : public ARMv7D16BitOpcode {
368 public:
369 static const uint16_t s_mask = 0xff00;
370 static const uint16_t s_pattern = 0x4500;
371
372 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT2, thisObj);
373
374 protected:
375 const char* format();
376
377 unsigned rn() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); }
378 unsigned rm() { return ((m_opcode >> 3) & 0xf); }
379 };
380
381 class ARMv7DOpcodeDataProcessingRegisterT1 : public ARMv7D16BitOpcode {
382 private:
383 static const char* const s_opNames[16];
384
385 public:
386 static const uint16_t s_mask = 0xfc00;
387 static const uint16_t s_pattern = 0x4000;
388
389 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeDataProcessingRegisterT1, thisObj);
390
391 protected:
392 const char* format();
393
394 const char* opName() { return s_opNames[op()]; }
395
396 unsigned op() { return (m_opcode >> 6) & 0xf; }
397
398 unsigned rm() { return (m_opcode >> 3) & 0x7; }
399 unsigned rdn() { return m_opcode & 0x7; }
400 };
401
402 class ARMv7DOpcodeGeneratePCRelativeAddress : public ARMv7D16BitOpcode {
403 public:
404 static const uint16_t s_mask = 0xf800;
405 static const uint16_t s_pattern = 0xa000;
406
407 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeGeneratePCRelativeAddress, thisObj);
408
409 protected:
410 const char* format();
411
412 unsigned rd() { return (m_opcode >> 8) & 0x7; }
413 unsigned immediate8() { return m_opcode & 0x0ff; }
414 };
415
416 class ARMv7DOpcodeLoadFromLiteralPool : public ARMv7D16BitOpcode {
417 public:
418 static const uint16_t s_mask = 0xf800;
419 static const uint16_t s_pattern = 0x4800;
420
421 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadFromLiteralPool, thisObj);
422
423 protected:
424 const char* format();
425
426 unsigned rt() { return (m_opcode >> 8) & 0x7; }
427 unsigned immediate8() { return m_opcode & 0x0ff; }
428 };
429
430 class ARMv7DOpcodeLoadStoreRegisterImmediate : public ARMv7D16BitOpcode {
431 private:
432 static const char* const s_opNames[6];
433
434 public:
435 const char* format();
436
437 protected:
438 const char* opName() { return s_opNames[op()]; }
439
440 unsigned op() { return ((m_opcode >> 11) & 0x1f) - 0xc; }
441 unsigned immediate5() { return (m_opcode >> 6) & 0x01f; }
442 unsigned rn() { return (m_opcode >> 3) & 0x7; }
443 unsigned rt() { return m_opcode & 0x7; }
444 unsigned scale() { return 2 - (op() >> 1); }
445 };
446
447 class ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte : public ARMv7DOpcodeLoadStoreRegisterImmediate {
448 public:
449 static const uint16_t s_mask = 0xe000;
450 static const uint16_t s_pattern = 0x6000;
451
452 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj);
453 };
454
455 class ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {
456 public:
457 static const uint16_t s_mask = 0xf800;
458 static const uint16_t s_pattern = 0x8000;
459
460 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterImmediate, thisObj);
461 };
462
463 class ARMv7DOpcodeLoadStoreRegisterOffsetT1 : public ARMv7D16BitOpcode {
464 private:
465 static const char* const s_opNames[8];
466
467 public:
468 static const uint16_t s_mask = 0xf000;
469 static const uint16_t s_pattern = 0x5000;
470
471 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterOffsetT1, thisObj);
472
473 protected:
474 const char* format();
475
476 const char* opName() { return s_opNames[opB()]; }
477
478 unsigned opB() { return (m_opcode >> 9) & 0x7; }
479 unsigned rm() { return (m_opcode >> 6) & 0x7; }
480 unsigned rn() { return (m_opcode >> 3) & 0x7; }
481 unsigned rt() { return m_opcode & 0x7; }
482 };
483
484 class ARMv7DOpcodeLoadStoreRegisterSPRelative : public ARMv7D16BitOpcode {
485 private:
486 static const char* const s_opNames[8];
487
488 public:
489 static const uint16_t s_mask = 0xf000;
490 static const uint16_t s_pattern = 0x9000;
491
492 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterSPRelative, thisObj);
493
494 protected:
495 const char* format();
496
497 const char* opName() { return op() ? "ldr" : "str"; }
498
499 unsigned op() { return (m_opcode >> 11) & 0x1; }
500 unsigned rt() { return (m_opcode >> 8) & 0x7; }
501 unsigned immediate8() { return m_opcode & 0xff; }
502 };
503
504 class ARMv7DOpcodeLogicalImmediateT1 : public ARMv7D16BitOpcode {
505 public:
506 static const uint16_t s_mask = 0xe000;
507 static const uint16_t s_pattern = 0x0000;
508
509 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLogicalImmediateT1, thisObj);
510
511 protected:
512 const char* format();
513
514 const char* opName() { return shiftName(op()); }
515
516 unsigned op() { return (m_opcode >> 12) & 0x3; }
517 unsigned immediate5() { return (m_opcode >> 6) & 0x1f; }
518 };
519
520 class ARMv7DOpcodeMiscAddSubSP : public ARMv7D16BitOpcode {
521 public:
522 static const uint16_t s_mask = 0xff00;
523 static const uint16_t s_pattern = 0xb000;
524
525 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscAddSubSP, thisObj);
526
527 protected:
528 const char* format();
529
530 const char* opName() { return op() ? "sub" : "add"; }
531 unsigned op() { return (m_opcode >> 7) & 0x1; }
532 unsigned immediate7() { return m_opcode & 0x7f; }
533 };
534
535 class ARMv7DOpcodeMiscByteHalfwordOps : public ARMv7D16BitOpcode {
536 private:
537 static const char* const s_opNames[8];
538
539 public:
540 static const uint16_t s_mask = 0xf700;
541 static const uint16_t s_pattern = 0xb200;
542
543 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscByteHalfwordOps, thisObj);
544
545 protected:
546 const char* format();
547
548 const char* opName() { return s_opNames[op()]; }
549 unsigned op() { return ((m_opcode >> 9) & 0x4) || ((m_opcode >> 6) & 0x3); }
550 };
551
552 class ARMv7DOpcodeMiscBreakpointT1 : public ARMv7D16BitOpcode {
553 public:
554 static const uint16_t s_mask = 0xff00;
555 static const uint16_t s_pattern = 0xbe00;
556
557 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscBreakpointT1, thisObj);
558
559 protected:
560 const char* format();
561
562 unsigned immediate8() { return m_opcode & 0xff; }
563 };
564
565 class ARMv7DOpcodeMiscCompareAndBranch : public ARMv7D16BitOpcode {
566 public:
567 static const uint16_t s_mask = 0xf500;
568 static const uint16_t s_pattern = 0xb100;
569
570 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscCompareAndBranch, thisObj);
571
572 protected:
573 const char* format();
574
575 const char* opName() { return op() ? "cbnz" : "cbz"; }
576 unsigned op() { return (m_opcode >> 11) & 0x1; }
577 int32_t immediate6() { return ((m_opcode >> 4) & 0x20) | ((m_opcode >> 3) & 0x1f); }
578 unsigned rn() { return m_opcode & 0x7; }
579 };
580
581 class ARMv7DOpcodeMiscHint16 : public ARMv7D16BitOpcode {
582 private:
583 static const char* const s_opNames[16];
584
585 public:
586 static const uint16_t s_mask = 0xff0f;
587 static const uint16_t s_pattern = 0xbf00;
588
589 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscHint16, thisObj);
590
591 protected:
592 const char* format();
593
594 const char* opName() { return s_opNames[opA()]; }
595 unsigned opA() { return (m_opcode >> 4) & 0xf; }
596 };
597
598 class ARMv7DOpcodeMiscIfThenT1 : public ARMv7D16BitOpcode {
599 public:
600 static const uint16_t s_mask = 0xff00;
601 static const uint16_t s_pattern = 0xbf00;
602
603 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscIfThenT1, thisObj);
604
605 protected:
606 const char* format();
607
608 unsigned firstCondition() { return (m_opcode >> 4) & 0xf; }
609 unsigned mask() { return m_opcode & 0xf; }
610 };
611
612 class ARMv7DOpcodeMiscPushPop : public ARMv7D16BitOpcode {
613 public:
614 static const uint16_t s_mask = 0xf600;
615 static const uint16_t s_pattern = 0xb400;
616
617 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscPushPop, thisObj);
618
619 protected:
620 const char* format();
621
622 const char* opName() { return op() ? "pop" : "push"; }
623 unsigned op() { return (m_opcode >> 11) & 0x1; }
624 unsigned registerMask() { return ((m_opcode << 6) & 0x4000) | (m_opcode & 0x7f); }
625 };
626
627 class ARMv7DOpcodeMoveImmediateT1 : public ARMv7D16BitOpcode {
628 public:
629 static const uint16_t s_mask = 0xf800;
630 static const uint16_t s_pattern = 0x2000;
631
632 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveImmediateT1, thisObj);
633
634 protected:
635 const char* format();
636
637 unsigned rd() { return (m_opcode >> 8) & 0x3; }
638 unsigned immediate8() { return m_opcode & 0xff; }
639 };
640
641 class ARMv7DOpcodeMoveRegisterT1 : public ARMv7D16BitOpcode {
642 public:
643 static const uint16_t s_mask = 0xff00;
644 static const uint16_t s_pattern = 0x4600;
645
646 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveRegisterT1, thisObj);
647
648 protected:
649 const char* format();
650
651 unsigned rd() { return ((m_opcode >> 4) & 0x8) | (m_opcode & 0x7); }
652 unsigned rm() { return ((m_opcode >> 3) & 0xf); }
653 };
654
655 // 32 Bit instructions
656
657 #define DEFINE_STATIC_FORMAT32(klass, thisObj) \
658 static const char* format(ARMv7D32BitOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); }
659
660 class ARMv7D32BitOpcode : public ARMv7DOpcode {
661 private:
662 class OpcodeGroup {
663 public:
664 OpcodeGroup(uint32_t opcodeMask, uint32_t opcodePattern, const char* (*format)(ARMv7D32BitOpcode*))
665 : m_opcodeMask(opcodeMask)
666 , m_opcodePattern(opcodePattern)
667 , m_format(format)
668 , m_next(0)
669 {
670 }
671
672 void setNext(OpcodeGroup* next)
673 {
674 m_next = next;
675 }
676
677 OpcodeGroup* next()
678 {
679 return m_next;
680 }
681
682 bool matches(uint32_t opcode)
683 {
684 return (opcode & m_opcodeMask) == m_opcodePattern;
685 }
686
687 const char* format(ARMv7D32BitOpcode* thisObj)
688 {
689 return m_format(thisObj);
690 }
691
692 public:
693 static const unsigned opcodeTableSize = 16;
694 static const unsigned opcodeTableMask = opcodeTableSize-1;
695
696 private:
697 uint32_t m_opcodeMask;
698 uint32_t m_opcodePattern;
699 const char* (*m_format)(ARMv7D32BitOpcode*);
700 OpcodeGroup* m_next;
701 };
702
703 public:
704 static void init();
705
706 const char* defaultFormat();
707 const char* doDisassemble();
708
709 protected:
710 unsigned rd() { return (m_opcode >> 8) & 0xf; }
711 unsigned rm() { return m_opcode & 0xf; }
712 unsigned rn() { return (m_opcode >> 16) & 0xf; }
713 unsigned rt() { return (m_opcode >> 12) & 0xf; }
714
715 unsigned opcodeGroupNumber(unsigned opcode) { return (opcode >> 25) & OpcodeGroup::opcodeTableMask; }
716
717 private:
718 static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize];
719 };
720
721 class ARMv7DOpcodeBranchRelative : public ARMv7D32BitOpcode {
722 protected:
723 unsigned sBit() { return (m_opcode >> 26) & 0x1; }
724 unsigned j1() { return (m_opcode >> 13) & 0x1; }
725 unsigned j2() { return (m_opcode >> 11) & 0x1; }
726 unsigned immediate11() { return m_opcode & 0x7ff; }
727 };
728
729 class ARMv7DOpcodeConditionalBranchT3 : public ARMv7DOpcodeBranchRelative {
730 public:
731 static const uint32_t s_mask = 0xf800d000;
732 static const uint32_t s_pattern = 0xf0008000;
733
734 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeConditionalBranchT3, thisObj);
735
736 protected:
737 const char* format();
738
739 int32_t offset() { return ((static_cast<int32_t>(sBit() << 31)) >> 12) | static_cast<int32_t>((j1() << 18) | (j2() << 17) | (immediate6() << 11) | immediate11()); }
740 unsigned condition() { return (m_opcode >> 22) & 0xf; }
741 unsigned immediate6() { return (m_opcode >> 16) & 0x3f; }
742 };
743
744 class ARMv7DOpcodeBranchOrBranchLink : public ARMv7DOpcodeBranchRelative {
745 public:
746 static const uint32_t s_mask = 0xf8009000;
747 static const uint32_t s_pattern = 0xf0009000;
748
749 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeBranchOrBranchLink, thisObj);
750
751 protected:
752 const char* format();
753
754 int32_t offset() { return ((static_cast<int32_t>(sBit() << 31)) >> 8) | static_cast<int32_t>((~(j1() ^ sBit()) << 22) | (~(j2() ^ sBit()) << 21) | (immediate10() << 11) | immediate11()); }
755 unsigned immediate10() { return (m_opcode >> 16) & 0x3ff; }
756 bool isBL() { return !!((m_opcode >> 14) & 0x1); }
757 };
758
759 class ARMv7DOpcodeDataProcessingLogicalAndRithmetic : public ARMv7D32BitOpcode {
760 protected:
761 static const char* const s_opNames[16];
762 };
763
764 class ARMv7DOpcodeDataProcessingModifiedImmediate : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic {
765 private:
766 void appendImmShift(unsigned, unsigned);
767
768 public:
769 static const uint32_t s_mask = 0xfa008000;
770 static const uint32_t s_pattern = 0xf0000000;
771
772 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingModifiedImmediate, thisObj);
773
774 protected:
775 const char* format();
776 void appendModifiedImmediate(unsigned);
777
778 const char* opName() { return s_opNames[op()]; }
779
780 unsigned op() { return (m_opcode >> 21) & 0xf; }
781 unsigned sBit() { return (m_opcode >> 20) & 0x1; }
782 unsigned immediate12() { return ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); }
783 };
784
785 class ARMv7DOpcodeDataProcessingShiftedReg : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic {
786 private:
787 void appendImmShift(unsigned, unsigned);
788
789 public:
790 static const uint32_t s_mask = 0xfe000000;
791 static const uint32_t s_pattern = 0xea000000;
792
793 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingShiftedReg, thisObj);
794
795 protected:
796 const char* format();
797
798 const char* opName() { return s_opNames[op()]; }
799
800 unsigned sBit() { return (m_opcode >> 20) & 0x1; }
801 unsigned op() { return (m_opcode >> 21) & 0xf; }
802 unsigned immediate5() { return ((m_opcode >> 10) & 0x1c) | ((m_opcode >> 6) & 0x3); }
803 unsigned type() { return (m_opcode >> 4) & 0x3; }
804 unsigned tbBit() { return (m_opcode >> 5) & 0x1; }
805 unsigned tBit() { return (m_opcode >> 4) & 0x1; }
806 };
807
808 class ARMv7DOpcodeDataProcessingReg : public ARMv7D32BitOpcode {
809 protected:
810 unsigned op1() { return (m_opcode >> 20) & 0xf; }
811 unsigned op2() { return (m_opcode >> 4) & 0xf; }
812 };
813
814 class ARMv7DOpcodeDataProcessingRegShift : public ARMv7DOpcodeDataProcessingReg {
815 public:
816 static const uint32_t s_mask = 0xffe0f0f0;
817 static const uint32_t s_pattern = 0xfa00f000;
818
819 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegShift, thisObj);
820
821 protected:
822 const char* format();
823
824 const char* opName() { return shiftName((op1() >> 1) & 0x3); }
825 };
826
827 class ARMv7DOpcodeDataProcessingRegExtend : public ARMv7DOpcodeDataProcessingReg {
828 private:
829 static const char* const s_opExtendNames[8];
830 static const char* const s_opExtendAndAddNames[8];
831
832 public:
833 static const uint32_t s_mask = 0xff80f0c0;
834 static const uint32_t s_pattern = 0xfa00f080;
835
836 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegExtend, thisObj);
837
838 protected:
839 const char* format();
840
841 const char* opExtendName() { return s_opExtendNames[op1()]; }
842 const char* opExtendAndAddName() { return s_opExtendAndAddNames[op1()]; }
843 unsigned rotate() { return (m_opcode >> 4) & 0x3; }
844 };
845
846 class ARMv7DOpcodeDataProcessingRegParallel : public ARMv7DOpcodeDataProcessingReg {
847 private:
848 static const char* const s_opNames[16];
849
850 public:
851 static const uint32_t s_mask = 0xff80f0e0;
852 static const uint32_t s_pattern = 0xfa00f000;
853
854 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegParallel, thisObj);
855
856 protected:
857 const char* format();
858
859 const char* opName() { return s_opNames[((op1() & 0x7) << 1) | (op2() & 0x1)]; }
860 };
861
862 class ARMv7DOpcodeDataProcessingRegMisc : public ARMv7DOpcodeDataProcessingReg {
863 private:
864 static const char* const s_opNames[16];
865
866 public:
867 static const uint32_t s_mask = 0xffc0f0c0;
868 static const uint32_t s_pattern = 0xfa80f080;
869
870 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegMisc, thisObj);
871
872 protected:
873 const char* format();
874
875 const char* opName() { return s_opNames[((op1() & 0x3) << 2) | (op2() & 0x3)]; }
876 };
877
878 class ARMv7DOpcodeHint32 : public ARMv7D32BitOpcode {
879 private:
880 static const char* const s_opNames[8];
881
882 public:
883 static const uint32_t s_mask = 0xfff0d000;
884 static const uint32_t s_pattern = 0xf3a08000;
885
886 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeHint32, thisObj);
887
888 protected:
889 const char* format();
890
891 const char* opName() { return s_opNames[op()]; }
892
893 bool isDebugHint() { return (m_opcode & 0xf0) == 0xf0; }
894 unsigned debugOption() { return m_opcode & 0xf; }
895 unsigned op() { return m_opcode & 0x7; }
896 };
897
898 class ARMv7DOpcodeFPTransfer : public ARMv7D32BitOpcode {
899 public:
900 static const uint32_t s_mask = 0xffc00e7f;
901 static const uint32_t s_pattern = 0xee000a10;
902
903 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeFPTransfer, thisObj);
904
905 protected:
906 const char* format();
907
908 void appendFPRegister();
909
910 unsigned opH() { return (m_opcode >> 21) & 0x1; }
911 unsigned opL() { return (m_opcode >> 20) & 0x1; }
912 unsigned rt() { return (m_opcode >> 12) & 0xf; }
913 unsigned opC() { return (m_opcode >> 8) & 0x1; }
914 unsigned opB() { return (m_opcode >> 5) & 0x3; }
915 unsigned vd() { return ((m_opcode >> 3) & 0x10) | ((m_opcode >> 16) & 0xf); }
916 unsigned vn() { return ((m_opcode >> 7) & 0x1) | ((m_opcode >> 15) & 0x1e); }
917 };
918
919 class ARMv7DOpcodeDataLoad : public ARMv7D32BitOpcode {
920 protected:
921 static const char* const s_opNames[8];
922
923 protected:
924 const char* opName() { return s_opNames[op()]; }
925
926 unsigned op() { return ((m_opcode >> 22) & 0x4) | ((m_opcode >> 21) & 0x3); }
927 };
928
929 class ARMv7DOpcodeLoadRegister : public ARMv7DOpcodeDataLoad {
930 public:
931 static const uint32_t s_mask = 0xfe900800;
932 static const uint32_t s_pattern = 0xf8100000;
933
934 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadRegister, thisObj);
935
936 protected:
937 const char* format();
938
939 unsigned immediate2() { return (m_opcode >> 4) & 0x3; }
940 };
941
942 class ARMv7DOpcodeLoadSignedImmediate : public ARMv7DOpcodeDataLoad {
943 public:
944 static const uint32_t s_mask = 0xfe900800;
945 static const uint32_t s_pattern = 0xf8100800;
946
947 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadSignedImmediate, thisObj);
948
949 protected:
950 const char* format();
951
952 unsigned pBit() { return (m_opcode >> 10) & 0x1; }
953 unsigned uBit() { return (m_opcode >> 9) & 0x1; }
954 unsigned wBit() { return (m_opcode >> 8) & 0x1; }
955 unsigned immediate8() { return m_opcode & 0xff; }
956 };
957
958 class ARMv7DOpcodeLoadUnsignedImmediate : public ARMv7DOpcodeDataLoad {
959 public:
960 static const uint32_t s_mask = 0xfe900000;
961 static const uint32_t s_pattern = 0xf8900000;
962
963 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadUnsignedImmediate, thisObj);
964
965 protected:
966 const char* format();
967
968 unsigned immediate12() { return m_opcode & 0xfff; }
969 };
970
971 class ARMv7DOpcodeLongMultipleDivide : public ARMv7D32BitOpcode {
972 protected:
973 static const char* const s_opNames[8];
974 static const char* const s_smlalOpNames[4];
975 static const char* const s_smlaldOpNames[2];
976 static const char* const s_smlsldOpNames[2];
977
978 public:
979 static const uint32_t s_mask = 0xff800000;
980 static const uint32_t s_pattern = 0xfb800000;
981
982 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLongMultipleDivide, thisObj);
983
984 protected:
985 const char* format();
986
987 const char* opName() { return s_opNames[op1()]; }
988 const char* smlalOpName() { return s_smlalOpNames[(nBit() << 1) | mBit()]; }
989 const char* smlaldOpName() { return s_smlaldOpNames[mBit()]; }
990 const char* smlsldOpName() { return s_smlsldOpNames[mBit()]; }
991
992 unsigned rdLo() { return rt(); }
993 unsigned rdHi() { return rd(); }
994 unsigned op1() { return (m_opcode >> 20) & 0x7; }
995 unsigned op2() { return (m_opcode >> 4) & 0xf; }
996 unsigned nBit() { return (m_opcode >> 5) & 0x1; }
997 unsigned mBit() { return (m_opcode >> 4) & 0x1; }
998 };
999
1000 class ARMv7DOpcodeDataPushPopSingle : public ARMv7D32BitOpcode {
1001 public:
1002 static const uint32_t s_mask = 0xffef0fff;
1003 static const uint32_t s_pattern = 0xf84d0d04;
1004
1005 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushPopSingle, thisObj);
1006
1007 protected:
1008 const char* format();
1009
1010 const char* opName() { return op() ? "pop" : "push"; }
1011 unsigned op() { return (m_opcode >> 20) & 0x1; }
1012 };
1013
1014 class ARMv7DOpcodeDataStoreSingle : public ARMv7D32BitOpcode {
1015 protected:
1016 static const char* const s_opNames[4];
1017
1018 protected:
1019 const char* opName() { return s_opNames[op()]; }
1020
1021 unsigned op() { return (m_opcode >> 21) & 0x3; }
1022 };
1023
1024 class ARMv7DOpcodeStoreSingleImmediate12 : public ARMv7DOpcodeDataStoreSingle {
1025 public:
1026 static const uint32_t s_mask = 0xfff00000;
1027 static const uint32_t s_pattern = 0xf8c00000;
1028
1029 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleImmediate12, thisObj);
1030
1031 const char* format();
1032
1033 protected:
1034 unsigned immediate12() { return m_opcode & 0xfff; }
1035 };
1036
1037 class ARMv7DOpcodeStoreSingleImmediate8 : public ARMv7DOpcodeDataStoreSingle {
1038 public:
1039 static const uint32_t s_mask = 0xfff00800;
1040 static const uint32_t s_pattern = 0xf8400800;
1041
1042 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleImmediate8, thisObj);
1043
1044 const char* format();
1045
1046 protected:
1047 unsigned pBit() { return (m_opcode >> 10) & 0x1; }
1048 unsigned uBit() { return (m_opcode >> 9) & 0x1; }
1049 unsigned wBit() { return (m_opcode >> 8) & 0x1; }
1050 unsigned immediate8() { return m_opcode & 0xff; }
1051 };
1052
1053 class ARMv7DOpcodeStoreSingleRegister : public ARMv7DOpcodeDataStoreSingle {
1054 public:
1055 static const uint32_t s_mask = 0xfff00fc0;
1056 static const uint32_t s_pattern = 0xf8400000;
1057
1058 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleRegister, thisObj);
1059
1060 protected:
1061 const char* format();
1062
1063 unsigned immediate2() { return (m_opcode >> 4) & 0x3; }
1064 };
1065
1066 class ARMv7DOpcodeUnmodifiedImmediate : public ARMv7D32BitOpcode {
1067 protected:
1068 static const char* const s_opNames[16];
1069
1070 public:
1071 static const uint32_t s_mask = 0xfa008000;
1072 static const uint32_t s_pattern = 0xf2000000;
1073
1074 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeUnmodifiedImmediate, thisObj);
1075
1076 protected:
1077 const char* format();
1078
1079 const char* opName() { return s_opNames[op() >> 1]; }
1080
1081 unsigned op() { return (m_opcode >> 20) & 0x1f; }
1082 unsigned shBit() { return (m_opcode >> 21) & 0x1; }
1083 unsigned bitNumOrSatImmediate() { return m_opcode & 0x1f; }
1084 unsigned immediate5() { return ((m_opcode >> 9) & 0x1c) | ((m_opcode >> 6) & 0x3); }
1085 unsigned immediate12() { return ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); }
1086 unsigned immediate16() { return ((m_opcode >> 4) & 0xf000) | ((m_opcode >> 15) & 0x0800) | ((m_opcode >> 4) & 0x0700) | (m_opcode & 0x00ff); }
1087 };
1088
1089 class ARMv7DOpcodeVMOVDoublePrecision : public ARMv7D32BitOpcode {
1090 public:
1091 static const uint32_t s_mask = 0xffe00fd0;
1092 static const uint32_t s_pattern = 0xec400b10;
1093
1094 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVDoublePrecision, thisObj);
1095
1096 protected:
1097 const char* format();
1098
1099 unsigned op() { return (m_opcode >> 20) & 0x1; }
1100 unsigned rt2() { return (m_opcode >> 16) & 0xf; }
1101 unsigned rt() { return (m_opcode >> 16) & 0xf; }
1102 unsigned vm() { return (m_opcode & 0xf) | ((m_opcode >> 1) & 0x10); }
1103 };
1104
1105 class ARMv7DOpcodeVMOVSinglePrecision : public ARMv7D32BitOpcode {
1106 public:
1107 static const uint32_t s_mask = 0xffe00fd0;
1108 static const uint32_t s_pattern = 0xec400a10;
1109
1110 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVSinglePrecision, thisObj);
1111
1112 protected:
1113 const char* format();
1114
1115 unsigned op() { return (m_opcode >> 20) & 0x1; }
1116 unsigned rt2() { return (m_opcode >> 16) & 0xf; }
1117 unsigned rt() { return (m_opcode >> 16) & 0xf; }
1118 unsigned vm() { return ((m_opcode << 1) & 0x1e) | ((m_opcode >> 5) & 0x1); }
1119 };
1120
1121 class ARMv7DOpcodeVMSR : public ARMv7D32BitOpcode {
1122 public:
1123 static const uint32_t s_mask = 0xffef0fff;
1124 static const uint32_t s_pattern = 0xeee10a10;
1125
1126 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMSR, thisObj);
1127
1128 protected:
1129 const char* format();
1130
1131 unsigned opL() { return (m_opcode >> 20) & 0x1; }
1132 unsigned rt() { return (m_opcode >> 12) & 0xf; }
1133 };
1134
1135
1136 } } // namespace JSC::ARMv7Disassembler
1137
1138 using JSC::ARMv7Disassembler::ARMv7DOpcode;
1139
1140 #endif // #if USE(ARMV7_DISASSEMBLER)
1141
1142 #endif // ARMv7DOpcode_h