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