]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - disassembler/ARMv7/ARMv7DOpcode.h
JavaScriptCore-1218.0.1.tar.gz
[apple/javascriptcore.git] / disassembler / ARMv7 / ARMv7DOpcode.h
... / ...
CommitLineData
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
34namespace JSC { namespace ARMv7Disassembler {
35
36class ARMv7DOpcode {
37public:
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
56protected:
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
150private:
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
157class ARMv7D16BitOpcode : public ARMv7DOpcode {
158private:
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
200public:
201 static void init();
202
203 const char* defaultFormat();
204 const char* doDisassemble();
205
206protected:
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
211private:
212 static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize];
213};
214
215class ARMv7DOpcodeAddRegisterT2 : public ARMv7D16BitOpcode {
216public:
217 static const uint16_t s_mask = 0xff00;
218 static const uint16_t s_pattern = 0x4400;
219
220 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddRegisterT2, thisObj);
221
222protected:
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
229class ARMv7DOpcodeAddSPPlusImmediate : public ARMv7D16BitOpcode {
230public:
231 static const uint16_t s_mask = 0xf800;
232 static const uint16_t s_pattern = 0xc800;
233
234 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSPPlusImmediate, thisObj);
235
236protected:
237 const char* format();
238
239 unsigned rd() { return (m_opcode >> 8) & 0x7; }
240 unsigned immediate8() { return m_opcode & 0x0ff; }
241};
242
243class ARMv7DOpcodeAddSubtract : public ARMv7D16BitOpcode {
244protected:
245 static const char* const s_opNames[2];
246};
247
248class ARMv7DOpcodeAddSubtractT1 : public ARMv7DOpcodeAddSubtract {
249public:
250 static const uint16_t s_mask = 0xfc00;
251 static const uint16_t s_pattern = 0x1800;
252
253 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractT1, thisObj);
254
255protected:
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
265class ARMv7DOpcodeAddSubtractImmediate3 : public ARMv7DOpcodeAddSubtract {
266public:
267 static const uint16_t s_mask = 0xfc00;
268 static const uint16_t s_pattern = 0x1c00;
269
270 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate3, thisObj);
271
272protected:
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
282class ARMv7DOpcodeAddSubtractImmediate8 : public ARMv7DOpcodeAddSubtract {
283public:
284 static const uint16_t s_mask = 0xf000;
285 static const uint16_t s_pattern = 0x3000;
286
287 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeAddSubtractImmediate8, thisObj);
288
289protected:
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
299class ARMv7DOpcodeBranchConditionalT1 : public ARMv7D16BitOpcode {
300public:
301 static const uint16_t s_mask = 0xf000;
302 static const uint16_t s_pattern = 0xd000;
303
304 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchConditionalT1, thisObj);
305
306protected:
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
313class ARMv7DOpcodeBranchExchangeT1 : public ARMv7D16BitOpcode {
314public:
315 static const uint16_t s_mask = 0xff00;
316 static const uint16_t s_pattern = 0x4700;
317
318 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchExchangeT1, thisObj);
319
320protected:
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
327class ARMv7DOpcodeBranchT2 : public ARMv7D16BitOpcode {
328public:
329 static const uint16_t s_mask = 0xf800;
330 static const uint16_t s_pattern = 0xe000;
331
332 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeBranchT2, thisObj);
333
334protected:
335 const char* format();
336
337 int immediate11() { return static_cast<int>(m_opcode & 0x7ff); }
338};
339
340class ARMv7DOpcodeCompareImmediateT1 : public ARMv7D16BitOpcode {
341public:
342 static const uint16_t s_mask = 0xf800;
343 static const uint16_t s_pattern = 0x2800;
344
345 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareImmediateT1, thisObj);
346
347protected:
348 const char* format();
349
350 unsigned rn() { return (m_opcode >> 8) & 0x3; }
351 unsigned immediate8() { return m_opcode & 0xff; }
352};
353
354class ARMv7DOpcodeCompareRegisterT1 : public ARMv7D16BitOpcode {
355public:
356 static const uint16_t s_mask = 0xffc0;
357 static const uint16_t s_pattern = 0x4280;
358
359 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT1, thisObj);
360
361protected:
362 const char* format();
363
364 unsigned rn() { return m_opcode & 0x7; }
365};
366
367class ARMv7DOpcodeCompareRegisterT2 : public ARMv7D16BitOpcode {
368public:
369 static const uint16_t s_mask = 0xff00;
370 static const uint16_t s_pattern = 0x4500;
371
372 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeCompareRegisterT2, thisObj);
373
374protected:
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
381class ARMv7DOpcodeDataProcessingRegisterT1 : public ARMv7D16BitOpcode {
382private:
383 static const char* const s_opNames[16];
384
385public:
386 static const uint16_t s_mask = 0xfc00;
387 static const uint16_t s_pattern = 0x4000;
388
389 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeDataProcessingRegisterT1, thisObj);
390
391protected:
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
402class ARMv7DOpcodeGeneratePCRelativeAddress : public ARMv7D16BitOpcode {
403public:
404 static const uint16_t s_mask = 0xf800;
405 static const uint16_t s_pattern = 0xa000;
406
407 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeGeneratePCRelativeAddress, thisObj);
408
409protected:
410 const char* format();
411
412 unsigned rd() { return (m_opcode >> 8) & 0x7; }
413 unsigned immediate8() { return m_opcode & 0x0ff; }
414};
415
416class ARMv7DOpcodeLoadFromLiteralPool : public ARMv7D16BitOpcode {
417public:
418 static const uint16_t s_mask = 0xf800;
419 static const uint16_t s_pattern = 0x4800;
420
421 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadFromLiteralPool, thisObj);
422
423protected:
424 const char* format();
425
426 unsigned rt() { return (m_opcode >> 8) & 0x7; }
427 unsigned immediate8() { return m_opcode & 0x0ff; }
428};
429
430class ARMv7DOpcodeLoadStoreRegisterImmediate : public ARMv7D16BitOpcode {
431private:
432 static const char* const s_opNames[6];
433
434public:
435 const char* format();
436
437protected:
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
447class ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte : public ARMv7DOpcodeLoadStoreRegisterImmediate {
448public:
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
455class ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord : public ARMv7DOpcodeLoadStoreRegisterImmediate {
456public:
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
463class ARMv7DOpcodeLoadStoreRegisterOffsetT1 : public ARMv7D16BitOpcode {
464private:
465 static const char* const s_opNames[8];
466
467public:
468 static const uint16_t s_mask = 0xf000;
469 static const uint16_t s_pattern = 0x5000;
470
471 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterOffsetT1, thisObj);
472
473protected:
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
484class ARMv7DOpcodeLoadStoreRegisterSPRelative : public ARMv7D16BitOpcode {
485private:
486 static const char* const s_opNames[8];
487
488public:
489 static const uint16_t s_mask = 0xf000;
490 static const uint16_t s_pattern = 0x9000;
491
492 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLoadStoreRegisterSPRelative, thisObj);
493
494protected:
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
504class ARMv7DOpcodeLogicalImmediateT1 : public ARMv7D16BitOpcode {
505public:
506 static const uint16_t s_mask = 0xe000;
507 static const uint16_t s_pattern = 0x0000;
508
509 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeLogicalImmediateT1, thisObj);
510
511protected:
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
520class ARMv7DOpcodeMiscAddSubSP : public ARMv7D16BitOpcode {
521public:
522 static const uint16_t s_mask = 0xff00;
523 static const uint16_t s_pattern = 0xb000;
524
525 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscAddSubSP, thisObj);
526
527protected:
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
535class ARMv7DOpcodeMiscByteHalfwordOps : public ARMv7D16BitOpcode {
536private:
537 static const char* const s_opNames[8];
538
539public:
540 static const uint16_t s_mask = 0xf700;
541 static const uint16_t s_pattern = 0xb200;
542
543 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscByteHalfwordOps, thisObj);
544
545protected:
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
552class ARMv7DOpcodeMiscBreakpointT1 : public ARMv7D16BitOpcode {
553public:
554 static const uint16_t s_mask = 0xff00;
555 static const uint16_t s_pattern = 0xbe00;
556
557 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscBreakpointT1, thisObj);
558
559protected:
560 const char* format();
561
562 unsigned immediate8() { return m_opcode & 0xff; }
563};
564
565class ARMv7DOpcodeMiscCompareAndBranch : public ARMv7D16BitOpcode {
566public:
567 static const uint16_t s_mask = 0xf500;
568 static const uint16_t s_pattern = 0xb100;
569
570 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscCompareAndBranch, thisObj);
571
572protected:
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
581class ARMv7DOpcodeMiscHint16 : public ARMv7D16BitOpcode {
582private:
583 static const char* const s_opNames[16];
584
585public:
586 static const uint16_t s_mask = 0xff0f;
587 static const uint16_t s_pattern = 0xbf00;
588
589 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscHint16, thisObj);
590
591protected:
592 const char* format();
593
594 const char* opName() { return s_opNames[opA()]; }
595 unsigned opA() { return (m_opcode >> 4) & 0xf; }
596};
597
598class ARMv7DOpcodeMiscIfThenT1 : public ARMv7D16BitOpcode {
599public:
600 static const uint16_t s_mask = 0xff00;
601 static const uint16_t s_pattern = 0xbf00;
602
603 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscIfThenT1, thisObj);
604
605protected:
606 const char* format();
607
608 unsigned firstCondition() { return (m_opcode >> 4) & 0xf; }
609 unsigned mask() { return m_opcode & 0xf; }
610};
611
612class ARMv7DOpcodeMiscPushPop : public ARMv7D16BitOpcode {
613public:
614 static const uint16_t s_mask = 0xf600;
615 static const uint16_t s_pattern = 0xb400;
616
617 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMiscPushPop, thisObj);
618
619protected:
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
627class ARMv7DOpcodeMoveImmediateT1 : public ARMv7D16BitOpcode {
628public:
629 static const uint16_t s_mask = 0xf800;
630 static const uint16_t s_pattern = 0x2000;
631
632 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveImmediateT1, thisObj);
633
634protected:
635 const char* format();
636
637 unsigned rd() { return (m_opcode >> 8) & 0x3; }
638 unsigned immediate8() { return m_opcode & 0xff; }
639};
640
641class ARMv7DOpcodeMoveRegisterT1 : public ARMv7D16BitOpcode {
642public:
643 static const uint16_t s_mask = 0xff00;
644 static const uint16_t s_pattern = 0x4600;
645
646 DEFINE_STATIC_FORMAT16(ARMv7DOpcodeMoveRegisterT1, thisObj);
647
648protected:
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
660class ARMv7D32BitOpcode : public ARMv7DOpcode {
661private:
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
703public:
704 static void init();
705
706 const char* defaultFormat();
707 const char* doDisassemble();
708
709protected:
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
717private:
718 static OpcodeGroup* opcodeTable[OpcodeGroup::opcodeTableSize];
719};
720
721class ARMv7DOpcodeBranchRelative : public ARMv7D32BitOpcode {
722protected:
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
729class ARMv7DOpcodeConditionalBranchT3 : public ARMv7DOpcodeBranchRelative {
730public:
731 static const uint32_t s_mask = 0xf800d000;
732 static const uint32_t s_pattern = 0xf0008000;
733
734 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeConditionalBranchT3, thisObj);
735
736protected:
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
744class ARMv7DOpcodeBranchOrBranchLink : public ARMv7DOpcodeBranchRelative {
745public:
746 static const uint32_t s_mask = 0xf8009000;
747 static const uint32_t s_pattern = 0xf0009000;
748
749 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeBranchOrBranchLink, thisObj);
750
751protected:
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
759class ARMv7DOpcodeDataProcessingLogicalAndRithmetic : public ARMv7D32BitOpcode {
760protected:
761 static const char* const s_opNames[16];
762};
763
764class ARMv7DOpcodeDataProcessingModifiedImmediate : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic {
765private:
766 void appendImmShift(unsigned, unsigned);
767
768public:
769 static const uint32_t s_mask = 0xfa008000;
770 static const uint32_t s_pattern = 0xf0000000;
771
772 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingModifiedImmediate, thisObj);
773
774protected:
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
785class ARMv7DOpcodeDataProcessingShiftedReg : public ARMv7DOpcodeDataProcessingLogicalAndRithmetic {
786private:
787 void appendImmShift(unsigned, unsigned);
788
789public:
790 static const uint32_t s_mask = 0xfe000000;
791 static const uint32_t s_pattern = 0xea000000;
792
793 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingShiftedReg, thisObj);
794
795protected:
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
808class ARMv7DOpcodeDataProcessingReg : public ARMv7D32BitOpcode {
809protected:
810 unsigned op1() { return (m_opcode >> 20) & 0xf; }
811 unsigned op2() { return (m_opcode >> 4) & 0xf; }
812};
813
814class ARMv7DOpcodeDataProcessingRegShift : public ARMv7DOpcodeDataProcessingReg {
815public:
816 static const uint32_t s_mask = 0xffe0f0f0;
817 static const uint32_t s_pattern = 0xfa00f000;
818
819 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegShift, thisObj);
820
821protected:
822 const char* format();
823
824 const char* opName() { return shiftName((op1() >> 1) & 0x3); }
825};
826
827class ARMv7DOpcodeDataProcessingRegExtend : public ARMv7DOpcodeDataProcessingReg {
828private:
829 static const char* const s_opExtendNames[8];
830 static const char* const s_opExtendAndAddNames[8];
831
832public:
833 static const uint32_t s_mask = 0xff80f0c0;
834 static const uint32_t s_pattern = 0xfa00f080;
835
836 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegExtend, thisObj);
837
838protected:
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
846class ARMv7DOpcodeDataProcessingRegParallel : public ARMv7DOpcodeDataProcessingReg {
847private:
848 static const char* const s_opNames[16];
849
850public:
851 static const uint32_t s_mask = 0xff80f0e0;
852 static const uint32_t s_pattern = 0xfa00f000;
853
854 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegParallel, thisObj);
855
856protected:
857 const char* format();
858
859 const char* opName() { return s_opNames[((op1() & 0x7) << 1) | (op2() & 0x1)]; }
860};
861
862class ARMv7DOpcodeDataProcessingRegMisc : public ARMv7DOpcodeDataProcessingReg {
863private:
864 static const char* const s_opNames[16];
865
866public:
867 static const uint32_t s_mask = 0xffc0f0c0;
868 static const uint32_t s_pattern = 0xfa80f080;
869
870 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataProcessingRegMisc, thisObj);
871
872protected:
873 const char* format();
874
875 const char* opName() { return s_opNames[((op1() & 0x3) << 2) | (op2() & 0x3)]; }
876};
877
878class ARMv7DOpcodeHint32 : public ARMv7D32BitOpcode {
879private:
880 static const char* const s_opNames[8];
881
882public:
883 static const uint32_t s_mask = 0xfff0d000;
884 static const uint32_t s_pattern = 0xf3a08000;
885
886 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeHint32, thisObj);
887
888protected:
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
898class ARMv7DOpcodeFPTransfer : public ARMv7D32BitOpcode {
899public:
900 static const uint32_t s_mask = 0xffc00e7f;
901 static const uint32_t s_pattern = 0xee000a10;
902
903 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeFPTransfer, thisObj);
904
905protected:
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
919class ARMv7DOpcodeDataLoad : public ARMv7D32BitOpcode {
920protected:
921 static const char* const s_opNames[8];
922
923protected:
924 const char* opName() { return s_opNames[op()]; }
925
926 unsigned op() { return ((m_opcode >> 22) & 0x4) | ((m_opcode >> 21) & 0x3); }
927};
928
929class ARMv7DOpcodeLoadRegister : public ARMv7DOpcodeDataLoad {
930public:
931 static const uint32_t s_mask = 0xfe900800;
932 static const uint32_t s_pattern = 0xf8100000;
933
934 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadRegister, thisObj);
935
936protected:
937 const char* format();
938
939 unsigned immediate2() { return (m_opcode >> 4) & 0x3; }
940};
941
942class ARMv7DOpcodeLoadSignedImmediate : public ARMv7DOpcodeDataLoad {
943public:
944 static const uint32_t s_mask = 0xfe900800;
945 static const uint32_t s_pattern = 0xf8100800;
946
947 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadSignedImmediate, thisObj);
948
949protected:
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
958class ARMv7DOpcodeLoadUnsignedImmediate : public ARMv7DOpcodeDataLoad {
959public:
960 static const uint32_t s_mask = 0xfe900000;
961 static const uint32_t s_pattern = 0xf8900000;
962
963 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLoadUnsignedImmediate, thisObj);
964
965protected:
966 const char* format();
967
968 unsigned immediate12() { return m_opcode & 0xfff; }
969};
970
971class ARMv7DOpcodeLongMultipleDivide : public ARMv7D32BitOpcode {
972protected:
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
978public:
979 static const uint32_t s_mask = 0xff800000;
980 static const uint32_t s_pattern = 0xfb800000;
981
982 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeLongMultipleDivide, thisObj);
983
984protected:
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
1000class ARMv7DOpcodeDataPushPopSingle : public ARMv7D32BitOpcode {
1001public:
1002 static const uint32_t s_mask = 0xffef0fff;
1003 static const uint32_t s_pattern = 0xf84d0d04;
1004
1005 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeDataPushPopSingle, thisObj);
1006
1007protected:
1008 const char* format();
1009
1010 const char* opName() { return op() ? "pop" : "push"; }
1011 unsigned op() { return (m_opcode >> 20) & 0x1; }
1012};
1013
1014class ARMv7DOpcodeDataStoreSingle : public ARMv7D32BitOpcode {
1015protected:
1016 static const char* const s_opNames[4];
1017
1018protected:
1019 const char* opName() { return s_opNames[op()]; }
1020
1021 unsigned op() { return (m_opcode >> 21) & 0x3; }
1022};
1023
1024class ARMv7DOpcodeStoreSingleImmediate12 : public ARMv7DOpcodeDataStoreSingle {
1025public:
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
1033protected:
1034 unsigned immediate12() { return m_opcode & 0xfff; }
1035};
1036
1037class ARMv7DOpcodeStoreSingleImmediate8 : public ARMv7DOpcodeDataStoreSingle {
1038public:
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
1046protected:
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
1053class ARMv7DOpcodeStoreSingleRegister : public ARMv7DOpcodeDataStoreSingle {
1054public:
1055 static const uint32_t s_mask = 0xfff00fc0;
1056 static const uint32_t s_pattern = 0xf8400000;
1057
1058 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeStoreSingleRegister, thisObj);
1059
1060protected:
1061 const char* format();
1062
1063 unsigned immediate2() { return (m_opcode >> 4) & 0x3; }
1064};
1065
1066class ARMv7DOpcodeUnmodifiedImmediate : public ARMv7D32BitOpcode {
1067protected:
1068 static const char* const s_opNames[16];
1069
1070public:
1071 static const uint32_t s_mask = 0xfa008000;
1072 static const uint32_t s_pattern = 0xf2000000;
1073
1074 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeUnmodifiedImmediate, thisObj);
1075
1076protected:
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
1089class ARMv7DOpcodeVMOVDoublePrecision : public ARMv7D32BitOpcode {
1090public:
1091 static const uint32_t s_mask = 0xffe00fd0;
1092 static const uint32_t s_pattern = 0xec400b10;
1093
1094 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVDoublePrecision, thisObj);
1095
1096protected:
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
1105class ARMv7DOpcodeVMOVSinglePrecision : public ARMv7D32BitOpcode {
1106public:
1107 static const uint32_t s_mask = 0xffe00fd0;
1108 static const uint32_t s_pattern = 0xec400a10;
1109
1110 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMOVSinglePrecision, thisObj);
1111
1112protected:
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
1121class ARMv7DOpcodeVMSR : public ARMv7D32BitOpcode {
1122public:
1123 static const uint32_t s_mask = 0xffef0fff;
1124 static const uint32_t s_pattern = 0xeee10a10;
1125
1126 DEFINE_STATIC_FORMAT32(ARMv7DOpcodeVMSR, thisObj);
1127
1128protected:
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
1138using JSC::ARMv7Disassembler::ARMv7DOpcode;
1139
1140#endif // #if USE(ARMV7_DISASSEMBLER)
1141
1142#endif // ARMv7DOpcode_h