]> git.saurik.com Git - apple/javascriptcore.git/blame - disassembler/ARM64/A64DOpcode.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / disassembler / ARM64 / A64DOpcode.h
CommitLineData
93a37866
A
1/*
2 * Copyright (C) 2012 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 A64DOpcode_h
27#define A64DOpcode_h
28
29#include <wtf/Assertions.h>
30#include <stdint.h>
31
32namespace JSC { namespace ARM64Disassembler {
33
34class A64DOpcode {
35private:
36 class OpcodeGroup {
37 public:
38 OpcodeGroup(uint32_t opcodeMask, uint32_t opcodePattern, const char* (*format)(A64DOpcode*))
39 : m_opcodeMask(opcodeMask)
40 , m_opcodePattern(opcodePattern)
41 , m_format(format)
42 , m_next(0)
43 {
44 }
45
46 void setNext(OpcodeGroup* next)
47 {
48 m_next = next;
49 }
50
51 OpcodeGroup* next()
52 {
53 return m_next;
54 }
55
56 bool matches(uint32_t opcode)
57 {
58 return (opcode & m_opcodeMask) == m_opcodePattern;
59 }
60
61 const char* format(A64DOpcode* thisObj)
62 {
63 return m_format(thisObj);
64 }
65
66 private:
67 uint32_t m_opcodeMask;
68 uint32_t m_opcodePattern;
69 const char* (*m_format)(A64DOpcode*);
70 OpcodeGroup* m_next;
71 };
72
73public:
74 static void init();
75
76 A64DOpcode()
77 : m_opcode(0)
78 , m_bufferOffset(0)
79 {
80 init();
81 m_formatBuffer[0] = '\0';
82 }
83
84 const char* disassemble(uint32_t* currentPC);
85
86protected:
87 void setPCAndOpcode(uint32_t*, uint32_t);
88 const char* format();
89
90 static const char* const s_conditionNames[16];
91 static const char* const s_shiftNames[4];
92 static const char* const s_optionName[8];
93 static const char s_FPRegisterPrefix[5];
94
95 static const char* conditionName(unsigned condition) { return s_conditionNames[condition & 0xf]; }
96 static const char* shiftName(unsigned shiftValue) { return s_shiftNames[shiftValue & 0x3]; }
97 const char* optionName() { return s_optionName[option()]; }
98 static char FPRegisterPrefix(unsigned FPRegisterSize)
99 {
100 if (FPRegisterSize > 4)
101 FPRegisterSize = 4;
102 return s_FPRegisterPrefix[FPRegisterSize];
103 }
104
105 unsigned opcodeGroupNumber(uint32_t opcode) { return (opcode >> 24) & 0x1f; }
106
107 bool is64Bit() { return m_opcode & 0x80000000; }
108 unsigned size() { return m_opcode >> 30; }
109 unsigned option() { return (m_opcode >> 13) & 0x7; }
110 unsigned rd() { return m_opcode & 0x1f; }
111 unsigned rt() { return m_opcode & 0x1f; }
112 unsigned rn() { return (m_opcode >> 5) & 0x1f; }
113 unsigned rm() { return (m_opcode >> 16) & 0x1f; }
114
115 void bufferPrintf(const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3);
116
117 void appendInstructionName(const char* instructionName)
118 {
119 bufferPrintf(" %-7.7s", instructionName);
120 }
121
122 void appendRegisterName(unsigned registerNumber, bool is64Bit = true);
123 void appendSPOrRegisterName(unsigned registerNumber, bool is64Bit = true)
124 {
125 if (registerNumber == 31) {
126 bufferPrintf(is64Bit ? "sp" : "wsp");
127 return;
128 }
129 appendRegisterName(registerNumber, is64Bit);
130 }
131
132 void appendZROrRegisterName(unsigned registerNumber, bool is64Bit = true)
133 {
134 if (registerNumber == 31) {
135 bufferPrintf(is64Bit ? "xzr" : "wzr");
136 return;
137 }
138 appendRegisterName(registerNumber, is64Bit);
139 }
140
141 void appendFPRegisterName(unsigned registerNumber, unsigned registerSize);
142
143 void appendSeparator()
144 {
145 bufferPrintf(", ");
146 }
147
148 void appendCharacter(const char c)
149 {
150 bufferPrintf("%c", c);
151 }
152
153 void appendString(const char* string)
154 {
155 bufferPrintf("%s", string);
156 }
157
158 void appendShiftType(unsigned shiftValue)
159 {
160 bufferPrintf("%s ", shiftName(shiftValue));
161 }
162
163 void appendSignedImmediate(int immediate)
164 {
165 bufferPrintf("#%d", immediate);
166 }
167
168 void appendUnsignedImmediate(unsigned immediate)
169 {
170 bufferPrintf("#%u", immediate);
171 }
172
173 void appendUnsignedImmediate64(uint64_t immediate)
174 {
175 bufferPrintf("#0x%llx", immediate);
176 }
177
178 void appendPCRelativeOffset(uint32_t* pc, int32_t immediate)
179 {
180 bufferPrintf("0x%llx", reinterpret_cast<uint64_t>(pc + immediate));
181 }
182
183 void appendShiftAmount(unsigned amount)
184 {
185 bufferPrintf("lsl #%u", 16 * amount);
186 }
187
188 static const int bufferSize = 81;
189
190 char m_formatBuffer[bufferSize];
191 uint32_t* m_currentPC;
192 uint32_t m_opcode;
193 int m_bufferOffset;
194
195private:
196 static OpcodeGroup* opcodeTable[32];
197
198 static bool s_initialized;
199};
200
201#define DEFINE_STATIC_FORMAT(klass, thisObj) \
202 static const char* format(A64DOpcode* thisObj) { return reinterpret_cast< klass *>(thisObj)->format(); }
203
204class A64DOpcodeAddSubtract : public A64DOpcode {
205private:
206 static const char* const s_opNames[4];
207
208public:
209 const char* opName() { return s_opNames[opAndS()]; }
210 const char* cmpName() { return op() ? "cmp" : "cmn"; }
211
212 bool isCMP() { return (sBit() && rd() == 31); }
213 unsigned op() { return (m_opcode >> 30) & 0x1; }
214 unsigned sBit() { return (m_opcode >> 29) & 0x1; }
215 unsigned opAndS() { return (m_opcode >> 29) & 0x3; }
216};
217
218class A64DOpcodeAddSubtractImmediate : public A64DOpcodeAddSubtract {
219public:
220 static const uint32_t mask = 0x1f000000;
221 static const uint32_t pattern = 0x11000000;
222
223 DEFINE_STATIC_FORMAT(A64DOpcodeAddSubtractImmediate, thisObj);
224
225 const char* format();
226
227 bool isMovSP() { return (!opAndS() && !immed12() && ((rd() == 31) || rn() == 31)); }
228 unsigned shift() { return (m_opcode >> 22) & 0x3; }
229 unsigned immed12() { return (m_opcode >> 10) & 0xfff; }
230};
231
232class A64DOpcodeAddSubtractExtendedRegister : public A64DOpcodeAddSubtract {
233public:
234 static const uint32_t mask = 0x1fe00000;
235 static const uint32_t pattern = 0x0b200000;
236
237 DEFINE_STATIC_FORMAT(A64DOpcodeAddSubtractExtendedRegister, thisObj);
238
239 const char* format();
240
241 unsigned immediate3() { return (m_opcode >> 10) & 0x7; }
242};
243
244class A64DOpcodeAddSubtractShiftedRegister : public A64DOpcodeAddSubtract {
245public:
246 static const uint32_t mask = 0x1f200000;
247 static const uint32_t pattern = 0x0b000000;
248
249 DEFINE_STATIC_FORMAT(A64DOpcodeAddSubtractShiftedRegister, thisObj);
250
251 const char* format();
252
253 bool isNeg() { return (op() && rn() == 31); }
254 const char* negName() { return sBit() ? "negs" : "neg"; }
255 unsigned shift() { return (m_opcode >> 22) & 0x3; }
256 int immediate6() { return (static_cast<int>((m_opcode >> 10) & 0x3f) << 26) >> 26; }
257};
258
259class A64DOpcodeBitfield : public A64DOpcode {
260private:
261 static const char* const s_opNames[3];
262 static const char* const s_extendPseudoOpNames[3][3];
263 static const char* const s_insertOpNames[3];
264 static const char* const s_extractOpNames[3];
265
266public:
267 static const uint32_t mask = 0x1f800000;
268 static const uint32_t pattern = 0x13000000;
269
270 DEFINE_STATIC_FORMAT(A64DOpcodeBitfield, thisObj);
271
272 const char* format();
273
274 const char* opName() { return s_opNames[opc()]; }
275 const char* extendPseudoOpNames(unsigned opSize) { return s_extendPseudoOpNames[opc()][opSize]; }
276 const char* insertOpNames() { return s_insertOpNames[opc()]; }
277 const char* extractOpNames() { return s_extractOpNames[opc()]; }
278
279 unsigned opc() { return (m_opcode >> 29) & 0x3; }
280 unsigned nBit() { return (m_opcode >> 22) & 0x1; }
281 unsigned immediateR() { return (m_opcode >> 16) & 0x3f; }
282 unsigned immediateS() { return (m_opcode >> 10) & 0x3f; }
283};
284
285class A64DOpcodeCompareAndBranchImmediate : public A64DOpcode {
286public:
287 static const uint32_t mask = 0x7e000000;
288 static const uint32_t pattern = 0x34000000;
289
290 DEFINE_STATIC_FORMAT(A64DOpcodeCompareAndBranchImmediate, thisObj);
291
292 const char* format();
293
294 unsigned opBit() { return (m_opcode >> 24) & 0x1; }
295 int immediate19() { return (static_cast<int>((m_opcode >> 5) & 0x7ffff) << 13) >> 13; }
296};
297
298class A64DOpcodeConditionalBranchImmediate : public A64DOpcode {
299public:
300 static const uint32_t mask = 0xff000010;
301 static const uint32_t pattern = 0x54000000;
302
303 DEFINE_STATIC_FORMAT(A64DOpcodeConditionalBranchImmediate, thisObj);
304
305 const char* format();
306
307 unsigned condition() { return m_opcode & 0xf; }
308 int immediate19() { return (static_cast<int>((m_opcode >> 5) & 0x7ffff) << 13) >> 13; }
309};
310
311class A64DOpcodeConditionalSelect : public A64DOpcode {
312private:
313 static const char* const s_opNames[4];
314
315public:
316 static const uint32_t mask = 0x1fe00010;
317 static const uint32_t pattern = 0x1a800000;
318
319 DEFINE_STATIC_FORMAT(A64DOpcodeConditionalSelect, thisObj);
320
321 const char* format();
322
323 const char* opName() { return s_opNames[opNum()]; }
324 unsigned opNum() { return (op() << 1 | (op2() & 0x1)); }
325 unsigned op() { return (m_opcode >> 30) & 0x1; }
326 unsigned sBit() { return (m_opcode >> 29) & 0x1; }
327 unsigned condition() { return (m_opcode >> 12) & 0xf; }
328 unsigned op2() { return (m_opcode >> 10) & 0x3; }
329};
330
331class A64DOpcodeDataProcessing2Source : public A64DOpcode {
332private:
333 static const char* const s_opNames[8];
334
335public:
336 static const uint32_t mask = 0x5fe00000;
337 static const uint32_t pattern = 0x1ac00000;
338
339 DEFINE_STATIC_FORMAT(A64DOpcodeDataProcessing2Source, thisObj);
340
341 const char* format();
342
343 const char* opName() { return s_opNames[opNameIndex()]; }
344 unsigned sBit() { return (m_opcode >> 29) & 0x1; }
345 unsigned opCode() { return (m_opcode >> 10) & 0x3f; }
346 unsigned opNameIndex() { return ((m_opcode >> 11) & 0x4) | ((m_opcode >> 10) & 0x3); }
347};
348
349class A64DOpcodeDataProcessing3Source : public A64DOpcode {
350private:
351 static const char* const s_opNames[16];
352 static const char* const s_pseudoOpNames[16];
353
354public:
355 static const uint32_t mask = 0x1f000000;
356 static const uint32_t pattern = 0x1b000000;
357
358 DEFINE_STATIC_FORMAT(A64DOpcodeDataProcessing3Source, thisObj);
359
360 const char* format();
361
362 const char* opName() { return ra() == 31 ? s_opNames[opNum() & 0xf] : s_pseudoOpNames[opNum() & 0xf]; }
363 unsigned ra() { return (m_opcode >> 10) & 0x1f; }
364 unsigned op54() { return (m_opcode >> 29) & 0x3; }
365 unsigned op31() { return (m_opcode >> 21) & 0x7; }
366 unsigned op0() { return (m_opcode >> 15) & 0x1; }
367 unsigned opNum() { return ((m_opcode >> 25) & 0x30) | ((m_opcode >> 20) & 0xe) | ((m_opcode >> 15) & 0x1); }
368};
369
370class A64OpcodeExceptionGeneration : public A64DOpcode {
371public:
372 static const uint32_t mask = 0xff000010;
373 static const uint32_t pattern = 0xd4000000;
374
375 DEFINE_STATIC_FORMAT(A64OpcodeExceptionGeneration, thisObj);
376
377 const char* format();
378
379 unsigned opc() { return (m_opcode>>21) & 0x7; }
380 unsigned op2() { return (m_opcode>>2) & 0x7; }
381 unsigned ll() { return m_opcode & 0x3; }
382 int immediate16() { return (static_cast<int>((m_opcode >> 5) & 0xffff) << 16) >> 16; }
383};
384
385class A64DOpcodeExtract : public A64DOpcode {
386public:
387 static const uint32_t mask = 0x1f800000;
388 static const uint32_t pattern = 0x13800000;
389
390 DEFINE_STATIC_FORMAT(A64DOpcodeExtract, thisObj);
391
392 const char* format();
393
394 unsigned op21() { return (m_opcode >> 29) & 0x3; }
395 unsigned nBit() { return (m_opcode >> 22) & 0x1; }
396 unsigned o0Bit() { return (m_opcode >> 21) & 0x1; }
397 unsigned immediateS() { return (m_opcode >> 10) & 0x3f; }
398};
399
400class A64DOpcodeFloatingPointOps : public A64DOpcode {
401public:
402 unsigned mBit() { return (m_opcode >> 31) & 0x1; }
403 unsigned sBit() { return (m_opcode >> 29) & 0x1; }
404 unsigned type() { return (m_opcode >> 22) & 0x3; }
405};
406
407class A64DOpcodeFloatingPointCompare : public A64DOpcodeFloatingPointOps {
408private:
409 static const char* const s_opNames[16];
410
411public:
412 static const uint32_t mask = 0x5f203c00;
413 static const uint32_t pattern = 0x1e202000;
414
415 DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointCompare, thisObj);
416
417 const char* format();
418
419 const char* opName() { return (opNum() & 0x2) ? "fcmpe" : "fcmp"; }
420
421 unsigned op() { return (m_opcode >> 14) & 0x3; }
422 unsigned opCode2() { return m_opcode & 0x1f; }
423 unsigned opNum() { return (m_opcode >> 3) & 0x3; }
424};
425
426class A64DOpcodeFloatingPointDataProcessing1Source : public A64DOpcodeFloatingPointOps {
427private:
428 static const char* const s_opNames[16];
429
430public:
431 static const uint32_t mask = 0x5f207c00;
432 static const uint32_t pattern = 0x1e204000;
433
434 DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointDataProcessing1Source, thisObj);
435
436 const char* format();
437
438 const char* opName() { return s_opNames[opNum()]; }
439
440 unsigned opNum() { return (m_opcode >> 15) & 0x3f; }
441};
442
443class A64DOpcodeFloatingPointDataProcessing2Source : public A64DOpcodeFloatingPointOps {
444private:
445 static const char* const s_opNames[16];
446
447public:
448 static const uint32_t mask = 0x5f200800;
449 static const uint32_t pattern = 0x1e200800;
450
451 DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointDataProcessing2Source, thisObj);
452
453 const char* format();
454
455 const char* opName() { return s_opNames[opNum()]; }
456
457 unsigned opNum() { return (m_opcode >> 12) & 0xf; }
458};
459
460class A64DOpcodeFloatingFixedPointConversions : public A64DOpcodeFloatingPointOps {
461private:
462 static const char* const s_opNames[4];
463
464public:
465 static const uint32_t mask = 0x5f200000;
466 static const uint32_t pattern = 0x1e000000;
467
468 DEFINE_STATIC_FORMAT(A64DOpcodeFloatingFixedPointConversions, thisObj);
469
470 const char* format();
471
472 const char* opName() { return s_opNames[opNum()]; }
473 unsigned rmode() { return (m_opcode >> 19) & 0x3; }
474 unsigned opcode() { return (m_opcode >> 16) & 0x7; }
475 unsigned scale() { return (m_opcode >> 10) & 0x3f; }
476 unsigned opNum() { return (m_opcode >> 16) & 0x3; }
477};
478
479class A64DOpcodeFloatingPointIntegerConversions : public A64DOpcodeFloatingPointOps {
480private:
481 static const char* const s_opNames[32];
482
483public:
484 static const uint32_t mask = 0x5f20fc00;
485 static const uint32_t pattern = 0x1e200000;
486
487 DEFINE_STATIC_FORMAT(A64DOpcodeFloatingPointIntegerConversions, thisObj);
488
489 const char* format();
490
491 const char* opName() { return s_opNames[opNum()]; }
492 unsigned rmode() { return (m_opcode >> 19) & 0x3; }
493 unsigned opcode() { return (m_opcode >> 16) & 0x7; }
494 unsigned opNum() { return (m_opcode >> 16) & 0x1f; }
495};
496
497class A64DOpcodeHint : public A64DOpcode {
498private:
499 static const char* const s_opNames[6];
500
501public:
502 static const uint32_t mask = 0xfffff01f;
503 static const uint32_t pattern = 0xd503201f;
504
505 DEFINE_STATIC_FORMAT(A64DOpcodeHint, thisObj);
506
507 const char* format();
508
509 const char* opName() { return immediate7() <= 5 ? s_opNames[immediate7()] : "hint"; }
510 unsigned immediate7() { return (m_opcode >> 5) & 0x7f; }
511};
512
513class A64DOpcodeLoadStore : public A64DOpcode {
514private:
515 static const char* const s_opNames[32];
516
517protected:
518 const char* opName()
519 {
520 return s_opNames[opNumber()];
521 }
522
523 unsigned size() { return (m_opcode >> 30) & 0x3; }
524 unsigned vBit() { return (m_opcode >> 26) & 0x1; }
525 unsigned opc() { return (m_opcode >> 22) & 0x3; }
526 unsigned opNumber() { return (size() <<3 ) | (vBit() << 2) | opc(); }
527 bool is64BitRT() { return ((opNumber() & 0x17) == 0x02) || ((opNumber() & 0x1e) == 0x18); }
528};
529
530class A64DOpcodeLoadStoreImmediate : public A64DOpcodeLoadStore {
531private:
532 static const char* const s_unprivilegedOpNames[32];
533 static const char* const s_unscaledOpNames[32];
534
535public:
536 static const uint32_t mask = 0x3b200000;
537 static const uint32_t pattern = 0x38000000;
538
539 DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreImmediate, thisObj);
540
541 const char* format();
542
543 const char* unprivilegedOpName()
544 {
545 return s_unprivilegedOpNames[opNumber()];
546 }
547 const char* unscaledOpName()
548 {
549 return s_unscaledOpNames[opNumber()];
550 }
551 unsigned type() { return (m_opcode >> 10) & 0x3; }
552 int immediate9() { return (static_cast<int>((m_opcode >> 12) & 0x1ff) << 23) >> 23; }
553};
554
555class A64DOpcodeLoadStoreRegisterOffset : public A64DOpcodeLoadStore {
556public:
557 static const uint32_t mask = 0x3b200c00;
558 static const uint32_t pattern = 0x38200800;
559
560 DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreRegisterOffset, thisObj);
561
562 const char* format();
563
564 unsigned option() { return (m_opcode >> 13) & 0x7; }
565 int sBit() { return (m_opcode >> 12) & 0x1; }
566};
567
81345200
A
568class A64DOpcodeLoadStoreRegisterPair : public A64DOpcodeLoadStore {
569public:
570 static const uint32_t mask = 0x3a000000;
571 static const uint32_t pattern = 0x28000000;
572
573 DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreRegisterPair, thisObj);
574
575 const char* format();
576 const char* opName();
577
578 unsigned rt2() { return (m_opcode >> 10) & 0x1f; }
579 int immediate7() { return (static_cast<int>((m_opcode >> 15) & 0x7f) << 25) >> 25; }
580 unsigned offsetMode() { return (m_opcode >> 23) & 0x7; }
581 int lBit() { return (m_opcode >> 22) & 0x1; }
582};
583
93a37866
A
584class A64DOpcodeLoadStoreUnsignedImmediate : public A64DOpcodeLoadStore {
585public:
586 static const uint32_t mask = 0x3b000000;
587 static const uint32_t pattern = 0x39000000;
588
589 DEFINE_STATIC_FORMAT(A64DOpcodeLoadStoreUnsignedImmediate, thisObj);
590
591 const char* format();
592
593 unsigned immediate12() { return (m_opcode >> 10) & 0xfff; }
594};
595
596class A64DOpcodeLogical : public A64DOpcode {
597private:
598 static const char* const s_opNames[8];
599
600public:
601 const char* opName(unsigned opNumber)
602 {
603 return s_opNames[opNumber & 0x7];
604 }
605
606 unsigned opc() { return (m_opcode >> 29) & 0x3; }
607 unsigned nBit() { return (m_opcode >> 21) & 0x1; }
608};
609
610class A64DOpcodeLogicalImmediate : public A64DOpcodeLogical {
611public:
612 static const uint32_t mask = 0x1f800000;
613 static const uint32_t pattern = 0x12000000;
614
615 DEFINE_STATIC_FORMAT(A64DOpcodeLogicalImmediate, thisObj);
616
617 const char* format();
618
619 bool isTst() { return ((opNumber() == 6) && (rd() == 31)); }
620 bool isMov() { return ((opNumber() == 2) && (rn() == 31)); }
621 unsigned opNumber() { return opc() << 1; }
622 unsigned nBit() { return (m_opcode >> 22) & 0x1; }
623 unsigned immediateR() { return (m_opcode >> 16) & 0x3f; }
624 unsigned immediateS() { return (m_opcode >> 10) & 0x3f; }
625};
626
627class A64DOpcodeLogicalShiftedRegister : public A64DOpcodeLogical {
628public:
629 static const uint32_t mask = 0x1f000000;
630 static const uint32_t pattern = 0x0a000000;
631
632 DEFINE_STATIC_FORMAT(A64DOpcodeLogicalShiftedRegister, thisObj);
633
634 const char* format();
635
636 bool isTst() { return ((opNumber() == 6) && (rd() == 31)); }
637 bool isMov() { return ((opNumber() == 2) && (rn() == 31)); }
638 unsigned opNumber() { return (opc() << 1) | nBit(); }
639 unsigned shift() { return (m_opcode >> 22) & 0x3; }
640 int immediate6() { return (static_cast<int>((m_opcode >> 10) & 0x3f) << 26) >> 26; }
641};
642
643class A64DOpcodeMoveWide : public A64DOpcode {
644private:
645 static const char* const s_opNames[4];
646
647public:
648 static const uint32_t mask = 0x1f800000;
649 static const uint32_t pattern = 0x12800000;
650
651 DEFINE_STATIC_FORMAT(A64DOpcodeMoveWide, thisObj);
652
653 const char* format();
654
655 const char* opName() { return s_opNames[opc()]; }
656 unsigned opc() { return (m_opcode >> 29) & 0x3; }
657 unsigned hw() { return (m_opcode >> 21) & 0x3; }
658 unsigned immediate16() { return (m_opcode >> 5) & 0xffff; }
659};
660
661class A64DOpcodeTestAndBranchImmediate : public A64DOpcode {
662public:
663 static const uint32_t mask = 0x7e000000;
664 static const uint32_t pattern = 0x36000000;
665
666 DEFINE_STATIC_FORMAT(A64DOpcodeTestAndBranchImmediate, thisObj);
667
668 const char* format();
669
670 unsigned bitNumber() { return ((m_opcode >> 26) & 0x20) | ((m_opcode >> 19) & 0x1f); }
671 unsigned opBit() { return (m_opcode >> 24) & 0x1; }
672 int immediate14() { return (static_cast<int>((m_opcode >> 5) & 0x3fff) << 18) >> 18; }
673};
674
675class A64DOpcodeUnconditionalBranchImmediate : public A64DOpcode {
676public:
677 static const uint32_t mask = 0x7c000000;
678 static const uint32_t pattern = 0x14000000;
679
680 DEFINE_STATIC_FORMAT(A64DOpcodeUnconditionalBranchImmediate, thisObj);
681
682 const char* format();
683
684 unsigned op() { return (m_opcode >> 31) & 0x1; }
685 int immediate26() { return (static_cast<int>(m_opcode & 0x3ffffff) << 6) >> 6; }
686};
687
688class A64DOpcodeUnconditionalBranchRegister : public A64DOpcode {
689private:
690 static const char* const s_opNames[8];
691
692public:
693 static const uint32_t mask = 0xfe1ffc1f;
694 static const uint32_t pattern = 0xd61f0000;
695
696 DEFINE_STATIC_FORMAT(A64DOpcodeUnconditionalBranchRegister, thisObj);
697
698 const char* format();
699
700 const char* opName() { return s_opNames[opc()]; }
701 unsigned opc() { return (m_opcode >> 21) & 0xf; }
702};
703
704} } // namespace JSC::ARM64Disassembler
705
706using JSC::ARM64Disassembler::A64DOpcode;
707
708#endif // A64DOpcode_h