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#include "config.h" 27 28#if USE(ARMV7_DISASSEMBLER) 29 30#include "ARMv7DOpcode.h" 31 32#include <stdarg.h> 33#include <stdint.h> 34#include <stdio.h> 35#include <string.h> 36 37namespace JSC { namespace ARMv7Disassembler { 38 39ARMv7D16BitOpcode::OpcodeGroup* ARMv7D16BitOpcode::opcodeTable[32]; 40ARMv7D32BitOpcode::OpcodeGroup* ARMv7D32BitOpcode::opcodeTable[16]; 41 42const char* const ARMv7DOpcode::s_conditionNames[16] = { 43 "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", 44 "hi", "ls", "ge", "lt", "gt", "le", "al", "al" 45}; 46 47const char* const ARMv7DOpcode::s_optionName[8] = { 48 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx" 49}; 50 51const char* const ARMv7DOpcode::s_shiftNames[4] = { 52 "lsl", "lsr", "asr", "ror" 53}; 54 55const char* const ARMv7DOpcode::s_specialRegisterNames[3] = { "sp", "lr", "pc" }; 56 57template <typename OpcodeType, typename InstructionType> 58struct OpcodeGroupInitializer { 59 unsigned m_opcodeGroupNumber; 60 InstructionType m_mask; 61 InstructionType m_pattern; 62 const char* (*m_format)(OpcodeType*); 63}; 64 65#define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \ 66{ groupIndex, groupClass::s_mask, groupClass::s_pattern, groupClass::format } 67 68typedef OpcodeGroupInitializer<ARMv7D16BitOpcode, uint16_t> Opcode16GroupInitializer; 69typedef OpcodeGroupInitializer<ARMv7D32BitOpcode, uint32_t> Opcode32GroupInitializer; 70 71static Opcode16GroupInitializer opcode16BitGroupList[] = { 72 OPCODE_GROUP_ENTRY(0x0, ARMv7DOpcodeLogicalImmediateT1), 73 OPCODE_GROUP_ENTRY(0x1, ARMv7DOpcodeLogicalImmediateT1), 74 OPCODE_GROUP_ENTRY(0x2, ARMv7DOpcodeLogicalImmediateT1), 75 OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractT1), 76 OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractImmediate3), 77 OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeMoveImmediateT1), 78 OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeCompareImmediateT1), 79 OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeAddSubtractImmediate8), 80 OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeAddSubtractImmediate8), 81 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingRegisterT1), 82 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeAddRegisterT2), 83 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT2), 84 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT1), 85 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeMoveRegisterT1), 86 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchExchangeT1), 87 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeLoadFromLiteralPool), 88 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeLoadStoreRegisterOffsetT1), 89 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeLoadStoreRegisterOffsetT1), 90 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), 91 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), 92 OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), 93 OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte), 94 OPCODE_GROUP_ENTRY(0x10, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord), 95 OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord), 96 OPCODE_GROUP_ENTRY(0x12, ARMv7DOpcodeLoadStoreRegisterSPRelative), 97 OPCODE_GROUP_ENTRY(0x13, ARMv7DOpcodeLoadStoreRegisterSPRelative), 98 OPCODE_GROUP_ENTRY(0x14, ARMv7DOpcodeGeneratePCRelativeAddress), 99 OPCODE_GROUP_ENTRY(0x15, ARMv7DOpcodeAddSPPlusImmediate), 100 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscCompareAndBranch), 101 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscByteHalfwordOps), 102 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscPushPop), 103 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscAddSubSP), 104 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscHint16), // Needs to be before IfThenT1 105 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscIfThenT1), 106 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscByteHalfwordOps), 107 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscCompareAndBranch), 108 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscPushPop), 109 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscBreakpointT1), 110 OPCODE_GROUP_ENTRY(0x1a, ARMv7DOpcodeBranchConditionalT1), 111 OPCODE_GROUP_ENTRY(0x1b, ARMv7DOpcodeBranchConditionalT1), 112 OPCODE_GROUP_ENTRY(0x1c, ARMv7DOpcodeBranchT2) 113}; 114 115static Opcode32GroupInitializer opcode32BitGroupList[] = { 116 OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeDataProcessingShiftedReg), 117 OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision), 118 OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision), 119 OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer), 120 OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR), 121 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingModifiedImmediate), 122 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeConditionalBranchT3), 123 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchOrBranchLink), 124 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeUnmodifiedImmediate), 125 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeHint32), 126 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeConditionalBranchT3), 127 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeBranchOrBranchLink), 128 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeDataProcessingModifiedImmediate), 129 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeConditionalBranchT3), 130 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeBranchOrBranchLink), 131 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeUnmodifiedImmediate), 132 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeConditionalBranchT3), 133 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeBranchOrBranchLink), 134 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadRegister), 135 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushPopSingle), // Should be before StoreSingle* 136 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleRegister), 137 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate12), 138 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate8), 139 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadSignedImmediate), 140 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadUnsignedImmediate), 141 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLongMultipleDivide), 142 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegShift), 143 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegExtend), 144 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegParallel), 145 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegMisc), 146}; 147 148bool ARMv7DOpcode::s_initialized = false; 149 150void ARMv7DOpcode::init() 151{ 152 if (s_initialized) 153 return; 154 155 ARMv7D16BitOpcode::init(); 156 ARMv7D32BitOpcode::init(); 157 158 s_initialized = true; 159} 160 161void ARMv7DOpcode::startITBlock(unsigned blocksize, unsigned firstCondition) 162{ 163 ASSERT(blocksize > 0 && blocksize <= MaxITBlockSize); 164 m_ITBlocksize = blocksize; 165 m_ITConditionIndex = m_ITBlocksize + 1; 166 m_currentITCondition = 0; 167 m_ifThenConditions[0] = firstCondition; 168} 169 170void ARMv7DOpcode::saveITConditionAt(unsigned blockPosition, unsigned condition) 171{ 172 if (blockPosition < m_ITBlocksize) 173 m_ifThenConditions[blockPosition] = static_cast<unsigned char>(condition); 174} 175 176void ARMv7DOpcode::fetchOpcode(uint16_t*& newPC) 177{ 178 m_bufferOffset = 0; 179 m_formatBuffer[0] = '\0'; 180 m_currentPC = newPC; 181 182 m_opcode = *newPC++; 183 184 if (is32BitInstruction()) { 185 m_opcode <<= 16; 186 m_opcode |= *newPC++; 187 } 188 189 if (m_ITConditionIndex < m_ITBlocksize) 190 m_currentITCondition = m_ifThenConditions[m_ITConditionIndex]; 191 else 192 m_currentITCondition = CondNone; 193} 194 195const char* ARMv7DOpcode::disassemble(uint16_t*& currentPC) 196{ 197 const char* result; 198 fetchOpcode(currentPC); 199 200 if (is32BitInstruction()) 201 result = reinterpret_cast<ARMv7D32BitOpcode*>(this)->doDisassemble(); 202 else 203 result = reinterpret_cast<ARMv7D16BitOpcode*>(this)->doDisassemble(); 204 205 if (startingITBlock()) 206 m_ITConditionIndex = 0; 207 else if (inITBlock() && (++m_ITConditionIndex >= m_ITBlocksize)) 208 endITBlock(); 209 210 return result; 211} 212 213void ARMv7DOpcode::bufferPrintf(const char* format, ...) 214{ 215 if (m_bufferOffset >= bufferSize) 216 return; 217 218 va_list argList; 219 va_start(argList, format); 220 221 m_bufferOffset += vsnprintf(m_formatBuffer + m_bufferOffset, bufferSize - m_bufferOffset, format, argList); 222 223 va_end(argList); 224} 225 226void ARMv7DOpcode::appendInstructionName(const char* instructionName, bool addS) 227{ 228 if (!inITBlock() && !addS) { 229 appendInstructionNameNoITBlock(instructionName); 230 231 return; 232 } 233 234 const char sevenSpaces[8] = " "; 235 236 unsigned length = strlen(instructionName); 237 238 bufferPrintf(" %s", instructionName); 239 if (inITBlock()) { 240 const char* condition = conditionName(m_currentITCondition); 241 length += strlen(condition); 242 appendString(condition); 243 } else if (addS) { 244 length++; 245 appendCharacter('s'); 246 } 247 248 if (length >= 7) 249 length = 6; 250 251 appendString(sevenSpaces + length); 252} 253 254void ARMv7DOpcode::appendRegisterName(unsigned registerNumber) 255{ 256 registerNumber &= 0xf; 257 258 if (registerNumber > 12) { 259 appendString(s_specialRegisterNames[registerNumber - 13]); 260 return; 261 } 262 263 bufferPrintf("r%u", registerNumber); 264} 265 266void ARMv7DOpcode::appendRegisterList(unsigned registers) 267{ 268 unsigned numberPrinted = 0; 269 270 appendCharacter('{'); 271 272 for (unsigned i = 0; i < 16; i++) { 273 if (registers & (1 << i)) { 274 if (numberPrinted++) 275 appendSeparator(); 276 appendRegisterName(i); 277 } 278 } 279 280 appendCharacter('}'); 281} 282 283void ARMv7DOpcode::appendFPRegisterName(char registerPrefix, unsigned registerNumber) 284{ 285 bufferPrintf("%c%u", registerPrefix, registerNumber); 286} 287 288// 16 Bit Instructions 289 290void ARMv7D16BitOpcode::init() 291{ 292 OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize]; 293 294 for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) { 295 opcodeTable[i] = 0; 296 lastGroups[i] = 0; 297 } 298 299 for (unsigned i = 0; i < sizeof(opcode16BitGroupList) / sizeof(Opcode16GroupInitializer); i++) { 300 OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode16BitGroupList[i].m_mask, opcode16BitGroupList[i].m_pattern, opcode16BitGroupList[i].m_format); 301 uint16_t opcodeGroupNumber = opcode16BitGroupList[i].m_opcodeGroupNumber; 302 303 if (!opcodeTable[opcodeGroupNumber]) 304 opcodeTable[opcodeGroupNumber] = newOpcodeGroup; 305 else 306 lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup); 307 lastGroups[opcodeGroupNumber] = newOpcodeGroup; 308 } 309} 310 311const char* ARMv7D16BitOpcode::doDisassemble() 312{ 313 OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)]; 314 315 while (opGroup) { 316 if (opGroup->matches(static_cast<uint16_t>(m_opcode))) 317 return opGroup->format(this); 318 opGroup = opGroup->next(); 319 } 320 321 return defaultFormat(); 322} 323 324const char* ARMv7D16BitOpcode::defaultFormat() 325{ 326 bufferPrintf(" .word %04x", m_opcode); 327 return m_formatBuffer; 328} 329 330const char* ARMv7DOpcodeAddRegisterT2::format() 331{ 332 appendInstructionName("add"); 333 appendRegisterName(rdn()); 334 appendSeparator(); 335 appendRegisterName(rm()); 336 337 return m_formatBuffer; 338} 339 340const char* ARMv7DOpcodeAddSPPlusImmediate::format() 341{ 342 appendInstructionName("add"); 343 appendRegisterName(rd()); 344 appendSeparator(); 345 appendRegisterName(RegSP); 346 appendSeparator(); 347 appendUnsignedImmediate(immediate8()); 348 349 return m_formatBuffer; 350} 351 352const char* const ARMv7DOpcodeAddSubtract::s_opNames[2] = { "add", "sub" }; 353 354const char* ARMv7DOpcodeAddSubtractT1::format() 355{ 356 appendInstructionName(opName(), !inITBlock()); 357 appendRegisterName(rd()); 358 appendSeparator(); 359 appendRegisterName(rn()); 360 appendSeparator(); 361 appendRegisterName(rm()); 362 363 return m_formatBuffer; 364} 365 366const char* ARMv7DOpcodeAddSubtractImmediate3::format() 367{ 368 appendInstructionName(opName(), !inITBlock()); 369 appendRegisterName(rd()); 370 appendSeparator(); 371 appendRegisterName(rn()); 372 appendSeparator(); 373 appendUnsignedImmediate(immediate3()); 374 375 return m_formatBuffer; 376} 377 378const char* ARMv7DOpcodeAddSubtractImmediate8::format() 379{ 380 appendInstructionName(opName(), !inITBlock()); 381 appendRegisterName(rdn()); 382 appendSeparator(); 383 appendUnsignedImmediate(immediate8()); 384 385 return m_formatBuffer; 386} 387 388const char* ARMv7DOpcodeBranchConditionalT1::format() 389{ 390 if (condition() == 0xe) 391 return defaultFormat(); 392 393 if (condition() == 0xf) { 394 appendInstructionName("svc"); 395 appendUnsignedImmediate(offset()); 396 397 return m_formatBuffer; 398 } 399 400 bufferPrintf(" b%-6.6s", conditionName(condition())); 401 appendPCRelativeOffset(static_cast<int32_t>(offset()) + 2); 402 403 return m_formatBuffer; 404} 405 406const char* ARMv7DOpcodeBranchExchangeT1::format() 407{ 408 appendInstructionName(opName()); 409 appendRegisterName(rm()); 410 411 return m_formatBuffer; 412} 413 414const char* ARMv7DOpcodeBranchT2::format() 415{ 416 appendInstructionName("b"); 417 appendPCRelativeOffset(static_cast<int32_t>(immediate11()) + 2); 418 419 return m_formatBuffer; 420} 421 422const char* ARMv7DOpcodeCompareImmediateT1::format() 423{ 424 appendInstructionName("cmp"); 425 appendRegisterName(rn()); 426 appendSeparator(); 427 appendUnsignedImmediate(immediate8()); 428 429 return m_formatBuffer; 430} 431 432const char* ARMv7DOpcodeCompareRegisterT1::format() 433{ 434 appendInstructionName("cmp"); 435 appendRegisterName(rn()); 436 appendSeparator(); 437 appendRegisterName(rm()); 438 439 return m_formatBuffer; 440} 441 442const char* ARMv7DOpcodeCompareRegisterT2::format() 443{ 444 appendInstructionName("compare"); 445 appendRegisterName(rn()); 446 appendSeparator(); 447 appendRegisterName(rm()); 448 449 return m_formatBuffer; 450} 451 452const char* const ARMv7DOpcodeDataProcessingRegisterT1::s_opNames[16] = { 453 "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn" 454}; 455 456const char* ARMv7DOpcodeDataProcessingRegisterT1::format() 457{ 458 appendInstructionName(opName(), inITBlock() && (!(op() == 0x8) || (op() == 0xa) || (op() == 0xb))); 459 appendRegisterName(rdn()); 460 appendSeparator(); 461 appendRegisterName(rm()); 462 if (op() == 0x9) // rsb T1 463 appendString(", #0"); 464 else if (op() == 0xd) { // mul T1 465 appendSeparator(); 466 appendRegisterName(rdn()); 467 } 468 469 return m_formatBuffer; 470} 471 472const char* ARMv7DOpcodeGeneratePCRelativeAddress::format() 473{ 474 appendInstructionName("adr"); 475 appendRegisterName(rd()); 476 appendSeparator(); 477 appendPCRelativeOffset(static_cast<int32_t>(immediate8())); 478 479 return m_formatBuffer; 480} 481 482const char* ARMv7DOpcodeLoadFromLiteralPool::format() 483{ 484 appendInstructionName("ldr"); 485 appendRegisterName(rt()); 486 appendSeparator(); 487 appendPCRelativeOffset(static_cast<int32_t>(immediate8())); 488 489 return m_formatBuffer; 490} 491 492const char* const ARMv7DOpcodeLoadStoreRegisterImmediate::s_opNames[6] = { 493 "str", "ldr", "strb", "ldrb", "strh", "ldrh" 494}; 495 496const char* ARMv7DOpcodeLoadStoreRegisterImmediate::format() 497{ 498 const char* instructionName = opName(); 499 500 if (!instructionName) 501 return defaultFormat(); 502 503 appendInstructionName(opName()); 504 appendRegisterName(rt()); 505 appendSeparator(); 506 appendCharacter('['); 507 appendRegisterName(rn()); 508 if (immediate5()) { 509 appendSeparator(); 510 appendUnsignedImmediate(immediate5() << scale()); 511 } 512 appendCharacter(']'); 513 514 return m_formatBuffer; 515} 516 517const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames[8] = { 518 "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh" 519}; 520 521const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format() 522{ 523 appendInstructionName(opName()); 524 appendRegisterName(rt()); 525 appendSeparator(); 526 appendCharacter('['); 527 appendRegisterName(rn()); 528 appendSeparator(); 529 appendRegisterName(rm()); 530 appendCharacter(']'); 531 532 return m_formatBuffer; 533} 534 535const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format() 536{ 537 appendInstructionName(opName()); 538 appendRegisterName(rt()); 539 appendSeparator(); 540 appendCharacter('['); 541 appendRegisterName(RegSP); 542 if (immediate8()) { 543 appendSeparator(); 544 appendUnsignedImmediate(immediate8() << 2); 545 } 546 appendCharacter(']'); 547 548 return m_formatBuffer; 549} 550 551const char* ARMv7DOpcodeLogicalImmediateT1::format() 552{ 553 if (!op() && !immediate5()) { 554 // mov T2 555 appendInstructionName("movs"); 556 appendRegisterName(rd()); 557 appendSeparator(); 558 appendRegisterName(rm()); 559 560 return m_formatBuffer; 561 } 562 563 appendInstructionName(opName(), !inITBlock()); 564 appendRegisterName(rd()); 565 appendSeparator(); 566 appendRegisterName(rm()); 567 appendSeparator(); 568 appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5()); 569 570 return m_formatBuffer; 571} 572 573const char* ARMv7DOpcodeMiscAddSubSP::format() 574{ 575 appendInstructionName(opName()); 576 appendRegisterName(RegSP); 577 appendSeparator(); 578 appendRegisterName(RegSP); 579 appendSeparator(); 580 appendUnsignedImmediate(immediate7()); 581 582 return m_formatBuffer; 583} 584 585const char* ARMv7DOpcodeMiscBreakpointT1::format() 586{ 587 appendInstructionNameNoITBlock("bkpt"); 588 appendUnsignedImmediate(immediate8()); 589 590 return m_formatBuffer; 591} 592 593const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames[8] = { 594 "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh" 595}; 596 597const char* ARMv7DOpcodeMiscByteHalfwordOps::format() 598{ 599 const char* instructionName = opName(); 600 601 if (!instructionName) 602 return defaultFormat(); 603 604 appendInstructionName(instructionName); 605 appendRegisterName(rd()); 606 appendSeparator(); 607 appendRegisterName(rm()); 608 609 return m_formatBuffer; 610} 611 612const char* ARMv7DOpcodeMiscCompareAndBranch::format() 613{ 614 appendInstructionName(opName()); 615 appendPCRelativeOffset(immediate6() + 2); 616 617 return m_formatBuffer; 618} 619 620const char* const ARMv7DOpcodeMiscHint16::s_opNames[16] = { 621 "nop", "yield", "wfe", "wfi", "sev" 622}; 623 624const char* ARMv7DOpcodeMiscHint16::format() 625{ 626 if (opA() > 4) 627 return defaultFormat(); 628 629 appendInstructionName(opName()); 630 631 return m_formatBuffer; 632} 633 634const char* ARMv7DOpcodeMiscIfThenT1::format() 635{ 636 char opName[6]; 637 opName[0] = 'i'; 638 opName[1] = 't'; 639 640 unsigned condition = firstCondition(); 641 unsigned maskBits = mask(); 642 unsigned blockLength = 0; 643 644 for (unsigned i = 0; i < 4; ++i) { 645 if (maskBits & (1 << i)) { 646 blockLength = 4 - i; 647 break; 648 } 649 } 650 651 startITBlock(blockLength, condition); 652 653 for (unsigned i = 1; i < blockLength; ++i) { 654 unsigned currMaskBit = (maskBits >> (4-i)) & 0x1; 655 opName[i + 1] = (currMaskBit ^ (condition & 1)) ? 'e' : 't'; 656 saveITConditionAt(i, (condition & ~1) | currMaskBit); 657 } 658 opName[blockLength + 1] = '\0'; 659 660 appendInstructionNameNoITBlock(opName); 661 appendString(conditionName(condition)); 662 663 return m_formatBuffer; 664} 665 666const char* ARMv7DOpcodeMiscPushPop::format() 667{ 668 appendInstructionName(opName()); 669 appendRegisterList(registerMask()); 670 671 return m_formatBuffer; 672} 673 674const char* ARMv7DOpcodeMoveImmediateT1::format() 675{ 676 appendInstructionName("mov", !inITBlock()); 677 appendRegisterName(rd()); 678 appendSeparator(); 679 appendUnsignedImmediate(immediate8()); 680 681 return m_formatBuffer; 682} 683 684const char* ARMv7DOpcodeMoveRegisterT1::format() 685{ 686 appendInstructionName("mov"); 687 appendRegisterName(rd()); 688 appendSeparator(); 689 appendRegisterName(rm()); 690 691 return m_formatBuffer; 692} 693 694// 32 bit Intructions 695 696void ARMv7D32BitOpcode::init() 697{ 698 OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize]; 699 700 for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) { 701 opcodeTable[i] = 0; 702 lastGroups[i] = 0; 703 } 704 705 for (unsigned i = 0; i < sizeof(opcode32BitGroupList) / sizeof(Opcode32GroupInitializer); i++) { 706 OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode32BitGroupList[i].m_mask, opcode32BitGroupList[i].m_pattern, opcode32BitGroupList[i].m_format); 707 uint16_t opcodeGroupNumber = opcode32BitGroupList[i].m_opcodeGroupNumber; 708 709 if (!opcodeTable[opcodeGroupNumber]) 710 opcodeTable[opcodeGroupNumber] = newOpcodeGroup; 711 else 712 lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup); 713 lastGroups[opcodeGroupNumber] = newOpcodeGroup; 714 } 715} 716 717const char* ARMv7D32BitOpcode::doDisassemble() 718{ 719 OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)]; 720 721 while (opGroup) { 722 if (opGroup->matches(m_opcode)) 723 return opGroup->format(this); 724 opGroup = opGroup->next(); 725 } 726 727 return defaultFormat(); 728} 729 730const char* ARMv7D32BitOpcode::defaultFormat() 731{ 732 bufferPrintf(" .long %08x", m_opcode); 733 return m_formatBuffer; 734} 735 736const char* ARMv7DOpcodeConditionalBranchT3::format() 737{ 738 if (condition() < 0xe) 739 bufferPrintf(" b%-6.6s", conditionName(condition())); 740 else 741 appendInstructionName("b"); 742 appendPCRelativeOffset(offset() + 2); 743 744 return m_formatBuffer; 745} 746 747const char* ARMv7DOpcodeBranchOrBranchLink::format() 748{ 749 appendInstructionName(isBL() ? "bl" : "b"); 750 appendPCRelativeOffset(offset() + 2); 751 752 return m_formatBuffer; 753} 754 755const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames[16] = { 756 "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0 757}; 758 759void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12) 760{ 761 if (!(immediate12 & 0xc00)) { 762 unsigned immediate = 0; 763 unsigned lower8Bits = immediate12 & 0xff; 764 765 switch ((immediate12 >> 8) & 3) { 766 case 0: 767 immediate = lower8Bits; 768 break; 769 case 1: 770 immediate = (lower8Bits << 16) | lower8Bits; 771 break; 772 case 2: 773 immediate = (lower8Bits << 24) | (lower8Bits << 8); 774 break; 775 case 3: 776 immediate = (lower8Bits << 24) | (lower8Bits << 16) | (lower8Bits << 8) | lower8Bits; 777 break; 778 } 779 appendUnsignedImmediate(immediate); 780 return; 781 } 782 783 unsigned immediate8 = 0x80 | (immediate12 & 0x7f); 784 unsigned shiftAmount = 32 - ((immediate12 >> 7) & 0x1f); 785 786 appendUnsignedImmediate(immediate8 << shiftAmount); 787} 788 789const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format() 790{ 791 if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf)) 792 return defaultFormat(); 793 794 const char* instructionName = opName(); 795 796 if (rn() == 15) { 797 if (op() == 2) { 798 // MOV T2 799 instructionName = sBit() ? "movs" : "mov"; 800 appendInstructionName(instructionName); 801 appendRegisterName(rd()); 802 appendSeparator(); 803 appendModifiedImmediate(immediate12()); 804 805 return m_formatBuffer; 806 } 807 808 if (op() == 3) { 809 // MVN T1 810 instructionName = sBit() ? "mvns" : "mvn"; 811 appendInstructionName(instructionName); 812 appendRegisterName(rd()); 813 appendSeparator(); 814 appendModifiedImmediate(immediate12()); 815 816 return m_formatBuffer; 817 } 818 } 819 820 if (rd() == 15) { 821 if (sBit()) { 822 bool testOrCmpInstruction = false; 823 824 switch (op()) { 825 case 0x0: 826 instructionName = "tst"; 827 testOrCmpInstruction = true; 828 break; 829 case 0x4: 830 instructionName = "teq"; 831 testOrCmpInstruction = true; 832 break; 833 case 0x8: 834 instructionName = "cmn"; 835 testOrCmpInstruction = true; 836 break; 837 case 0xd: 838 instructionName = "cmp"; 839 testOrCmpInstruction = true; 840 break; 841 } 842 843 if (testOrCmpInstruction) { 844 appendInstructionName(instructionName); 845 appendRegisterName(rn()); 846 appendSeparator(); 847 appendModifiedImmediate(immediate12()); 848 849 return m_formatBuffer; 850 } 851 } 852 } 853 854 appendInstructionName(instructionName); 855 appendRegisterName(rd()); 856 appendSeparator(); 857 appendRegisterName(rn()); 858 appendSeparator(); 859 appendModifiedImmediate(immediate12()); 860 861 return m_formatBuffer; 862} 863 864void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type, unsigned immediate) 865{ 866 if (type || immediate) { 867 appendSeparator(); 868 869 if (!immediate) { 870 switch (type) { 871 case 1: 872 case 2: 873 immediate = 32; 874 break; 875 case 3: 876 appendString("rrx"); 877 return; 878 } 879 } 880 881 appendShiftType(type); 882 appendUnsignedImmediate(immediate); 883 } 884} 885 886const char* ARMv7DOpcodeDataProcessingShiftedReg::format() 887{ 888 if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf)) 889 return defaultFormat(); 890 891 if (op() == 6) { 892 // pkhbt or pkhtb 893 if (sBit() || tBit()) 894 return defaultFormat(); 895 896 if (tbBit()) 897 appendInstructionName("pkhtb"); 898 else 899 appendInstructionName("pkhbt"); 900 appendRegisterName(rd()); 901 appendSeparator(); 902 appendRegisterName(rn()); 903 appendSeparator(); 904 appendRegisterName(rm()); 905 appendImmShift(tbBit() << 1, immediate5()); 906 907 return m_formatBuffer; 908 } 909 910 const char* instructionName = opName(); 911 912 if (rn() == 15) { 913 if (op() == 2) { 914 if (!type() && !immediate5()) { 915 // MOV T3 916 instructionName = sBit() ? "movs" : "mov"; 917 appendInstructionName(instructionName); 918 appendRegisterName(rd()); 919 appendSeparator(); 920 appendRegisterName(rm()); 921 922 return m_formatBuffer; 923 } 924 925 if (type() == 3 && !immediate5()) { 926 // RRX T1 927 instructionName = sBit() ? "rrx" : "rrx"; 928 appendInstructionName(instructionName); 929 appendRegisterName(rd()); 930 appendSeparator(); 931 appendRegisterName(rm()); 932 933 return m_formatBuffer; 934 } 935 936 // Logical 937 if (sBit()) 938 bufferPrintf("%ss ", shiftName(type())); 939 else 940 appendInstructionName(shiftName(type())); 941 appendRegisterName(rd()); 942 appendSeparator(); 943 appendRegisterName(rm()); 944 appendSeparator(); 945 appendUnsignedImmediate(immediate5()); 946 947 return m_formatBuffer; 948 } 949 950 if (op() == 3) { 951 // MVN T2 952 instructionName = sBit() ? "mvns" : "mvn"; 953 appendInstructionName(instructionName); 954 appendRegisterName(rd()); 955 appendSeparator(); 956 appendRegisterName(rm()); 957 appendImmShift(type(), immediate5()); 958 959 return m_formatBuffer; 960 } 961 } 962 963 if (rd() == 15) { 964 if (sBit()) { 965 bool testOrCmpInstruction = false; 966 967 switch (op()) { 968 case 0x0: 969 instructionName = "tst"; 970 testOrCmpInstruction = true; 971 break; 972 case 0x4: 973 instructionName = "teq"; 974 testOrCmpInstruction = true; 975 break; 976 case 0x8: 977 instructionName = "cmn"; 978 testOrCmpInstruction = true; 979 break; 980 case 0xd: 981 instructionName = "cmp"; 982 testOrCmpInstruction = true; 983 break; 984 } 985 986 if (testOrCmpInstruction) { 987 appendInstructionName(instructionName); 988 appendRegisterName(rn()); 989 appendSeparator(); 990 appendRegisterName(rm()); 991 appendImmShift(type(), immediate5()); 992 993 return m_formatBuffer; 994 } 995 } 996 } 997 998 appendInstructionName(instructionName); 999 appendRegisterName(rd()); 1000 appendSeparator(); 1001 appendRegisterName(rn()); 1002 appendSeparator(); 1003 appendRegisterName(rm()); 1004 appendImmShift(type(), immediate5()); 1005 1006 return m_formatBuffer; 1007} 1008 1009const char* ARMv7DOpcodeFPTransfer::format() 1010{ 1011 appendInstructionName("vmov"); 1012 1013 if (opL()) { 1014 appendFPRegister(); 1015 appendSeparator(); 1016 } 1017 1018 appendRegisterName(rt()); 1019 1020 if (!opL()) { 1021 appendSeparator(); 1022 appendFPRegister(); 1023 } 1024 1025 return m_formatBuffer; 1026} 1027 1028void ARMv7DOpcodeFPTransfer::appendFPRegister() 1029{ 1030 if (opC()) { 1031 appendFPRegisterName('d', vd()); 1032 bufferPrintf("[%u]", opH()); 1033 } else 1034 appendFPRegisterName('s', vn()); 1035} 1036 1037const char* ARMv7DOpcodeDataProcessingRegShift::format() 1038{ 1039 appendInstructionName(opName()); 1040 appendRegisterName(rd()); 1041 appendSeparator(); 1042 appendRegisterName(rn()); 1043 appendSeparator(); 1044 appendRegisterName(rm()); 1045 1046 return m_formatBuffer; 1047} 1048 1049const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames[8] = { 1050 "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb" 1051}; 1052 1053const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames[8] = { 1054 "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab" 1055}; 1056 1057const char* ARMv7DOpcodeDataProcessingRegExtend::format() 1058{ 1059 const char* instructionName; 1060 1061 if (rn() == 0xf) 1062 instructionName = opExtendName(); 1063 else 1064 instructionName = opExtendAndAddName(); 1065 1066 if (!instructionName) 1067 return defaultFormat(); 1068 1069 appendInstructionName(instructionName); 1070 appendRegisterName(rd()); 1071 appendSeparator(); 1072 appendRegisterName(rn()); 1073 appendSeparator(); 1074 appendRegisterName(rm()); 1075 1076 if (rotate()) { 1077 appendSeparator(); 1078 appendString("ror "); 1079 appendUnsignedImmediate(rotate() * 8); 1080 } 1081 1082 return m_formatBuffer; 1083} 1084 1085const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames[16] = { 1086 "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0, 1087 "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0 1088}; 1089 1090const char* ARMv7DOpcodeDataProcessingRegParallel::format() 1091{ 1092 const char* instructionName; 1093 1094 instructionName = opName(); 1095 1096 if (!instructionName) 1097 return defaultFormat(); 1098 1099 appendInstructionName(instructionName); 1100 appendRegisterName(rd()); 1101 appendSeparator(); 1102 appendRegisterName(rn()); 1103 appendSeparator(); 1104 appendRegisterName(rm()); 1105 1106 return m_formatBuffer; 1107} 1108 1109const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames[16] = { 1110 "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh", 1111 "sel", 0, 0, 0, "clz" 1112}; 1113 1114const char* ARMv7DOpcodeDataProcessingRegMisc::format() 1115{ 1116 const char* instructionName; 1117 1118 instructionName = opName(); 1119 1120 if (!instructionName) 1121 return defaultFormat(); 1122 1123 if ((op1() & 0x1) && (rn() != rm())) 1124 return defaultFormat(); 1125 1126 appendInstructionName(instructionName); 1127 appendRegisterName(rd()); 1128 appendSeparator(); 1129 1130 if (op1() == 0x2) { // sel 1131 appendRegisterName(rn()); 1132 appendSeparator(); 1133 appendRegisterName(rm()); 1134 1135 return m_formatBuffer; 1136 } 1137 1138 appendRegisterName(rm()); 1139 1140 if (!(op1() & 0x1)) { 1141 appendSeparator(); 1142 appendRegisterName(rn()); 1143 } 1144 1145 return m_formatBuffer; 1146} 1147 1148const char* const ARMv7DOpcodeHint32::s_opNames[8] = { 1149 "nop", "yield", "wfe", "wfi", "sev" 1150}; 1151 1152const char* ARMv7DOpcodeHint32::format() 1153{ 1154 if (isDebugHint()) { 1155 appendInstructionName("debug"); 1156 appendUnsignedImmediate(debugOption()); 1157 1158 return m_formatBuffer; 1159 } 1160 1161 if (op() > 0x4) 1162 return defaultFormat(); 1163 1164 appendInstructionName(opName()); 1165 1166 return m_formatBuffer; 1167} 1168 1169const char* const ARMv7DOpcodeDataLoad::s_opNames[8] = { 1170 "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh" 1171}; 1172 1173const char* ARMv7DOpcodeLoadRegister::format() 1174{ 1175 appendInstructionName(opName()); 1176 appendRegisterName(rt()); 1177 appendSeparator(); 1178 appendCharacter('['); 1179 appendRegisterName(rn()); 1180 appendSeparator(); 1181 appendRegisterName(rm()); 1182 if (immediate2()) { 1183 appendSeparator(); 1184 appendUnsignedImmediate(immediate2()); 1185 } 1186 appendCharacter(']'); 1187 1188 return m_formatBuffer; 1189} 1190 1191const char* ARMv7DOpcodeLoadSignedImmediate::format() 1192{ 1193 appendInstructionName(opName()); 1194 appendRegisterName(rt()); 1195 appendSeparator(); 1196 appendCharacter('['); 1197 appendRegisterName(rn()); 1198 if (pBit()) { 1199 if (wBit() || immediate8()) { 1200 appendSeparator(); 1201 if (uBit()) 1202 appendUnsignedImmediate(immediate8()); 1203 else 1204 appendSignedImmediate(0 - static_cast<int>(immediate8())); 1205 } 1206 appendCharacter(']'); 1207 if (wBit()) 1208 appendCharacter('!'); 1209 } else { 1210 appendCharacter(']'); 1211 appendSeparator(); 1212 if (uBit()) 1213 appendUnsignedImmediate(immediate8()); 1214 else 1215 appendSignedImmediate(0 - static_cast<int>(immediate8())); 1216 } 1217 1218 return m_formatBuffer; 1219} 1220 1221const char* ARMv7DOpcodeLoadUnsignedImmediate::format() 1222{ 1223 appendInstructionName(opName()); 1224 appendRegisterName(rt()); 1225 appendSeparator(); 1226 appendCharacter('['); 1227 appendRegisterName(rn()); 1228 if (immediate12()) { 1229 appendSeparator(); 1230 appendUnsignedImmediate(immediate12()); 1231 } 1232 appendCharacter(']'); 1233 1234 return m_formatBuffer; 1235} 1236 1237const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames[8] = { 1238 "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0 1239}; 1240 1241const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames[4] = { 1242 "smlalbb", "smlalbt", "smlaltb", "smlaltt" 1243}; 1244 1245const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames[2] = { 1246 "smlald", "smlaldx" 1247}; 1248 1249const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames[2] = { 1250 "smlsld", "smlsldx" 1251}; 1252 1253const char* ARMv7DOpcodeLongMultipleDivide::format() 1254{ 1255 const char* instructionName = opName(); 1256 1257 switch (op1()) { 1258 case 0x0: 1259 case 0x2: 1260 if (op2()) 1261 return defaultFormat(); 1262 break; 1263 case 0x1: 1264 case 0x3: 1265 if (op2() != 0xf) 1266 return defaultFormat(); 1267 break; 1268 case 0x4: 1269 if ((op2() & 0xc) == 0x8) 1270 instructionName = smlalOpName(); 1271 else if ((op2() & 0xe) == 0xc) 1272 instructionName = smlaldOpName(); 1273 else if (op2()) 1274 return defaultFormat(); 1275 break; 1276 case 0x5: 1277 if ((op2() & 0xe) == 0xc) 1278 instructionName = smlaldOpName(); 1279 else 1280 return defaultFormat(); 1281 break; 1282 case 0x6: 1283 if (op2() == 0x5) 1284 instructionName = "umaal"; 1285 else if (op2()) 1286 return defaultFormat(); 1287 break; 1288 case 0x7: 1289 return defaultFormat(); 1290 break; 1291 } 1292 1293 appendInstructionName(instructionName); 1294 if ((op1() & 0x5) == 0x1) { // sdiv and udiv 1295 if (rt() != 0xf) 1296 return defaultFormat(); 1297 } else { 1298 appendRegisterName(rdLo()); 1299 appendSeparator(); 1300 } 1301 appendRegisterName(rdHi()); 1302 appendSeparator(); 1303 appendRegisterName(rn()); 1304 appendSeparator(); 1305 appendRegisterName(rm()); 1306 1307 return m_formatBuffer; 1308} 1309 1310const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames[16] = { 1311 "addw", 0, "movw", 0, 0, "subw", "movt", 0, 1312 "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0 1313}; 1314 1315const char* ARMv7DOpcodeUnmodifiedImmediate::format() 1316{ 1317 const char* instructionName = opName(); 1318 1319 switch (op() >> 1) { 1320 case 0x0: 1321 case 0x5: 1322 if (rn() == 0xf) 1323 instructionName = "adr"; 1324 break; 1325 case 0x9: 1326 if (immediate5()) 1327 instructionName = "ssat"; 1328 break; 1329 case 0xb: 1330 if (rn() == 0xf) 1331 instructionName = "bfc"; 1332 break; 1333 case 0xd: 1334 if (immediate5()) 1335 instructionName = "usat"; 1336 break; 1337 } 1338 1339 if (!instructionName) 1340 return defaultFormat(); 1341 1342 appendInstructionName(instructionName); 1343 appendRegisterName(rd()); 1344 appendSeparator(); 1345 1346 if ((op() & 0x17) == 0x4) { // movw or movt 1347 appendUnsignedImmediate(immediate16()); 1348 1349 return m_formatBuffer; 1350 } 1351 1352 if (!op() || (op() == 0xa)) { // addw, subw and adr 1353 if (rn() == 0xf) { 1354 int32_t offset; 1355 1356 if ((op() == 0xa) && (rn() == 0xf)) 1357 offset = 0 - static_cast<int32_t>(immediate12()); 1358 else 1359 offset = static_cast<int32_t>(immediate12()); 1360 1361 appendPCRelativeOffset(offset); 1362 1363 return m_formatBuffer; 1364 } 1365 1366 appendRegisterName(rn()); 1367 appendSeparator(); 1368 appendUnsignedImmediate(immediate12()); 1369 1370 return m_formatBuffer; 1371 } 1372 1373 if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16 1374 appendSeparator(); 1375 appendUnsignedImmediate(bitNumOrSatImmediate() + 1); 1376 appendSeparator(); 1377 appendRegisterName(rn()); 1378 if (shBit() || immediate5()) { 1379 appendSeparator(); 1380 appendShiftType(shBit() << 1); 1381 appendUnsignedImmediate(immediate5()); 1382 } 1383 1384 return m_formatBuffer; 1385 } 1386 1387 if (op() == 0x16) { // bfi or bfc 1388 int width = static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1; 1389 1390 if (width < 0) 1391 return defaultFormat(); 1392 1393 if (rn() != 0xf) { 1394 appendSeparator(); 1395 appendRegisterName(rn()); 1396 } 1397 appendSeparator(); 1398 appendUnsignedImmediate(immediate5()); 1399 appendSeparator(); 1400 appendSignedImmediate(width); 1401 1402 return m_formatBuffer; 1403 } 1404 1405 // Must be sbfx or ubfx 1406 appendSeparator(); 1407 appendRegisterName(rn()); 1408 appendSeparator(); 1409 appendUnsignedImmediate(immediate5()); 1410 appendSeparator(); 1411 appendUnsignedImmediate(bitNumOrSatImmediate() + 1); 1412 1413 return m_formatBuffer; 1414} 1415 1416const char* const ARMv7DOpcodeDataStoreSingle::s_opNames[4] = { 1417 "strb", "strh", "str", 0 1418}; 1419 1420const char* ARMv7DOpcodeDataPushPopSingle::format() 1421{ 1422 appendInstructionName(opName()); 1423 appendRegisterName(rt()); 1424 1425 return m_formatBuffer; 1426} 1427 1428const char* ARMv7DOpcodeStoreSingleImmediate12::format() 1429{ 1430 appendInstructionName(opName()); 1431 appendRegisterName(rt()); 1432 appendSeparator(); 1433 appendCharacter('['); 1434 appendRegisterName(rn()); 1435 if (immediate12()) { 1436 appendSeparator(); 1437 appendUnsignedImmediate(immediate12()); 1438 } 1439 appendCharacter(']'); 1440 1441 return m_formatBuffer; 1442} 1443 1444const char* ARMv7DOpcodeStoreSingleImmediate8::format() 1445{ 1446 if (pBit() && uBit() && !wBit()) // Really undecoded strt 1447 return defaultFormat(); 1448 1449 if ((rn() == 0xf) || (!pBit() && !wBit())) 1450 return defaultFormat(); 1451 1452 appendInstructionName(opName()); 1453 appendRegisterName(rt()); 1454 appendSeparator(); 1455 appendCharacter('['); 1456 appendRegisterName(rn()); 1457 1458 if (!pBit()) { 1459 appendCharacter(']'); 1460 appendSeparator(); 1461 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8()))); 1462 1463 return m_formatBuffer; 1464 } 1465 1466 if (immediate8()) { 1467 appendSeparator(); 1468 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8()))); 1469 } 1470 appendCharacter(']'); 1471 1472 if (wBit()) 1473 appendCharacter('!'); 1474 1475 return m_formatBuffer; 1476} 1477 1478const char* ARMv7DOpcodeStoreSingleRegister::format() 1479{ 1480 appendInstructionName(opName()); 1481 appendRegisterName(rt()); 1482 appendSeparator(); 1483 appendCharacter('['); 1484 appendRegisterName(rn()); 1485 appendSeparator(); 1486 appendRegisterName(rm()); 1487 if (immediate2()) { 1488 appendSeparator(); 1489 appendString("lsl "); 1490 appendUnsignedImmediate(immediate2()); 1491 } 1492 appendCharacter(']'); 1493 1494 return m_formatBuffer; 1495} 1496 1497const char* ARMv7DOpcodeVMOVDoublePrecision::format() 1498{ 1499 appendInstructionName("vmov"); 1500 if (op()) { 1501 appendRegisterName(rt()); 1502 appendSeparator(); 1503 appendRegisterName(rt2()); 1504 appendSeparator(); 1505 } 1506 1507 appendFPRegisterName('d', vm()); 1508 1509 if (!op()) { 1510 appendSeparator(); 1511 appendRegisterName(rt()); 1512 appendSeparator(); 1513 appendRegisterName(rt2()); 1514 } 1515 1516 return m_formatBuffer; 1517} 1518 1519const char* ARMv7DOpcodeVMOVSinglePrecision::format() 1520{ 1521 appendInstructionName("vmov"); 1522 if (op()) { 1523 appendRegisterName(rt()); 1524 appendSeparator(); 1525 appendRegisterName(rt2()); 1526 appendSeparator(); 1527 } 1528 1529 appendFPRegisterName('s', vm()); 1530 appendSeparator(); 1531 appendFPRegisterName('s', (vm() + 1) % 32); 1532 1533 if (!op()) { 1534 appendSeparator(); 1535 appendRegisterName(rt()); 1536 appendSeparator(); 1537 appendRegisterName(rt2()); 1538 } 1539 1540 return m_formatBuffer; 1541} 1542 1543const char* ARMv7DOpcodeVMSR::format() 1544{ 1545 appendInstructionName("vmrs"); 1546 if (opL()) { 1547 if (rt() == 0xf) 1548 appendString("apsr_nzcv"); 1549 else 1550 appendRegisterName(rt()); 1551 appendSeparator(); 1552 } 1553 1554 appendString("fpscr"); 1555 1556 if (!opL()) { 1557 appendSeparator(); 1558 appendRegisterName(rt()); 1559 } 1560 1561 return m_formatBuffer; 1562} 1563 1564} } // namespace JSC::ARMv7Disassembler 1565 1566#endif // #if USE(ARMV7_DISASSEMBLER) 1567