2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #if USE(ARMV7_DISASSEMBLER)
30 #include "ARMv7DOpcode.h"
37 namespace JSC
{ namespace ARMv7Disassembler
{
39 ARMv7D16BitOpcode::OpcodeGroup
* ARMv7D16BitOpcode::opcodeTable
[32];
40 ARMv7D32BitOpcode::OpcodeGroup
* ARMv7D32BitOpcode::opcodeTable
[16];
42 const char* const ARMv7DOpcode::s_conditionNames
[16] = {
43 "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
44 "hi", "ls", "ge", "lt", "gt", "le", "al", "al"
47 const char* const ARMv7DOpcode::s_optionName
[8] = {
48 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"
51 const char* const ARMv7DOpcode::s_shiftNames
[4] = {
52 "lsl", "lsr", "asr", "ror"
55 const char* const ARMv7DOpcode::s_specialRegisterNames
[3] = { "sp", "lr", "pc" };
57 template <typename OpcodeType
, typename InstructionType
>
58 struct OpcodeGroupInitializer
{
59 unsigned m_opcodeGroupNumber
;
60 InstructionType m_mask
;
61 InstructionType m_pattern
;
62 const char* (*m_format
)(OpcodeType
*);
65 #define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \
66 { groupIndex, groupClass::s_mask, groupClass::s_pattern, groupClass::format }
68 typedef OpcodeGroupInitializer
<ARMv7D16BitOpcode
, uint16_t> Opcode16GroupInitializer
;
69 typedef OpcodeGroupInitializer
<ARMv7D32BitOpcode
, uint32_t> Opcode32GroupInitializer
;
71 static 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
)
115 static 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
),
148 bool ARMv7DOpcode::s_initialized
= false;
150 void ARMv7DOpcode::init()
155 ARMv7D16BitOpcode::init();
156 ARMv7D32BitOpcode::init();
158 s_initialized
= true;
161 void ARMv7DOpcode::startITBlock(unsigned blocksize
, unsigned firstCondition
)
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
;
170 void ARMv7DOpcode::saveITConditionAt(unsigned blockPosition
, unsigned condition
)
172 if (blockPosition
< m_ITBlocksize
)
173 m_ifThenConditions
[blockPosition
] = static_cast<unsigned char>(condition
);
176 void ARMv7DOpcode::fetchOpcode(uint16_t*& newPC
)
179 m_formatBuffer
[0] = '\0';
184 if (is32BitInstruction()) {
186 m_opcode
|= *newPC
++;
189 if (m_ITConditionIndex
< m_ITBlocksize
)
190 m_currentITCondition
= m_ifThenConditions
[m_ITConditionIndex
];
192 m_currentITCondition
= CondNone
;
195 const char* ARMv7DOpcode::disassemble(uint16_t*& currentPC
)
198 fetchOpcode(currentPC
);
200 if (is32BitInstruction())
201 result
= reinterpret_cast<ARMv7D32BitOpcode
*>(this)->doDisassemble();
203 result
= reinterpret_cast<ARMv7D16BitOpcode
*>(this)->doDisassemble();
205 if (startingITBlock())
206 m_ITConditionIndex
= 0;
207 else if (inITBlock() && (++m_ITConditionIndex
>= m_ITBlocksize
))
213 void ARMv7DOpcode::bufferPrintf(const char* format
, ...)
215 if (m_bufferOffset
>= bufferSize
)
219 va_start(argList
, format
);
221 m_bufferOffset
+= vsnprintf(m_formatBuffer
+ m_bufferOffset
, bufferSize
- m_bufferOffset
, format
, argList
);
226 void ARMv7DOpcode::appendInstructionName(const char* instructionName
, bool addS
)
228 if (!inITBlock() && !addS
) {
229 appendInstructionNameNoITBlock(instructionName
);
234 const char sevenSpaces
[8] = " ";
236 unsigned length
= strlen(instructionName
);
238 bufferPrintf(" %s", instructionName
);
240 const char* condition
= conditionName(m_currentITCondition
);
241 length
+= strlen(condition
);
242 appendString(condition
);
245 appendCharacter('s');
251 appendString(sevenSpaces
+ length
);
254 void ARMv7DOpcode::appendRegisterName(unsigned registerNumber
)
256 registerNumber
&= 0xf;
258 if (registerNumber
> 12) {
259 appendString(s_specialRegisterNames
[registerNumber
- 13]);
263 bufferPrintf("r%u", registerNumber
);
266 void ARMv7DOpcode::appendRegisterList(unsigned registers
)
268 unsigned numberPrinted
= 0;
270 appendCharacter('{');
272 for (unsigned i
= 0; i
< 16; i
++) {
273 if (registers
& (1 << i
)) {
276 appendRegisterName(i
);
280 appendCharacter('}');
283 void ARMv7DOpcode::appendFPRegisterName(char registerPrefix
, unsigned registerNumber
)
285 bufferPrintf("%c%u", registerPrefix
, registerNumber
);
288 // 16 Bit Instructions
290 void ARMv7D16BitOpcode::init()
292 OpcodeGroup
* lastGroups
[OpcodeGroup::opcodeTableSize
];
294 for (unsigned i
= 0; i
< OpcodeGroup::opcodeTableSize
; i
++) {
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
;
303 if (!opcodeTable
[opcodeGroupNumber
])
304 opcodeTable
[opcodeGroupNumber
] = newOpcodeGroup
;
306 lastGroups
[opcodeGroupNumber
]->setNext(newOpcodeGroup
);
307 lastGroups
[opcodeGroupNumber
] = newOpcodeGroup
;
311 const char* ARMv7D16BitOpcode::doDisassemble()
313 OpcodeGroup
* opGroup
= opcodeTable
[opcodeGroupNumber(m_opcode
)];
316 if (opGroup
->matches(static_cast<uint16_t>(m_opcode
)))
317 return opGroup
->format(this);
318 opGroup
= opGroup
->next();
321 return defaultFormat();
324 const char* ARMv7D16BitOpcode::defaultFormat()
326 bufferPrintf(" .word %04x", m_opcode
);
327 return m_formatBuffer
;
330 const char* ARMv7DOpcodeAddRegisterT2::format()
332 appendInstructionName("add");
333 appendRegisterName(rdn());
335 appendRegisterName(rm());
337 return m_formatBuffer
;
340 const char* ARMv7DOpcodeAddSPPlusImmediate::format()
342 appendInstructionName("add");
343 appendRegisterName(rd());
345 appendRegisterName(RegSP
);
347 appendUnsignedImmediate(immediate8());
349 return m_formatBuffer
;
352 const char* const ARMv7DOpcodeAddSubtract::s_opNames
[2] = { "add", "sub" };
354 const char* ARMv7DOpcodeAddSubtractT1::format()
356 appendInstructionName(opName(), !inITBlock());
357 appendRegisterName(rd());
359 appendRegisterName(rn());
361 appendRegisterName(rm());
363 return m_formatBuffer
;
366 const char* ARMv7DOpcodeAddSubtractImmediate3::format()
368 appendInstructionName(opName(), !inITBlock());
369 appendRegisterName(rd());
371 appendRegisterName(rn());
373 appendUnsignedImmediate(immediate3());
375 return m_formatBuffer
;
378 const char* ARMv7DOpcodeAddSubtractImmediate8::format()
380 appendInstructionName(opName(), !inITBlock());
381 appendRegisterName(rdn());
383 appendUnsignedImmediate(immediate8());
385 return m_formatBuffer
;
388 const char* ARMv7DOpcodeBranchConditionalT1::format()
390 if (condition() == 0xe)
391 return defaultFormat();
393 if (condition() == 0xf) {
394 appendInstructionName("svc");
395 appendUnsignedImmediate(offset());
397 return m_formatBuffer
;
400 bufferPrintf(" b%-6.6s", conditionName(condition()));
401 appendPCRelativeOffset(static_cast<int32_t>(offset()) + 2);
403 return m_formatBuffer
;
406 const char* ARMv7DOpcodeBranchExchangeT1::format()
408 appendInstructionName(opName());
409 appendRegisterName(rm());
411 return m_formatBuffer
;
414 const char* ARMv7DOpcodeBranchT2::format()
416 appendInstructionName("b");
417 appendPCRelativeOffset(static_cast<int32_t>(immediate11()) + 2);
419 return m_formatBuffer
;
422 const char* ARMv7DOpcodeCompareImmediateT1::format()
424 appendInstructionName("cmp");
425 appendRegisterName(rn());
427 appendUnsignedImmediate(immediate8());
429 return m_formatBuffer
;
432 const char* ARMv7DOpcodeCompareRegisterT1::format()
434 appendInstructionName("cmp");
435 appendRegisterName(rn());
437 appendRegisterName(rm());
439 return m_formatBuffer
;
442 const char* ARMv7DOpcodeCompareRegisterT2::format()
444 appendInstructionName("compare");
445 appendRegisterName(rn());
447 appendRegisterName(rm());
449 return m_formatBuffer
;
452 const char* const ARMv7DOpcodeDataProcessingRegisterT1::s_opNames
[16] = {
453 "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn"
456 const char* ARMv7DOpcodeDataProcessingRegisterT1::format()
458 appendInstructionName(opName(), inITBlock() && (!(op() == 0x8) || (op() == 0xa) || (op() == 0xb)));
459 appendRegisterName(rdn());
461 appendRegisterName(rm());
462 if (op() == 0x9) // rsb T1
463 appendString(", #0");
464 else if (op() == 0xd) { // mul T1
466 appendRegisterName(rdn());
469 return m_formatBuffer
;
472 const char* ARMv7DOpcodeGeneratePCRelativeAddress::format()
474 appendInstructionName("adr");
475 appendRegisterName(rd());
477 appendPCRelativeOffset(static_cast<int32_t>(immediate8()));
479 return m_formatBuffer
;
482 const char* ARMv7DOpcodeLoadFromLiteralPool::format()
484 appendInstructionName("ldr");
485 appendRegisterName(rt());
487 appendPCRelativeOffset(static_cast<int32_t>(immediate8()));
489 return m_formatBuffer
;
492 const char* const ARMv7DOpcodeLoadStoreRegisterImmediate::s_opNames
[6] = {
493 "str", "ldr", "strb", "ldrb", "strh", "ldrh"
496 const char* ARMv7DOpcodeLoadStoreRegisterImmediate::format()
498 const char* instructionName
= opName();
500 if (!instructionName
)
501 return defaultFormat();
503 appendInstructionName(opName());
504 appendRegisterName(rt());
506 appendCharacter('[');
507 appendRegisterName(rn());
510 appendUnsignedImmediate(immediate5() << scale());
512 appendCharacter(']');
514 return m_formatBuffer
;
517 const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames
[8] = {
518 "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh"
521 const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format()
523 appendInstructionName(opName());
524 appendRegisterName(rt());
526 appendCharacter('[');
527 appendRegisterName(rn());
529 appendRegisterName(rm());
530 appendCharacter(']');
532 return m_formatBuffer
;
535 const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format()
537 appendInstructionName(opName());
538 appendRegisterName(rt());
540 appendCharacter('[');
541 appendRegisterName(RegSP
);
544 appendUnsignedImmediate(immediate8() << 2);
546 appendCharacter(']');
548 return m_formatBuffer
;
551 const char* ARMv7DOpcodeLogicalImmediateT1::format()
553 if (!op() && !immediate5()) {
555 appendInstructionName("movs");
556 appendRegisterName(rd());
558 appendRegisterName(rm());
560 return m_formatBuffer
;
563 appendInstructionName(opName(), !inITBlock());
564 appendRegisterName(rd());
566 appendRegisterName(rm());
568 appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5());
570 return m_formatBuffer
;
573 const char* ARMv7DOpcodeMiscAddSubSP::format()
575 appendInstructionName(opName());
576 appendRegisterName(RegSP
);
578 appendRegisterName(RegSP
);
580 appendUnsignedImmediate(immediate7());
582 return m_formatBuffer
;
585 const char* ARMv7DOpcodeMiscBreakpointT1::format()
587 appendInstructionNameNoITBlock("bkpt");
588 appendUnsignedImmediate(immediate8());
590 return m_formatBuffer
;
593 const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames
[8] = {
594 "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh"
597 const char* ARMv7DOpcodeMiscByteHalfwordOps::format()
599 const char* instructionName
= opName();
601 if (!instructionName
)
602 return defaultFormat();
604 appendInstructionName(instructionName
);
605 appendRegisterName(rd());
607 appendRegisterName(rm());
609 return m_formatBuffer
;
612 const char* ARMv7DOpcodeMiscCompareAndBranch::format()
614 appendInstructionName(opName());
615 appendPCRelativeOffset(immediate6() + 2);
617 return m_formatBuffer
;
620 const char* const ARMv7DOpcodeMiscHint16::s_opNames
[16] = {
621 "nop", "yield", "wfe", "wfi", "sev"
624 const char* ARMv7DOpcodeMiscHint16::format()
627 return defaultFormat();
629 appendInstructionName(opName());
631 return m_formatBuffer
;
634 const char* ARMv7DOpcodeMiscIfThenT1::format()
640 unsigned condition
= firstCondition();
641 unsigned maskBits
= mask();
642 unsigned blockLength
= 0;
644 for (unsigned i
= 0; i
< 4; ++i
) {
645 if (maskBits
& (1 << i
)) {
651 startITBlock(blockLength
, condition
);
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
);
658 opName
[blockLength
+ 1] = '\0';
660 appendInstructionNameNoITBlock(opName
);
661 appendString(conditionName(condition
));
663 return m_formatBuffer
;
666 const char* ARMv7DOpcodeMiscPushPop::format()
668 appendInstructionName(opName());
669 appendRegisterList(registerMask());
671 return m_formatBuffer
;
674 const char* ARMv7DOpcodeMoveImmediateT1::format()
676 appendInstructionName("mov", !inITBlock());
677 appendRegisterName(rd());
679 appendUnsignedImmediate(immediate8());
681 return m_formatBuffer
;
684 const char* ARMv7DOpcodeMoveRegisterT1::format()
686 appendInstructionName("mov");
687 appendRegisterName(rd());
689 appendRegisterName(rm());
691 return m_formatBuffer
;
694 // 32 bit Intructions
696 void ARMv7D32BitOpcode::init()
698 OpcodeGroup
* lastGroups
[OpcodeGroup::opcodeTableSize
];
700 for (unsigned i
= 0; i
< OpcodeGroup::opcodeTableSize
; i
++) {
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
;
709 if (!opcodeTable
[opcodeGroupNumber
])
710 opcodeTable
[opcodeGroupNumber
] = newOpcodeGroup
;
712 lastGroups
[opcodeGroupNumber
]->setNext(newOpcodeGroup
);
713 lastGroups
[opcodeGroupNumber
] = newOpcodeGroup
;
717 const char* ARMv7D32BitOpcode::doDisassemble()
719 OpcodeGroup
* opGroup
= opcodeTable
[opcodeGroupNumber(m_opcode
)];
722 if (opGroup
->matches(m_opcode
))
723 return opGroup
->format(this);
724 opGroup
= opGroup
->next();
727 return defaultFormat();
730 const char* ARMv7D32BitOpcode::defaultFormat()
732 bufferPrintf(" .long %08x", m_opcode
);
733 return m_formatBuffer
;
736 const char* ARMv7DOpcodeConditionalBranchT3::format()
738 if (condition() < 0xe)
739 bufferPrintf(" b%-6.6s", conditionName(condition()));
741 appendInstructionName("b");
742 appendPCRelativeOffset(offset() + 2);
744 return m_formatBuffer
;
747 const char* ARMv7DOpcodeBranchOrBranchLink::format()
749 appendInstructionName(isBL() ? "bl" : "b");
750 appendPCRelativeOffset(offset() + 2);
752 return m_formatBuffer
;
755 const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames
[16] = {
756 "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0
759 void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12
)
761 if (!(immediate12
& 0xc00)) {
762 unsigned immediate
= 0;
763 unsigned lower8Bits
= immediate12
& 0xff;
765 switch ((immediate12
>> 8) & 3) {
767 immediate
= lower8Bits
;
770 immediate
= (lower8Bits
<< 16) | lower8Bits
;
773 immediate
= (lower8Bits
<< 24) | (lower8Bits
<< 8);
776 immediate
= (lower8Bits
<< 24) | (lower8Bits
<< 16) | (lower8Bits
<< 8) | lower8Bits
;
779 appendUnsignedImmediate(immediate
);
783 unsigned immediate8
= 0x80 | (immediate12
& 0x7f);
784 unsigned shiftAmount
= 32 - ((immediate12
>> 7) & 0x1f);
786 appendUnsignedImmediate(immediate8
<< shiftAmount
);
789 const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format()
791 if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
792 return defaultFormat();
794 const char* instructionName
= opName();
799 instructionName
= sBit() ? "movs" : "mov";
800 appendInstructionName(instructionName
);
801 appendRegisterName(rd());
803 appendModifiedImmediate(immediate12());
805 return m_formatBuffer
;
810 instructionName
= sBit() ? "mvns" : "mvn";
811 appendInstructionName(instructionName
);
812 appendRegisterName(rd());
814 appendModifiedImmediate(immediate12());
816 return m_formatBuffer
;
822 bool testOrCmpInstruction
= false;
826 instructionName
= "tst";
827 testOrCmpInstruction
= true;
830 instructionName
= "teq";
831 testOrCmpInstruction
= true;
834 instructionName
= "cmn";
835 testOrCmpInstruction
= true;
838 instructionName
= "cmp";
839 testOrCmpInstruction
= true;
843 if (testOrCmpInstruction
) {
844 appendInstructionName(instructionName
);
845 appendRegisterName(rn());
847 appendModifiedImmediate(immediate12());
849 return m_formatBuffer
;
854 appendInstructionName(instructionName
);
855 appendRegisterName(rd());
857 appendRegisterName(rn());
859 appendModifiedImmediate(immediate12());
861 return m_formatBuffer
;
864 void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type
, unsigned immediate
)
866 if (type
|| immediate
) {
881 appendShiftType(type
);
882 appendUnsignedImmediate(immediate
);
886 const char* ARMv7DOpcodeDataProcessingShiftedReg::format()
888 if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
889 return defaultFormat();
893 if (sBit() || tBit())
894 return defaultFormat();
897 appendInstructionName("pkhtb");
899 appendInstructionName("pkhbt");
900 appendRegisterName(rd());
902 appendRegisterName(rn());
904 appendRegisterName(rm());
905 appendImmShift(tbBit() << 1, immediate5());
907 return m_formatBuffer
;
910 const char* instructionName
= opName();
914 if (!type() && !immediate5()) {
916 instructionName
= sBit() ? "movs" : "mov";
917 appendInstructionName(instructionName
);
918 appendRegisterName(rd());
920 appendRegisterName(rm());
922 return m_formatBuffer
;
925 if (type() == 3 && !immediate5()) {
927 instructionName
= sBit() ? "rrx" : "rrx";
928 appendInstructionName(instructionName
);
929 appendRegisterName(rd());
931 appendRegisterName(rm());
933 return m_formatBuffer
;
938 bufferPrintf("%ss ", shiftName(type()));
940 appendInstructionName(shiftName(type()));
941 appendRegisterName(rd());
943 appendRegisterName(rm());
945 appendUnsignedImmediate(immediate5());
947 return m_formatBuffer
;
952 instructionName
= sBit() ? "mvns" : "mvn";
953 appendInstructionName(instructionName
);
954 appendRegisterName(rd());
956 appendRegisterName(rm());
957 appendImmShift(type(), immediate5());
959 return m_formatBuffer
;
965 bool testOrCmpInstruction
= false;
969 instructionName
= "tst";
970 testOrCmpInstruction
= true;
973 instructionName
= "teq";
974 testOrCmpInstruction
= true;
977 instructionName
= "cmn";
978 testOrCmpInstruction
= true;
981 instructionName
= "cmp";
982 testOrCmpInstruction
= true;
986 if (testOrCmpInstruction
) {
987 appendInstructionName(instructionName
);
988 appendRegisterName(rn());
990 appendRegisterName(rm());
991 appendImmShift(type(), immediate5());
993 return m_formatBuffer
;
998 appendInstructionName(instructionName
);
999 appendRegisterName(rd());
1001 appendRegisterName(rn());
1003 appendRegisterName(rm());
1004 appendImmShift(type(), immediate5());
1006 return m_formatBuffer
;
1009 const char* ARMv7DOpcodeFPTransfer::format()
1011 appendInstructionName("vmov");
1018 appendRegisterName(rt());
1025 return m_formatBuffer
;
1028 void ARMv7DOpcodeFPTransfer::appendFPRegister()
1031 appendFPRegisterName('d', vd());
1032 bufferPrintf("[%u]", opH());
1034 appendFPRegisterName('s', vn());
1037 const char* ARMv7DOpcodeDataProcessingRegShift::format()
1039 appendInstructionName(opName());
1040 appendRegisterName(rd());
1042 appendRegisterName(rn());
1044 appendRegisterName(rm());
1046 return m_formatBuffer
;
1049 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames
[8] = {
1050 "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb"
1053 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames
[8] = {
1054 "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab"
1057 const char* ARMv7DOpcodeDataProcessingRegExtend::format()
1059 const char* instructionName
;
1062 instructionName
= opExtendName();
1064 instructionName
= opExtendAndAddName();
1066 if (!instructionName
)
1067 return defaultFormat();
1069 appendInstructionName(instructionName
);
1070 appendRegisterName(rd());
1072 appendRegisterName(rn());
1074 appendRegisterName(rm());
1078 appendString("ror ");
1079 appendUnsignedImmediate(rotate() * 8);
1082 return m_formatBuffer
;
1085 const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames
[16] = {
1086 "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0,
1087 "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0
1090 const char* ARMv7DOpcodeDataProcessingRegParallel::format()
1092 const char* instructionName
;
1094 instructionName
= opName();
1096 if (!instructionName
)
1097 return defaultFormat();
1099 appendInstructionName(instructionName
);
1100 appendRegisterName(rd());
1102 appendRegisterName(rn());
1104 appendRegisterName(rm());
1106 return m_formatBuffer
;
1109 const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames
[16] = {
1110 "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh",
1111 "sel", 0, 0, 0, "clz"
1114 const char* ARMv7DOpcodeDataProcessingRegMisc::format()
1116 const char* instructionName
;
1118 instructionName
= opName();
1120 if (!instructionName
)
1121 return defaultFormat();
1123 if ((op1() & 0x1) && (rn() != rm()))
1124 return defaultFormat();
1126 appendInstructionName(instructionName
);
1127 appendRegisterName(rd());
1130 if (op1() == 0x2) { // sel
1131 appendRegisterName(rn());
1133 appendRegisterName(rm());
1135 return m_formatBuffer
;
1138 appendRegisterName(rm());
1140 if (!(op1() & 0x1)) {
1142 appendRegisterName(rn());
1145 return m_formatBuffer
;
1148 const char* const ARMv7DOpcodeHint32::s_opNames
[8] = {
1149 "nop", "yield", "wfe", "wfi", "sev"
1152 const char* ARMv7DOpcodeHint32::format()
1154 if (isDebugHint()) {
1155 appendInstructionName("debug");
1156 appendUnsignedImmediate(debugOption());
1158 return m_formatBuffer
;
1162 return defaultFormat();
1164 appendInstructionName(opName());
1166 return m_formatBuffer
;
1169 const char* const ARMv7DOpcodeDataLoad::s_opNames
[8] = {
1170 "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh"
1173 const char* ARMv7DOpcodeLoadRegister::format()
1175 appendInstructionName(opName());
1176 appendRegisterName(rt());
1178 appendCharacter('[');
1179 appendRegisterName(rn());
1181 appendRegisterName(rm());
1184 appendUnsignedImmediate(immediate2());
1186 appendCharacter(']');
1188 return m_formatBuffer
;
1191 const char* ARMv7DOpcodeLoadSignedImmediate::format()
1193 appendInstructionName(opName());
1194 appendRegisterName(rt());
1196 appendCharacter('[');
1197 appendRegisterName(rn());
1199 if (wBit() || immediate8()) {
1202 appendUnsignedImmediate(immediate8());
1204 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1206 appendCharacter(']');
1208 appendCharacter('!');
1210 appendCharacter(']');
1213 appendUnsignedImmediate(immediate8());
1215 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1218 return m_formatBuffer
;
1221 const char* ARMv7DOpcodeLoadUnsignedImmediate::format()
1223 appendInstructionName(opName());
1224 appendRegisterName(rt());
1226 appendCharacter('[');
1227 appendRegisterName(rn());
1228 if (immediate12()) {
1230 appendUnsignedImmediate(immediate12());
1232 appendCharacter(']');
1234 return m_formatBuffer
;
1237 const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames
[8] = {
1238 "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0
1241 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames
[4] = {
1242 "smlalbb", "smlalbt", "smlaltb", "smlaltt"
1245 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames
[2] = {
1249 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames
[2] = {
1253 const char* ARMv7DOpcodeLongMultipleDivide::format()
1255 const char* instructionName
= opName();
1261 return defaultFormat();
1266 return defaultFormat();
1269 if ((op2() & 0xc) == 0x8)
1270 instructionName
= smlalOpName();
1271 else if ((op2() & 0xe) == 0xc)
1272 instructionName
= smlaldOpName();
1274 return defaultFormat();
1277 if ((op2() & 0xe) == 0xc)
1278 instructionName
= smlaldOpName();
1280 return defaultFormat();
1284 instructionName
= "umaal";
1286 return defaultFormat();
1289 return defaultFormat();
1293 appendInstructionName(instructionName
);
1294 if ((op1() & 0x5) == 0x1) { // sdiv and udiv
1296 return defaultFormat();
1298 appendRegisterName(rdLo());
1301 appendRegisterName(rdHi());
1303 appendRegisterName(rn());
1305 appendRegisterName(rm());
1307 return m_formatBuffer
;
1310 const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames
[16] = {
1311 "addw", 0, "movw", 0, 0, "subw", "movt", 0,
1312 "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0
1315 const char* ARMv7DOpcodeUnmodifiedImmediate::format()
1317 const char* instructionName
= opName();
1319 switch (op() >> 1) {
1323 instructionName
= "adr";
1327 instructionName
= "ssat";
1331 instructionName
= "bfc";
1335 instructionName
= "usat";
1339 if (!instructionName
)
1340 return defaultFormat();
1342 appendInstructionName(instructionName
);
1343 appendRegisterName(rd());
1346 if ((op() & 0x17) == 0x4) { // movw or movt
1347 appendUnsignedImmediate(immediate16());
1349 return m_formatBuffer
;
1352 if (!op() || (op() == 0xa)) { // addw, subw and adr
1356 if ((op() == 0xa) && (rn() == 0xf))
1357 offset
= 0 - static_cast<int32_t>(immediate12());
1359 offset
= static_cast<int32_t>(immediate12());
1361 appendPCRelativeOffset(offset
);
1363 return m_formatBuffer
;
1366 appendRegisterName(rn());
1368 appendUnsignedImmediate(immediate12());
1370 return m_formatBuffer
;
1373 if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16
1375 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1377 appendRegisterName(rn());
1378 if (shBit() || immediate5()) {
1380 appendShiftType(shBit() << 1);
1381 appendUnsignedImmediate(immediate5());
1384 return m_formatBuffer
;
1387 if (op() == 0x16) { // bfi or bfc
1388 int width
= static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1;
1391 return defaultFormat();
1395 appendRegisterName(rn());
1398 appendUnsignedImmediate(immediate5());
1400 appendSignedImmediate(width
);
1402 return m_formatBuffer
;
1405 // Must be sbfx or ubfx
1407 appendRegisterName(rn());
1409 appendUnsignedImmediate(immediate5());
1411 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1413 return m_formatBuffer
;
1416 const char* const ARMv7DOpcodeDataStoreSingle::s_opNames
[4] = {
1417 "strb", "strh", "str", 0
1420 const char* ARMv7DOpcodeDataPushPopSingle::format()
1422 appendInstructionName(opName());
1423 appendRegisterName(rt());
1425 return m_formatBuffer
;
1428 const char* ARMv7DOpcodeStoreSingleImmediate12::format()
1430 appendInstructionName(opName());
1431 appendRegisterName(rt());
1433 appendCharacter('[');
1434 appendRegisterName(rn());
1435 if (immediate12()) {
1437 appendUnsignedImmediate(immediate12());
1439 appendCharacter(']');
1441 return m_formatBuffer
;
1444 const char* ARMv7DOpcodeStoreSingleImmediate8::format()
1446 if (pBit() && uBit() && !wBit()) // Really undecoded strt
1447 return defaultFormat();
1449 if ((rn() == 0xf) || (!pBit() && !wBit()))
1450 return defaultFormat();
1452 appendInstructionName(opName());
1453 appendRegisterName(rt());
1455 appendCharacter('[');
1456 appendRegisterName(rn());
1459 appendCharacter(']');
1461 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1463 return m_formatBuffer
;
1468 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1470 appendCharacter(']');
1473 appendCharacter('!');
1475 return m_formatBuffer
;
1478 const char* ARMv7DOpcodeStoreSingleRegister::format()
1480 appendInstructionName(opName());
1481 appendRegisterName(rt());
1483 appendCharacter('[');
1484 appendRegisterName(rn());
1486 appendRegisterName(rm());
1489 appendString("lsl ");
1490 appendUnsignedImmediate(immediate2());
1492 appendCharacter(']');
1494 return m_formatBuffer
;
1497 const char* ARMv7DOpcodeVMOVDoublePrecision::format()
1499 appendInstructionName("vmov");
1501 appendRegisterName(rt());
1503 appendRegisterName(rt2());
1507 appendFPRegisterName('d', vm());
1511 appendRegisterName(rt());
1513 appendRegisterName(rt2());
1516 return m_formatBuffer
;
1519 const char* ARMv7DOpcodeVMOVSinglePrecision::format()
1521 appendInstructionName("vmov");
1523 appendRegisterName(rt());
1525 appendRegisterName(rt2());
1529 appendFPRegisterName('s', vm());
1531 appendFPRegisterName('s', (vm() + 1) % 32);
1535 appendRegisterName(rt());
1537 appendRegisterName(rt2());
1540 return m_formatBuffer
;
1543 const char* ARMv7DOpcodeVMSR::format()
1545 appendInstructionName("vmrs");
1548 appendString("apsr_nzcv");
1550 appendRegisterName(rt());
1554 appendString("fpscr");
1558 appendRegisterName(rt());
1561 return m_formatBuffer
;
1564 } } // namespace JSC::ARMv7Disassembler
1566 #endif // #if USE(ARMV7_DISASSEMBLER)