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, ARMv7DOpcodeStoreRegisterImmediateHalfWord
),
95 OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadRegisterImmediateHalfWord
),
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 unsigned ARMv7DOpcodeLoadStoreRegisterImmediate::scale()
532 ASSERT_NOT_REACHED();
536 const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames
[8] = {
537 "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh"
540 const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format()
542 appendInstructionName(opName());
543 appendRegisterName(rt());
545 appendCharacter('[');
546 appendRegisterName(rn());
548 appendRegisterName(rm());
549 appendCharacter(']');
551 return m_formatBuffer
;
554 const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format()
556 appendInstructionName(opName());
557 appendRegisterName(rt());
559 appendCharacter('[');
560 appendRegisterName(RegSP
);
563 appendUnsignedImmediate(immediate8() << 2);
565 appendCharacter(']');
567 return m_formatBuffer
;
570 const char* ARMv7DOpcodeLogicalImmediateT1::format()
572 if (!op() && !immediate5()) {
574 appendInstructionName("movs");
575 appendRegisterName(rd());
577 appendRegisterName(rm());
579 return m_formatBuffer
;
582 appendInstructionName(opName(), !inITBlock());
583 appendRegisterName(rd());
585 appendRegisterName(rm());
587 appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5());
589 return m_formatBuffer
;
592 const char* ARMv7DOpcodeMiscAddSubSP::format()
594 appendInstructionName(opName());
595 appendRegisterName(RegSP
);
597 appendRegisterName(RegSP
);
599 appendUnsignedImmediate(immediate7());
601 return m_formatBuffer
;
604 const char* ARMv7DOpcodeMiscBreakpointT1::format()
606 appendInstructionNameNoITBlock("bkpt");
607 appendUnsignedImmediate(immediate8());
609 return m_formatBuffer
;
612 const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames
[8] = {
613 "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh"
616 const char* ARMv7DOpcodeMiscByteHalfwordOps::format()
618 const char* instructionName
= opName();
620 if (!instructionName
)
621 return defaultFormat();
623 appendInstructionName(instructionName
);
624 appendRegisterName(rd());
626 appendRegisterName(rm());
628 return m_formatBuffer
;
631 const char* ARMv7DOpcodeMiscCompareAndBranch::format()
633 appendInstructionName(opName());
634 appendPCRelativeOffset(immediate6() + 2);
636 return m_formatBuffer
;
639 const char* const ARMv7DOpcodeMiscHint16::s_opNames
[16] = {
640 "nop", "yield", "wfe", "wfi", "sev"
643 const char* ARMv7DOpcodeMiscHint16::format()
646 return defaultFormat();
648 appendInstructionName(opName());
650 return m_formatBuffer
;
653 const char* ARMv7DOpcodeMiscIfThenT1::format()
659 unsigned condition
= firstCondition();
660 unsigned maskBits
= mask();
661 unsigned blockLength
= 0;
663 for (unsigned i
= 0; i
< 4; ++i
) {
664 if (maskBits
& (1 << i
)) {
670 startITBlock(blockLength
, condition
);
672 for (unsigned i
= 1; i
< blockLength
; ++i
) {
673 unsigned currMaskBit
= (maskBits
>> (4-i
)) & 0x1;
674 opName
[i
+ 1] = (currMaskBit
^ (condition
& 1)) ? 'e' : 't';
675 saveITConditionAt(i
, (condition
& ~1) | currMaskBit
);
677 opName
[blockLength
+ 1] = '\0';
679 appendInstructionNameNoITBlock(opName
);
680 appendString(conditionName(condition
));
682 return m_formatBuffer
;
685 const char* ARMv7DOpcodeMiscPushPop::format()
687 appendInstructionName(opName());
688 appendRegisterList(registerMask());
690 return m_formatBuffer
;
693 const char* ARMv7DOpcodeMoveImmediateT1::format()
695 appendInstructionName("mov", !inITBlock());
696 appendRegisterName(rd());
698 appendUnsignedImmediate(immediate8());
700 return m_formatBuffer
;
703 const char* ARMv7DOpcodeMoveRegisterT1::format()
705 appendInstructionName("mov");
706 appendRegisterName(rd());
708 appendRegisterName(rm());
710 return m_formatBuffer
;
713 // 32 bit Intructions
715 void ARMv7D32BitOpcode::init()
717 OpcodeGroup
* lastGroups
[OpcodeGroup::opcodeTableSize
];
719 for (unsigned i
= 0; i
< OpcodeGroup::opcodeTableSize
; i
++) {
724 for (unsigned i
= 0; i
< sizeof(opcode32BitGroupList
) / sizeof(Opcode32GroupInitializer
); i
++) {
725 OpcodeGroup
* newOpcodeGroup
= new OpcodeGroup(opcode32BitGroupList
[i
].m_mask
, opcode32BitGroupList
[i
].m_pattern
, opcode32BitGroupList
[i
].m_format
);
726 uint16_t opcodeGroupNumber
= opcode32BitGroupList
[i
].m_opcodeGroupNumber
;
728 if (!opcodeTable
[opcodeGroupNumber
])
729 opcodeTable
[opcodeGroupNumber
] = newOpcodeGroup
;
731 lastGroups
[opcodeGroupNumber
]->setNext(newOpcodeGroup
);
732 lastGroups
[opcodeGroupNumber
] = newOpcodeGroup
;
736 const char* ARMv7D32BitOpcode::doDisassemble()
738 OpcodeGroup
* opGroup
= opcodeTable
[opcodeGroupNumber(m_opcode
)];
741 if (opGroup
->matches(m_opcode
))
742 return opGroup
->format(this);
743 opGroup
= opGroup
->next();
746 return defaultFormat();
749 const char* ARMv7D32BitOpcode::defaultFormat()
751 bufferPrintf(" .long %08x", m_opcode
);
752 return m_formatBuffer
;
755 const char* ARMv7DOpcodeConditionalBranchT3::format()
757 if (condition() < 0xe)
758 bufferPrintf(" b%-6.6s", conditionName(condition()));
760 appendInstructionName("b");
761 appendPCRelativeOffset(offset() + 2);
763 return m_formatBuffer
;
766 const char* ARMv7DOpcodeBranchOrBranchLink::format()
768 appendInstructionName(isBL() ? "bl" : "b");
769 appendPCRelativeOffset(offset() + 2);
771 return m_formatBuffer
;
774 const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames
[16] = {
775 "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0
778 void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12
)
780 if (!(immediate12
& 0xc00)) {
781 unsigned immediate
= 0;
782 unsigned lower8Bits
= immediate12
& 0xff;
784 switch ((immediate12
>> 8) & 3) {
786 immediate
= lower8Bits
;
789 immediate
= (lower8Bits
<< 16) | lower8Bits
;
792 immediate
= (lower8Bits
<< 24) | (lower8Bits
<< 8);
795 immediate
= (lower8Bits
<< 24) | (lower8Bits
<< 16) | (lower8Bits
<< 8) | lower8Bits
;
798 appendUnsignedImmediate(immediate
);
802 unsigned immediate8
= 0x80 | (immediate12
& 0x7f);
803 unsigned shiftAmount
= 32 - ((immediate12
>> 7) & 0x1f);
805 appendUnsignedImmediate(immediate8
<< shiftAmount
);
808 const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format()
810 if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
811 return defaultFormat();
813 const char* instructionName
= opName();
818 instructionName
= sBit() ? "movs" : "mov";
819 appendInstructionName(instructionName
);
820 appendRegisterName(rd());
822 appendModifiedImmediate(immediate12());
824 return m_formatBuffer
;
829 instructionName
= sBit() ? "mvns" : "mvn";
830 appendInstructionName(instructionName
);
831 appendRegisterName(rd());
833 appendModifiedImmediate(immediate12());
835 return m_formatBuffer
;
841 bool testOrCmpInstruction
= false;
845 instructionName
= "tst";
846 testOrCmpInstruction
= true;
849 instructionName
= "teq";
850 testOrCmpInstruction
= true;
853 instructionName
= "cmn";
854 testOrCmpInstruction
= true;
857 instructionName
= "cmp";
858 testOrCmpInstruction
= true;
862 if (testOrCmpInstruction
) {
863 appendInstructionName(instructionName
);
864 appendRegisterName(rn());
866 appendModifiedImmediate(immediate12());
868 return m_formatBuffer
;
873 appendInstructionName(instructionName
);
874 appendRegisterName(rd());
876 appendRegisterName(rn());
878 appendModifiedImmediate(immediate12());
880 return m_formatBuffer
;
883 void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type
, unsigned immediate
)
885 if (type
|| immediate
) {
900 appendShiftType(type
);
901 appendUnsignedImmediate(immediate
);
905 const char* ARMv7DOpcodeDataProcessingShiftedReg::format()
907 if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
908 return defaultFormat();
912 if (sBit() || tBit())
913 return defaultFormat();
916 appendInstructionName("pkhtb");
918 appendInstructionName("pkhbt");
919 appendRegisterName(rd());
921 appendRegisterName(rn());
923 appendRegisterName(rm());
924 appendImmShift(tbBit() << 1, immediate5());
926 return m_formatBuffer
;
929 const char* instructionName
= opName();
933 if (!type() && !immediate5()) {
935 instructionName
= sBit() ? "movs" : "mov";
936 appendInstructionName(instructionName
);
937 appendRegisterName(rd());
939 appendRegisterName(rm());
941 return m_formatBuffer
;
944 if (type() == 3 && !immediate5()) {
946 instructionName
= sBit() ? "rrx" : "rrx";
947 appendInstructionName(instructionName
);
948 appendRegisterName(rd());
950 appendRegisterName(rm());
952 return m_formatBuffer
;
957 bufferPrintf("%ss ", shiftName(type()));
959 appendInstructionName(shiftName(type()));
960 appendRegisterName(rd());
962 appendRegisterName(rm());
964 appendUnsignedImmediate(immediate5());
966 return m_formatBuffer
;
971 instructionName
= sBit() ? "mvns" : "mvn";
972 appendInstructionName(instructionName
);
973 appendRegisterName(rd());
975 appendRegisterName(rm());
976 appendImmShift(type(), immediate5());
978 return m_formatBuffer
;
984 bool testOrCmpInstruction
= false;
988 instructionName
= "tst";
989 testOrCmpInstruction
= true;
992 instructionName
= "teq";
993 testOrCmpInstruction
= true;
996 instructionName
= "cmn";
997 testOrCmpInstruction
= true;
1000 instructionName
= "cmp";
1001 testOrCmpInstruction
= true;
1005 if (testOrCmpInstruction
) {
1006 appendInstructionName(instructionName
);
1007 appendRegisterName(rn());
1009 appendRegisterName(rm());
1010 appendImmShift(type(), immediate5());
1012 return m_formatBuffer
;
1017 appendInstructionName(instructionName
);
1018 appendRegisterName(rd());
1020 appendRegisterName(rn());
1022 appendRegisterName(rm());
1023 appendImmShift(type(), immediate5());
1025 return m_formatBuffer
;
1028 const char* ARMv7DOpcodeFPTransfer::format()
1030 appendInstructionName("vmov");
1037 appendRegisterName(rt());
1044 return m_formatBuffer
;
1047 void ARMv7DOpcodeFPTransfer::appendFPRegister()
1050 appendFPRegisterName('d', vd());
1051 bufferPrintf("[%u]", opH());
1053 appendFPRegisterName('s', vn());
1056 const char* ARMv7DOpcodeDataProcessingRegShift::format()
1058 appendInstructionName(opName());
1059 appendRegisterName(rd());
1061 appendRegisterName(rn());
1063 appendRegisterName(rm());
1065 return m_formatBuffer
;
1068 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames
[8] = {
1069 "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb"
1072 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames
[8] = {
1073 "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab"
1076 const char* ARMv7DOpcodeDataProcessingRegExtend::format()
1078 const char* instructionName
;
1081 instructionName
= opExtendName();
1083 instructionName
= opExtendAndAddName();
1085 if (!instructionName
)
1086 return defaultFormat();
1088 appendInstructionName(instructionName
);
1089 appendRegisterName(rd());
1091 appendRegisterName(rn());
1093 appendRegisterName(rm());
1097 appendString("ror ");
1098 appendUnsignedImmediate(rotate() * 8);
1101 return m_formatBuffer
;
1104 const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames
[16] = {
1105 "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0,
1106 "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0
1109 const char* ARMv7DOpcodeDataProcessingRegParallel::format()
1111 const char* instructionName
;
1113 instructionName
= opName();
1115 if (!instructionName
)
1116 return defaultFormat();
1118 appendInstructionName(instructionName
);
1119 appendRegisterName(rd());
1121 appendRegisterName(rn());
1123 appendRegisterName(rm());
1125 return m_formatBuffer
;
1128 const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames
[16] = {
1129 "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh",
1130 "sel", 0, 0, 0, "clz"
1133 const char* ARMv7DOpcodeDataProcessingRegMisc::format()
1135 const char* instructionName
;
1137 instructionName
= opName();
1139 if (!instructionName
)
1140 return defaultFormat();
1142 if ((op1() & 0x1) && (rn() != rm()))
1143 return defaultFormat();
1145 appendInstructionName(instructionName
);
1146 appendRegisterName(rd());
1149 if (op1() == 0x2) { // sel
1150 appendRegisterName(rn());
1152 appendRegisterName(rm());
1154 return m_formatBuffer
;
1157 appendRegisterName(rm());
1159 if (!(op1() & 0x1)) {
1161 appendRegisterName(rn());
1164 return m_formatBuffer
;
1167 const char* const ARMv7DOpcodeHint32::s_opNames
[8] = {
1168 "nop", "yield", "wfe", "wfi", "sev"
1171 const char* ARMv7DOpcodeHint32::format()
1173 if (isDebugHint()) {
1174 appendInstructionName("debug");
1175 appendUnsignedImmediate(debugOption());
1177 return m_formatBuffer
;
1181 return defaultFormat();
1183 appendInstructionName(opName());
1185 return m_formatBuffer
;
1188 const char* const ARMv7DOpcodeDataLoad::s_opNames
[8] = {
1189 "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh"
1192 const char* ARMv7DOpcodeLoadRegister::format()
1194 appendInstructionName(opName());
1195 appendRegisterName(rt());
1197 appendCharacter('[');
1198 appendRegisterName(rn());
1200 appendRegisterName(rm());
1203 appendUnsignedImmediate(immediate2());
1205 appendCharacter(']');
1207 return m_formatBuffer
;
1210 const char* ARMv7DOpcodeLoadSignedImmediate::format()
1212 appendInstructionName(opName());
1213 appendRegisterName(rt());
1215 appendCharacter('[');
1216 appendRegisterName(rn());
1218 if (wBit() || immediate8()) {
1221 appendUnsignedImmediate(immediate8());
1223 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1225 appendCharacter(']');
1227 appendCharacter('!');
1229 appendCharacter(']');
1232 appendUnsignedImmediate(immediate8());
1234 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1237 return m_formatBuffer
;
1240 const char* ARMv7DOpcodeLoadUnsignedImmediate::format()
1242 appendInstructionName(opName());
1243 appendRegisterName(rt());
1245 appendCharacter('[');
1246 appendRegisterName(rn());
1247 if (immediate12()) {
1249 appendUnsignedImmediate(immediate12());
1251 appendCharacter(']');
1253 return m_formatBuffer
;
1256 const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames
[8] = {
1257 "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0
1260 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames
[4] = {
1261 "smlalbb", "smlalbt", "smlaltb", "smlaltt"
1264 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames
[2] = {
1268 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames
[2] = {
1272 const char* ARMv7DOpcodeLongMultipleDivide::format()
1274 const char* instructionName
= opName();
1280 return defaultFormat();
1285 return defaultFormat();
1288 if ((op2() & 0xc) == 0x8)
1289 instructionName
= smlalOpName();
1290 else if ((op2() & 0xe) == 0xc)
1291 instructionName
= smlaldOpName();
1293 return defaultFormat();
1296 if ((op2() & 0xe) == 0xc)
1297 instructionName
= smlaldOpName();
1299 return defaultFormat();
1303 instructionName
= "umaal";
1305 return defaultFormat();
1308 return defaultFormat();
1312 appendInstructionName(instructionName
);
1313 if ((op1() & 0x5) == 0x1) { // sdiv and udiv
1315 return defaultFormat();
1317 appendRegisterName(rdLo());
1320 appendRegisterName(rdHi());
1322 appendRegisterName(rn());
1324 appendRegisterName(rm());
1326 return m_formatBuffer
;
1329 const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames
[16] = {
1330 "addw", 0, "movw", 0, 0, "subw", "movt", 0,
1331 "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0
1334 const char* ARMv7DOpcodeUnmodifiedImmediate::format()
1336 const char* instructionName
= opName();
1338 switch (op() >> 1) {
1342 instructionName
= "adr";
1346 instructionName
= "ssat";
1350 instructionName
= "bfc";
1354 instructionName
= "usat";
1358 if (!instructionName
)
1359 return defaultFormat();
1361 appendInstructionName(instructionName
);
1362 appendRegisterName(rd());
1365 if ((op() & 0x17) == 0x4) { // movw or movt
1366 appendUnsignedImmediate(immediate16());
1368 return m_formatBuffer
;
1371 if (!op() || (op() == 0xa)) { // addw, subw and adr
1375 if ((op() == 0xa) && (rn() == 0xf))
1376 offset
= 0 - static_cast<int32_t>(immediate12());
1378 offset
= static_cast<int32_t>(immediate12());
1380 appendPCRelativeOffset(offset
);
1382 return m_formatBuffer
;
1385 appendRegisterName(rn());
1387 appendUnsignedImmediate(immediate12());
1389 return m_formatBuffer
;
1392 if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16
1394 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1396 appendRegisterName(rn());
1397 if (shBit() || immediate5()) {
1399 appendShiftType(shBit() << 1);
1400 appendUnsignedImmediate(immediate5());
1403 return m_formatBuffer
;
1406 if (op() == 0x16) { // bfi or bfc
1407 int width
= static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1;
1410 return defaultFormat();
1414 appendRegisterName(rn());
1417 appendUnsignedImmediate(immediate5());
1419 appendSignedImmediate(width
);
1421 return m_formatBuffer
;
1424 // Must be sbfx or ubfx
1426 appendRegisterName(rn());
1428 appendUnsignedImmediate(immediate5());
1430 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1432 return m_formatBuffer
;
1435 const char* const ARMv7DOpcodeDataStoreSingle::s_opNames
[4] = {
1436 "strb", "strh", "str", 0
1439 const char* ARMv7DOpcodeDataPushPopSingle::format()
1441 appendInstructionName(opName());
1442 appendRegisterName(rt());
1444 return m_formatBuffer
;
1447 const char* ARMv7DOpcodeStoreSingleImmediate12::format()
1449 appendInstructionName(opName());
1450 appendRegisterName(rt());
1452 appendCharacter('[');
1453 appendRegisterName(rn());
1454 if (immediate12()) {
1456 appendUnsignedImmediate(immediate12());
1458 appendCharacter(']');
1460 return m_formatBuffer
;
1463 const char* ARMv7DOpcodeStoreSingleImmediate8::format()
1465 if (pBit() && uBit() && !wBit()) // Really undecoded strt
1466 return defaultFormat();
1468 if ((rn() == 0xf) || (!pBit() && !wBit()))
1469 return defaultFormat();
1471 appendInstructionName(opName());
1472 appendRegisterName(rt());
1474 appendCharacter('[');
1475 appendRegisterName(rn());
1478 appendCharacter(']');
1480 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1482 return m_formatBuffer
;
1487 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1489 appendCharacter(']');
1492 appendCharacter('!');
1494 return m_formatBuffer
;
1497 const char* ARMv7DOpcodeStoreSingleRegister::format()
1499 appendInstructionName(opName());
1500 appendRegisterName(rt());
1502 appendCharacter('[');
1503 appendRegisterName(rn());
1505 appendRegisterName(rm());
1508 appendString("lsl ");
1509 appendUnsignedImmediate(immediate2());
1511 appendCharacter(']');
1513 return m_formatBuffer
;
1516 const char* ARMv7DOpcodeVMOVDoublePrecision::format()
1518 appendInstructionName("vmov");
1520 appendRegisterName(rt());
1522 appendRegisterName(rt2());
1526 appendFPRegisterName('d', vm());
1530 appendRegisterName(rt());
1532 appendRegisterName(rt2());
1535 return m_formatBuffer
;
1538 const char* ARMv7DOpcodeVMOVSinglePrecision::format()
1540 appendInstructionName("vmov");
1542 appendRegisterName(rt());
1544 appendRegisterName(rt2());
1548 appendFPRegisterName('s', vm());
1550 appendFPRegisterName('s', (vm() + 1) % 32);
1554 appendRegisterName(rt());
1556 appendRegisterName(rt2());
1559 return m_formatBuffer
;
1562 const char* ARMv7DOpcodeVMSR::format()
1564 appendInstructionName("vmrs");
1567 appendString("apsr_nzcv");
1569 appendRegisterName(rt());
1573 appendString("fpscr");
1577 appendRegisterName(rt());
1580 return m_formatBuffer
;
1583 } } // namespace JSC::ARMv7Disassembler
1585 #endif // #if USE(ARMV7_DISASSEMBLER)