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"
36 namespace JSC
{ namespace ARMv7Disassembler
{
38 ARMv7D16BitOpcode::OpcodeGroup
* ARMv7D16BitOpcode::opcodeTable
[32];
39 ARMv7D32BitOpcode::OpcodeGroup
* ARMv7D32BitOpcode::opcodeTable
[16];
41 const char* const ARMv7DOpcode::s_conditionNames
[16] = {
42 "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
43 "hi", "ls", "ge", "lt", "gt", "le", "al", "al"
46 const char* const ARMv7DOpcode::s_optionName
[8] = {
47 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"
50 const char* const ARMv7DOpcode::s_shiftNames
[4] = {
51 "lsl", "lsr", "asl", "ror"
54 const char* const ARMv7DOpcode::s_specialRegisterNames
[3] = { "sp", "lr", "pc" };
56 template <typename OpcodeType
, typename InstructionType
>
57 struct OpcodeGroupInitializer
{
58 unsigned m_opcodeGroupNumber
;
59 InstructionType m_mask
;
60 InstructionType m_pattern
;
61 const char* (*m_format
)(OpcodeType
*);
64 #define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \
65 { groupIndex, groupClass::s_mask, groupClass::s_pattern, groupClass::format }
67 typedef OpcodeGroupInitializer
<ARMv7D16BitOpcode
, uint16_t> Opcode16GroupInitializer
;
68 typedef OpcodeGroupInitializer
<ARMv7D32BitOpcode
, uint32_t> Opcode32GroupInitializer
;
70 static 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
)
114 static 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
),
147 bool ARMv7DOpcode::s_initialized
= false;
149 void ARMv7DOpcode::init()
154 ARMv7D16BitOpcode::init();
155 ARMv7D32BitOpcode::init();
157 s_initialized
= true;
160 void ARMv7DOpcode::startITBlock(unsigned blocksize
, unsigned firstCondition
)
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
;
169 void ARMv7DOpcode::saveITConditionAt(unsigned blockPosition
, unsigned condition
)
171 if (blockPosition
< m_ITBlocksize
)
172 m_ifThenConditions
[blockPosition
] = static_cast<unsigned char>(condition
);
175 void ARMv7DOpcode::fetchOpcode(uint16_t*& newPC
)
178 m_formatBuffer
[0] = '\0';
183 if (is32BitInstruction()) {
185 m_opcode
|= *newPC
++;
188 if (m_ITConditionIndex
< m_ITBlocksize
)
189 m_currentITCondition
= m_ifThenConditions
[m_ITConditionIndex
];
191 m_currentITCondition
= CondNone
;
194 const char* ARMv7DOpcode::disassemble(uint16_t*& currentPC
)
197 fetchOpcode(currentPC
);
199 if (is32BitInstruction())
200 result
= reinterpret_cast<ARMv7D32BitOpcode
*>(this)->doDisassemble();
202 result
= reinterpret_cast<ARMv7D16BitOpcode
*>(this)->doDisassemble();
204 if (startingITBlock())
205 m_ITConditionIndex
= 0;
206 else if (inITBlock() && (++m_ITConditionIndex
>= m_ITBlocksize
))
212 void ARMv7DOpcode::bufferPrintf(const char* format
, ...)
214 if (m_bufferOffset
>= bufferSize
)
218 va_start(argList
, format
);
220 m_bufferOffset
+= vsnprintf(m_formatBuffer
+ m_bufferOffset
, bufferSize
- m_bufferOffset
, format
, argList
);
225 void ARMv7DOpcode::appendInstructionName(const char* instructionName
, bool addS
)
227 if (!inITBlock() && !addS
) {
228 appendInstructionNameNoITBlock(instructionName
);
233 const char sevenSpaces
[8] = " ";
235 unsigned length
= strlen(instructionName
);
237 bufferPrintf(" %s", instructionName
);
239 const char* condition
= conditionName(m_currentITCondition
);
240 length
+= strlen(condition
);
241 appendString(condition
);
244 appendCharacter('s');
250 appendString(sevenSpaces
+ length
);
253 void ARMv7DOpcode::appendRegisterName(unsigned registerNumber
)
255 registerNumber
&= 0xf;
257 if (registerNumber
> 12) {
258 appendString(s_specialRegisterNames
[registerNumber
- 13]);
262 bufferPrintf("r%u", registerNumber
);
265 void ARMv7DOpcode::appendRegisterList(unsigned registers
)
267 unsigned numberPrinted
= 0;
269 appendCharacter('{');
271 for (unsigned i
= 0; i
< 16; i
++) {
275 appendRegisterName(i
);
279 appendCharacter('}');
282 void ARMv7DOpcode::appendFPRegisterName(char registerPrefix
, unsigned registerNumber
)
284 bufferPrintf("%c%u", registerPrefix
, registerNumber
);
287 // 16 Bit Instructions
289 void ARMv7D16BitOpcode::init()
291 OpcodeGroup
* lastGroups
[OpcodeGroup::opcodeTableSize
];
293 for (unsigned i
= 0; i
< OpcodeGroup::opcodeTableSize
; i
++) {
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
;
302 if (!opcodeTable
[opcodeGroupNumber
])
303 opcodeTable
[opcodeGroupNumber
] = newOpcodeGroup
;
305 lastGroups
[opcodeGroupNumber
]->setNext(newOpcodeGroup
);
306 lastGroups
[opcodeGroupNumber
] = newOpcodeGroup
;
310 const char* ARMv7D16BitOpcode::doDisassemble()
312 OpcodeGroup
* opGroup
= opcodeTable
[opcodeGroupNumber(m_opcode
)];
315 if (opGroup
->matches(static_cast<uint16_t>(m_opcode
)))
316 return opGroup
->format(this);
317 opGroup
= opGroup
->next();
320 return defaultFormat();
323 const char* ARMv7D16BitOpcode::defaultFormat()
325 bufferPrintf(" .word %04x", m_opcode
);
326 return m_formatBuffer
;
329 const char* ARMv7DOpcodeAddRegisterT2::format()
331 appendInstructionName("add");
332 appendRegisterName(rdn());
334 appendRegisterName(rm());
336 return m_formatBuffer
;
339 const char* ARMv7DOpcodeAddSPPlusImmediate::format()
341 appendInstructionName("add");
342 appendRegisterName(rd());
344 appendRegisterName(RegSP
);
346 appendUnsignedImmediate(immediate8());
348 return m_formatBuffer
;
351 const char* const ARMv7DOpcodeAddSubtract::s_opNames
[2] = { "add", "sub" };
353 const char* ARMv7DOpcodeAddSubtractT1::format()
355 appendInstructionName(opName(), !inITBlock());
356 appendRegisterName(rd());
358 appendRegisterName(rn());
360 appendRegisterName(rm());
362 return m_formatBuffer
;
365 const char* ARMv7DOpcodeAddSubtractImmediate3::format()
367 appendInstructionName(opName(), !inITBlock());
368 appendRegisterName(rd());
370 appendRegisterName(rn());
372 appendUnsignedImmediate(immediate3());
374 return m_formatBuffer
;
377 const char* ARMv7DOpcodeAddSubtractImmediate8::format()
379 appendInstructionName(opName(), !inITBlock());
380 appendRegisterName(rdn());
382 appendUnsignedImmediate(immediate8());
384 return m_formatBuffer
;
387 const char* ARMv7DOpcodeBranchConditionalT1::format()
389 if (condition() == 0xe)
390 return defaultFormat();
392 if (condition() == 0xf) {
393 appendInstructionName("svc");
394 appendUnsignedImmediate(offset());
396 return m_formatBuffer
;
399 bufferPrintf(" b%-6.6s", conditionName(condition()));
400 appendPCRelativeOffset(static_cast<int32_t>(offset()) + 2);
402 return m_formatBuffer
;
405 const char* ARMv7DOpcodeBranchExchangeT1::format()
407 appendInstructionName(opName());
408 appendRegisterName(rm());
410 return m_formatBuffer
;
413 const char* ARMv7DOpcodeBranchT2::format()
415 appendInstructionName("b");
416 appendPCRelativeOffset(static_cast<int32_t>(immediate11()) + 2);
418 return m_formatBuffer
;
421 const char* ARMv7DOpcodeCompareImmediateT1::format()
423 appendInstructionName("cmp");
424 appendRegisterName(rn());
426 appendUnsignedImmediate(immediate8());
428 return m_formatBuffer
;
431 const char* ARMv7DOpcodeCompareRegisterT1::format()
433 appendInstructionName("cmp");
434 appendRegisterName(rn());
436 appendRegisterName(rm());
438 return m_formatBuffer
;
441 const char* ARMv7DOpcodeCompareRegisterT2::format()
443 appendInstructionName("compare");
444 appendRegisterName(rn());
446 appendRegisterName(rm());
448 return m_formatBuffer
;
451 const char* const ARMv7DOpcodeDataProcessingRegisterT1::s_opNames
[16] = {
452 "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn"
455 const char* ARMv7DOpcodeDataProcessingRegisterT1::format()
457 appendInstructionName(opName(), inITBlock() && (!(op() == 0x8) || (op() == 0xa) || (op() == 0xb)));
458 appendRegisterName(rdn());
460 appendRegisterName(rm());
461 if (op() == 0x9) // rsb T1
462 appendString(", #0");
463 else if (op() == 0xd) { // mul T1
465 appendRegisterName(rdn());
468 return m_formatBuffer
;
471 const char* ARMv7DOpcodeGeneratePCRelativeAddress::format()
473 appendInstructionName("adr");
474 appendRegisterName(rd());
476 appendPCRelativeOffset(static_cast<int32_t>(immediate8()));
478 return m_formatBuffer
;
481 const char* ARMv7DOpcodeLoadFromLiteralPool::format()
483 appendInstructionName("ldr");
484 appendRegisterName(rt());
486 appendPCRelativeOffset(static_cast<int32_t>(immediate8()));
488 return m_formatBuffer
;
491 const char* const ARMv7DOpcodeLoadStoreRegisterImmediate::s_opNames
[6] = {
492 "str", "ldr", "strb", "ldrb", "strh", "ldrh"
495 const char* ARMv7DOpcodeLoadStoreRegisterImmediate::format()
497 const char* instructionName
= opName();
499 if (!instructionName
)
500 return defaultFormat();
502 appendInstructionName(opName());
503 appendRegisterName(rt());
505 appendCharacter('[');
506 appendRegisterName(rn());
509 appendUnsignedImmediate(immediate5() << scale());
511 appendCharacter(']');
513 return m_formatBuffer
;
516 const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames
[8] = {
517 "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh"
520 const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format()
522 appendInstructionName(opName());
523 appendRegisterName(rt());
525 appendCharacter('[');
526 appendRegisterName(rn());
528 appendRegisterName(rm());
529 appendCharacter(']');
531 return m_formatBuffer
;
534 const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format()
536 appendInstructionName(opName());
537 appendRegisterName(rt());
539 appendCharacter('[');
540 appendRegisterName(RegSP
);
543 appendUnsignedImmediate(immediate8() << 2);
545 appendCharacter(']');
547 return m_formatBuffer
;
550 const char* ARMv7DOpcodeLogicalImmediateT1::format()
552 if (!op() && !immediate5()) {
554 appendInstructionName("movs");
555 appendRegisterName(rd());
557 appendRegisterName(rm());
559 return m_formatBuffer
;
562 appendInstructionName(opName(), !inITBlock());
563 appendRegisterName(rd());
565 appendRegisterName(rm());
567 appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5());
569 return m_formatBuffer
;
572 const char* ARMv7DOpcodeMiscAddSubSP::format()
574 appendInstructionName(opName());
575 appendRegisterName(RegSP
);
577 appendRegisterName(RegSP
);
579 appendUnsignedImmediate(immediate7());
581 return m_formatBuffer
;
584 const char* ARMv7DOpcodeMiscBreakpointT1::format()
586 appendInstructionNameNoITBlock("bkpt");
587 appendUnsignedImmediate(immediate8());
589 return m_formatBuffer
;
592 const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames
[8] = {
593 "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh"
596 const char* ARMv7DOpcodeMiscByteHalfwordOps::format()
598 const char* instructionName
= opName();
600 if (!instructionName
)
601 return defaultFormat();
603 appendInstructionName(instructionName
);
604 appendRegisterName(rd());
606 appendRegisterName(rm());
608 return m_formatBuffer
;
611 const char* ARMv7DOpcodeMiscCompareAndBranch::format()
613 appendInstructionName(opName());
614 appendPCRelativeOffset(immediate6() + 2);
616 return m_formatBuffer
;
619 const char* const ARMv7DOpcodeMiscHint16::s_opNames
[16] = {
620 "nop", "yield", "wfe", "wfi", "sev"
623 const char* ARMv7DOpcodeMiscHint16::format()
626 return defaultFormat();
628 appendInstructionName(opName());
630 return m_formatBuffer
;
633 const char* ARMv7DOpcodeMiscIfThenT1::format()
639 unsigned condition
= firstCondition();
640 unsigned maskBits
= mask();
641 unsigned blockLength
= 0;
643 for (unsigned i
= 0; i
< 4; ++i
) {
644 if (maskBits
& (1 << i
)) {
650 startITBlock(blockLength
, condition
);
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
);
657 opName
[blockLength
+ 1] = '\0';
659 appendInstructionNameNoITBlock(opName
);
660 appendString(conditionName(condition
));
662 return m_formatBuffer
;
665 const char* ARMv7DOpcodeMiscPushPop::format()
667 appendInstructionName(opName());
668 appendRegisterList(registerMask());
670 return m_formatBuffer
;
673 const char* ARMv7DOpcodeMoveImmediateT1::format()
675 appendInstructionName("mov", !inITBlock());
676 appendRegisterName(rd());
678 appendUnsignedImmediate(immediate8());
680 return m_formatBuffer
;
683 const char* ARMv7DOpcodeMoveRegisterT1::format()
685 appendInstructionName("mov");
686 appendRegisterName(rd());
688 appendRegisterName(rm());
690 return m_formatBuffer
;
693 // 32 bit Intructions
695 void ARMv7D32BitOpcode::init()
697 OpcodeGroup
* lastGroups
[OpcodeGroup::opcodeTableSize
];
699 for (unsigned i
= 0; i
< OpcodeGroup::opcodeTableSize
; i
++) {
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
;
708 if (!opcodeTable
[opcodeGroupNumber
])
709 opcodeTable
[opcodeGroupNumber
] = newOpcodeGroup
;
711 lastGroups
[opcodeGroupNumber
]->setNext(newOpcodeGroup
);
712 lastGroups
[opcodeGroupNumber
] = newOpcodeGroup
;
716 const char* ARMv7D32BitOpcode::doDisassemble()
718 OpcodeGroup
* opGroup
= opcodeTable
[opcodeGroupNumber(m_opcode
)];
721 if (opGroup
->matches(m_opcode
))
722 return opGroup
->format(this);
723 opGroup
= opGroup
->next();
726 return defaultFormat();
729 const char* ARMv7D32BitOpcode::defaultFormat()
731 bufferPrintf(" .long %08x", m_opcode
);
732 return m_formatBuffer
;
735 const char* ARMv7DOpcodeConditionalBranchT3::format()
737 if (condition() < 0xe)
738 bufferPrintf(" b%-6.6s", conditionName(condition()));
740 appendInstructionName("b");
741 appendPCRelativeOffset(offset() + 2);
743 return m_formatBuffer
;
746 const char* ARMv7DOpcodeBranchOrBranchLink::format()
748 appendInstructionName(isBL() ? "bl" : "b");
749 appendPCRelativeOffset(offset() + 2);
751 return m_formatBuffer
;
754 const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames
[16] = {
755 "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0
758 void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12
)
760 if (!(immediate12
& 0xc00)) {
761 unsigned immediate
= 0;
762 unsigned lower8Bits
= immediate12
& 0xff;
764 switch ((immediate12
>> 8) & 3) {
766 immediate
= lower8Bits
;
769 immediate
= (lower8Bits
<< 16) | lower8Bits
;
772 immediate
= (lower8Bits
<< 24) | (lower8Bits
<< 8);
775 immediate
= (lower8Bits
<< 24) | (lower8Bits
<< 16) | (lower8Bits
<< 8) | lower8Bits
;
778 appendUnsignedImmediate(immediate
);
782 unsigned immediate8
= 0x80 | (immediate12
& 0x7f);
783 unsigned shiftAmount
= 32 - ((immediate12
>> 7) & 0x1f);
785 appendUnsignedImmediate(immediate8
<< shiftAmount
);
788 const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format()
790 if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
791 return defaultFormat();
793 const char* instructionName
= opName();
798 instructionName
= sBit() ? "movs" : "mov";
799 appendInstructionName(instructionName
);
800 appendRegisterName(rd());
802 appendModifiedImmediate(immediate12());
804 return m_formatBuffer
;
809 instructionName
= sBit() ? "mvns" : "mvn";
810 appendInstructionName(instructionName
);
811 appendRegisterName(rd());
813 appendModifiedImmediate(immediate12());
815 return m_formatBuffer
;
821 bool testOrCmpInstruction
= false;
825 instructionName
= "tst";
826 testOrCmpInstruction
= true;
829 instructionName
= "teq";
830 testOrCmpInstruction
= true;
833 instructionName
= "cmn";
834 testOrCmpInstruction
= true;
837 instructionName
= "cmp";
838 testOrCmpInstruction
= true;
842 if (testOrCmpInstruction
) {
843 appendInstructionName(instructionName
);
844 appendRegisterName(rn());
846 appendModifiedImmediate(immediate12());
848 return m_formatBuffer
;
853 appendInstructionName(instructionName
);
854 appendRegisterName(rd());
856 appendRegisterName(rn());
858 appendModifiedImmediate(immediate12());
860 return m_formatBuffer
;
863 void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type
, unsigned immediate
)
865 if (type
|| immediate
) {
880 appendShiftType(type
);
881 appendUnsignedImmediate(immediate
);
885 const char* ARMv7DOpcodeDataProcessingShiftedReg::format()
887 if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
888 return defaultFormat();
892 if (sBit() || tBit())
893 return defaultFormat();
896 appendInstructionName("pkhtb");
898 appendInstructionName("pkhbt");
899 appendRegisterName(rd());
901 appendRegisterName(rn());
903 appendRegisterName(rm());
904 appendImmShift(tbBit() << 1, immediate5());
906 return m_formatBuffer
;
909 const char* instructionName
= opName();
913 if (!type() && !immediate5()) {
915 instructionName
= sBit() ? "movs" : "mov";
916 appendInstructionName(instructionName
);
917 appendRegisterName(rd());
919 appendRegisterName(rm());
921 return m_formatBuffer
;
924 if (type() == 3 && !immediate5()) {
926 instructionName
= sBit() ? "rrx" : "rrx";
927 appendInstructionName(instructionName
);
928 appendRegisterName(rd());
930 appendRegisterName(rm());
932 return m_formatBuffer
;
937 bufferPrintf("%ss ", shiftName(type()));
939 appendInstructionName(shiftName(type()));
940 appendRegisterName(rd());
942 appendRegisterName(rm());
944 appendUnsignedImmediate(immediate5());
946 return m_formatBuffer
;
951 instructionName
= sBit() ? "mvns" : "mvn";
952 appendInstructionName(instructionName
);
953 appendRegisterName(rd());
955 appendRegisterName(rm());
956 appendImmShift(type(), immediate5());
958 return m_formatBuffer
;
964 bool testOrCmpInstruction
= false;
968 instructionName
= "tst";
969 testOrCmpInstruction
= true;
972 instructionName
= "teq";
973 testOrCmpInstruction
= true;
976 instructionName
= "cmn";
977 testOrCmpInstruction
= true;
980 instructionName
= "cmp";
981 testOrCmpInstruction
= true;
985 if (testOrCmpInstruction
) {
986 appendInstructionName(instructionName
);
987 appendRegisterName(rn());
989 appendRegisterName(rm());
990 appendImmShift(type(), immediate5());
992 return m_formatBuffer
;
997 appendInstructionName(instructionName
);
998 appendRegisterName(rd());
1000 appendRegisterName(rn());
1002 appendRegisterName(rm());
1003 appendImmShift(type(), immediate5());
1005 return m_formatBuffer
;
1008 const char* ARMv7DOpcodeFPTransfer::format()
1010 appendInstructionName("vmov");
1017 appendRegisterName(rt());
1024 return m_formatBuffer
;
1027 void ARMv7DOpcodeFPTransfer::appendFPRegister()
1030 appendFPRegisterName('d', vd());
1031 bufferPrintf("[%u]", opH());
1033 appendFPRegisterName('s', vn());
1036 const char* ARMv7DOpcodeDataProcessingRegShift::format()
1038 appendInstructionName(opName());
1039 appendRegisterName(rd());
1041 appendRegisterName(rn());
1043 appendRegisterName(rm());
1045 return m_formatBuffer
;
1048 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames
[8] = {
1049 "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb"
1052 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames
[8] = {
1053 "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab"
1056 const char* ARMv7DOpcodeDataProcessingRegExtend::format()
1058 const char* instructionName
;
1061 instructionName
= opExtendName();
1063 instructionName
= opExtendAndAddName();
1065 if (!instructionName
)
1066 return defaultFormat();
1068 appendInstructionName(instructionName
);
1069 appendRegisterName(rd());
1071 appendRegisterName(rn());
1073 appendRegisterName(rm());
1077 appendString("ror ");
1078 appendUnsignedImmediate(rotate() * 8);
1081 return m_formatBuffer
;
1084 const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames
[16] = {
1085 "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0,
1086 "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0
1089 const char* ARMv7DOpcodeDataProcessingRegParallel::format()
1091 const char* instructionName
;
1093 instructionName
= opName();
1095 if (!instructionName
)
1096 return defaultFormat();
1098 appendInstructionName(instructionName
);
1099 appendRegisterName(rd());
1101 appendRegisterName(rn());
1103 appendRegisterName(rm());
1105 return m_formatBuffer
;
1108 const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames
[16] = {
1109 "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh",
1110 "sel", 0, 0, 0, "clz"
1113 const char* ARMv7DOpcodeDataProcessingRegMisc::format()
1115 const char* instructionName
;
1117 instructionName
= opName();
1119 if (!instructionName
)
1120 return defaultFormat();
1122 if ((op1() & 0x1) && (rn() != rm()))
1123 return defaultFormat();
1125 appendInstructionName(instructionName
);
1126 appendRegisterName(rd());
1129 if (op1() == 0x2) { // sel
1130 appendRegisterName(rn());
1132 appendRegisterName(rm());
1134 return m_formatBuffer
;
1137 appendRegisterName(rm());
1139 if (!(op1() & 0x1)) {
1141 appendRegisterName(rn());
1144 return m_formatBuffer
;
1147 const char* const ARMv7DOpcodeHint32::s_opNames
[8] = {
1148 "nop", "yield", "wfe", "wfi", "sev"
1151 const char* ARMv7DOpcodeHint32::format()
1153 if (isDebugHint()) {
1154 appendInstructionName("debug");
1155 appendUnsignedImmediate(debugOption());
1157 return m_formatBuffer
;
1161 return defaultFormat();
1163 appendInstructionName(opName());
1165 return m_formatBuffer
;
1168 const char* const ARMv7DOpcodeDataLoad::s_opNames
[8] = {
1169 "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh"
1172 const char* ARMv7DOpcodeLoadRegister::format()
1174 appendInstructionName(opName());
1175 appendRegisterName(rt());
1177 appendCharacter('[');
1178 appendRegisterName(rn());
1180 appendRegisterName(rm());
1183 appendUnsignedImmediate(immediate2());
1185 appendCharacter(']');
1187 return m_formatBuffer
;
1190 const char* ARMv7DOpcodeLoadSignedImmediate::format()
1192 appendInstructionName(opName());
1193 appendRegisterName(rt());
1195 appendCharacter('[');
1196 appendRegisterName(rn());
1198 if (wBit() || immediate8()) {
1201 appendUnsignedImmediate(immediate8());
1203 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1205 appendCharacter(']');
1207 appendCharacter('!');
1209 appendCharacter(']');
1212 appendUnsignedImmediate(immediate8());
1214 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1217 return m_formatBuffer
;
1220 const char* ARMv7DOpcodeLoadUnsignedImmediate::format()
1222 appendInstructionName(opName());
1223 appendRegisterName(rt());
1225 appendCharacter('[');
1226 appendRegisterName(rn());
1227 if (immediate12()) {
1229 appendUnsignedImmediate(immediate12());
1231 appendCharacter(']');
1233 return m_formatBuffer
;
1236 const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames
[8] = {
1237 "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0
1240 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames
[4] = {
1241 "smlalbb", "smlalbt", "smlaltb", "smlaltt"
1244 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames
[2] = {
1248 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames
[2] = {
1252 const char* ARMv7DOpcodeLongMultipleDivide::format()
1254 const char* instructionName
= opName();
1260 return defaultFormat();
1265 return defaultFormat();
1268 if ((op2() & 0xc) == 0x8)
1269 instructionName
= smlalOpName();
1270 else if ((op2() & 0xe) == 0xc)
1271 instructionName
= smlaldOpName();
1273 return defaultFormat();
1276 if ((op2() & 0xe) == 0xc)
1277 instructionName
= smlaldOpName();
1279 return defaultFormat();
1283 instructionName
= "umaal";
1285 return defaultFormat();
1288 return defaultFormat();
1292 appendInstructionName(instructionName
);
1293 if ((op1() & 0x5) == 0x1) { // sdiv and udiv
1295 return defaultFormat();
1297 appendRegisterName(rdLo());
1300 appendRegisterName(rdHi());
1302 appendRegisterName(rn());
1304 appendRegisterName(rm());
1306 return m_formatBuffer
;
1309 const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames
[16] = {
1310 "addw", 0, "movw", 0, 0, "subw", "movt", 0,
1311 "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0
1314 const char* ARMv7DOpcodeUnmodifiedImmediate::format()
1316 const char* instructionName
= opName();
1318 switch (op() >> 1) {
1322 instructionName
= "adr";
1326 instructionName
= "ssat";
1330 instructionName
= "bfc";
1334 instructionName
= "usat";
1338 if (!instructionName
)
1339 return defaultFormat();
1341 appendInstructionName(instructionName
);
1342 appendRegisterName(rd());
1345 if ((op() & 0x17) == 0x4) { // movw or movt
1346 appendUnsignedImmediate(immediate16());
1348 return m_formatBuffer
;
1351 if (!op() || (op() == 0xa)) { // addw, subw and adr
1355 if ((op() == 0xa) && (rn() == 0xf))
1356 offset
= 0 - static_cast<int32_t>(immediate12());
1358 offset
= static_cast<int32_t>(immediate12());
1360 appendPCRelativeOffset(offset
);
1362 return m_formatBuffer
;
1365 appendRegisterName(rn());
1367 appendUnsignedImmediate(immediate12());
1369 return m_formatBuffer
;
1372 if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16
1374 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1376 appendRegisterName(rn());
1377 if (shBit() || immediate5()) {
1379 appendShiftType(shBit() << 1);
1380 appendUnsignedImmediate(immediate5());
1383 return m_formatBuffer
;
1386 if (op() == 0x16) { // bfi or bfc
1387 int width
= static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1;
1390 return defaultFormat();
1394 appendRegisterName(rn());
1397 appendUnsignedImmediate(immediate5());
1399 appendSignedImmediate(width
);
1401 return m_formatBuffer
;
1404 // Must be sbfx or ubfx
1406 appendRegisterName(rn());
1408 appendUnsignedImmediate(immediate5());
1410 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1412 return m_formatBuffer
;
1415 const char* const ARMv7DOpcodeDataStoreSingle::s_opNames
[4] = {
1416 "strb", "strh", "str", 0
1419 const char* ARMv7DOpcodeDataPushPopSingle::format()
1421 appendInstructionName(opName());
1422 appendRegisterName(rt());
1424 return m_formatBuffer
;
1427 const char* ARMv7DOpcodeStoreSingleImmediate12::format()
1429 appendInstructionName(opName());
1430 appendRegisterName(rt());
1432 appendCharacter('[');
1433 appendRegisterName(rn());
1434 if (immediate12()) {
1436 appendUnsignedImmediate(immediate12());
1438 appendCharacter(']');
1440 return m_formatBuffer
;
1443 const char* ARMv7DOpcodeStoreSingleImmediate8::format()
1445 if (pBit() && uBit() && !wBit()) // Really undecoded strt
1446 return defaultFormat();
1448 if ((rn() == 0xf) || (!pBit() && !wBit()))
1449 return defaultFormat();
1451 appendInstructionName(opName());
1452 appendRegisterName(rt());
1454 appendCharacter('[');
1455 appendRegisterName(rn());
1458 appendCharacter(']');
1460 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1462 return m_formatBuffer
;
1467 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1469 appendCharacter(']');
1472 appendCharacter('!');
1474 return m_formatBuffer
;
1477 const char* ARMv7DOpcodeStoreSingleRegister::format()
1479 appendInstructionName(opName());
1480 appendRegisterName(rt());
1482 appendCharacter('[');
1483 appendRegisterName(rn());
1485 appendRegisterName(rm());
1488 appendString("lsl ");
1489 appendUnsignedImmediate(immediate2());
1491 appendCharacter(']');
1493 return m_formatBuffer
;
1496 const char* ARMv7DOpcodeVMOVDoublePrecision::format()
1498 appendInstructionName("vmov");
1500 appendRegisterName(rt());
1502 appendRegisterName(rt2());
1506 appendFPRegisterName('d', vm());
1510 appendRegisterName(rt());
1512 appendRegisterName(rt2());
1515 return m_formatBuffer
;
1518 const char* ARMv7DOpcodeVMOVSinglePrecision::format()
1520 appendInstructionName("vmov");
1522 appendRegisterName(rt());
1524 appendRegisterName(rt2());
1528 appendFPRegisterName('s', vm());
1530 appendFPRegisterName('s', (vm() + 1) % 32);
1534 appendRegisterName(rt());
1536 appendRegisterName(rt2());
1539 return m_formatBuffer
;
1542 const char* ARMv7DOpcodeVMSR::format()
1544 appendInstructionName("vmrs");
1547 appendString("apsr_nzcv");
1549 appendRegisterName(rt());
1553 appendString("fpscr");
1557 appendRegisterName(rt());
1560 return m_formatBuffer
;
1563 } } // namespace JSC::ARMv7Disassembler
1565 #endif // #if USE(ARMV7_DISASSEMBLER)