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