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 1143