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

source code of qtdeclarative/src/3rdparty/masm/disassembler/ARMv7/ARMv7DOpcode.cpp