]> git.saurik.com Git - apple/javascriptcore.git/blob - disassembler/ARMv7/ARMv7DOpcode.cpp
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / disassembler / ARMv7 / ARMv7DOpcode.cpp
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
37 namespace JSC { namespace ARMv7Disassembler {
38
39 ARMv7D16BitOpcode::OpcodeGroup* ARMv7D16BitOpcode::opcodeTable[32];
40 ARMv7D32BitOpcode::OpcodeGroup* ARMv7D32BitOpcode::opcodeTable[16];
41
42 const char* const ARMv7DOpcode::s_conditionNames[16] = {
43 "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
44 "hi", "ls", "ge", "lt", "gt", "le", "al", "al"
45 };
46
47 const char* const ARMv7DOpcode::s_optionName[8] = {
48 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"
49 };
50
51 const char* const ARMv7DOpcode::s_shiftNames[4] = {
52 "lsl", "lsr", "asr", "ror"
53 };
54
55 const char* const ARMv7DOpcode::s_specialRegisterNames[3] = { "sp", "lr", "pc" };
56
57 template <typename OpcodeType, typename InstructionType>
58 struct OpcodeGroupInitializer {
59 unsigned m_opcodeGroupNumber;
60 InstructionType m_mask;
61 InstructionType m_pattern;
62 const char* (*m_format)(OpcodeType*);
63 };
64
65 #define OPCODE_GROUP_ENTRY(groupIndex, groupClass) \
66 { groupIndex, groupClass::s_mask, groupClass::s_pattern, groupClass::format }
67
68 typedef OpcodeGroupInitializer<ARMv7D16BitOpcode, uint16_t> Opcode16GroupInitializer;
69 typedef OpcodeGroupInitializer<ARMv7D32BitOpcode, uint32_t> Opcode32GroupInitializer;
70
71 static Opcode16GroupInitializer opcode16BitGroupList[] = {
72 OPCODE_GROUP_ENTRY(0x0, ARMv7DOpcodeLogicalImmediateT1),
73 OPCODE_GROUP_ENTRY(0x1, ARMv7DOpcodeLogicalImmediateT1),
74 OPCODE_GROUP_ENTRY(0x2, ARMv7DOpcodeLogicalImmediateT1),
75 OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractT1),
76 OPCODE_GROUP_ENTRY(0x3, ARMv7DOpcodeAddSubtractImmediate3),
77 OPCODE_GROUP_ENTRY(0x4, ARMv7DOpcodeMoveImmediateT1),
78 OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeCompareImmediateT1),
79 OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeAddSubtractImmediate8),
80 OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeAddSubtractImmediate8),
81 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingRegisterT1),
82 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeAddRegisterT2),
83 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT2),
84 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeCompareRegisterT1),
85 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeMoveRegisterT1),
86 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchExchangeT1),
87 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeLoadFromLiteralPool),
88 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeLoadStoreRegisterOffsetT1),
89 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeLoadStoreRegisterOffsetT1),
90 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte),
91 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte),
92 OPCODE_GROUP_ENTRY(0xe, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte),
93 OPCODE_GROUP_ENTRY(0xf, ARMv7DOpcodeLoadStoreRegisterImmediateWordAndByte),
94 OPCODE_GROUP_ENTRY(0x10, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord),
95 OPCODE_GROUP_ENTRY(0x11, ARMv7DOpcodeLoadStoreRegisterImmediateHalfWord),
96 OPCODE_GROUP_ENTRY(0x12, ARMv7DOpcodeLoadStoreRegisterSPRelative),
97 OPCODE_GROUP_ENTRY(0x13, ARMv7DOpcodeLoadStoreRegisterSPRelative),
98 OPCODE_GROUP_ENTRY(0x14, ARMv7DOpcodeGeneratePCRelativeAddress),
99 OPCODE_GROUP_ENTRY(0x15, ARMv7DOpcodeAddSPPlusImmediate),
100 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscCompareAndBranch),
101 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscByteHalfwordOps),
102 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscPushPop),
103 OPCODE_GROUP_ENTRY(0x16, ARMv7DOpcodeMiscAddSubSP),
104 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscHint16), // Needs to be before IfThenT1
105 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscIfThenT1),
106 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscByteHalfwordOps),
107 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscCompareAndBranch),
108 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscPushPop),
109 OPCODE_GROUP_ENTRY(0x17, ARMv7DOpcodeMiscBreakpointT1),
110 OPCODE_GROUP_ENTRY(0x1a, ARMv7DOpcodeBranchConditionalT1),
111 OPCODE_GROUP_ENTRY(0x1b, ARMv7DOpcodeBranchConditionalT1),
112 OPCODE_GROUP_ENTRY(0x1c, ARMv7DOpcodeBranchT2)
113 };
114
115 static Opcode32GroupInitializer opcode32BitGroupList[] = {
116 OPCODE_GROUP_ENTRY(0x5, ARMv7DOpcodeDataProcessingShiftedReg),
117 OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVSinglePrecision),
118 OPCODE_GROUP_ENTRY(0x6, ARMv7DOpcodeVMOVDoublePrecision),
119 OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeFPTransfer),
120 OPCODE_GROUP_ENTRY(0x7, ARMv7DOpcodeVMSR),
121 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeDataProcessingModifiedImmediate),
122 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeConditionalBranchT3),
123 OPCODE_GROUP_ENTRY(0x8, ARMv7DOpcodeBranchOrBranchLink),
124 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeUnmodifiedImmediate),
125 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeHint32),
126 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeConditionalBranchT3),
127 OPCODE_GROUP_ENTRY(0x9, ARMv7DOpcodeBranchOrBranchLink),
128 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeDataProcessingModifiedImmediate),
129 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeConditionalBranchT3),
130 OPCODE_GROUP_ENTRY(0xa, ARMv7DOpcodeBranchOrBranchLink),
131 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeUnmodifiedImmediate),
132 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeConditionalBranchT3),
133 OPCODE_GROUP_ENTRY(0xb, ARMv7DOpcodeBranchOrBranchLink),
134 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadRegister),
135 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeDataPushPopSingle), // Should be before StoreSingle*
136 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleRegister),
137 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate12),
138 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeStoreSingleImmediate8),
139 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadSignedImmediate),
140 OPCODE_GROUP_ENTRY(0xc, ARMv7DOpcodeLoadUnsignedImmediate),
141 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeLongMultipleDivide),
142 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegShift),
143 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegExtend),
144 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegParallel),
145 OPCODE_GROUP_ENTRY(0xd, ARMv7DOpcodeDataProcessingRegMisc),
146 };
147
148 bool ARMv7DOpcode::s_initialized = false;
149
150 void ARMv7DOpcode::init()
151 {
152 if (s_initialized)
153 return;
154
155 ARMv7D16BitOpcode::init();
156 ARMv7D32BitOpcode::init();
157
158 s_initialized = true;
159 }
160
161 void 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
170 void ARMv7DOpcode::saveITConditionAt(unsigned blockPosition, unsigned condition)
171 {
172 if (blockPosition < m_ITBlocksize)
173 m_ifThenConditions[blockPosition] = static_cast<unsigned char>(condition);
174 }
175
176 void 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
195 const 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
213 void 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
226 void 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
254 void 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
266 void ARMv7DOpcode::appendRegisterList(unsigned registers)
267 {
268 unsigned numberPrinted = 0;
269
270 appendCharacter('{');
271
272 for (unsigned i = 0; i < 16; i++) {
273 if (registers & (1 << i)) {
274 if (numberPrinted++)
275 appendSeparator();
276 appendRegisterName(i);
277 }
278 }
279
280 appendCharacter('}');
281 }
282
283 void ARMv7DOpcode::appendFPRegisterName(char registerPrefix, unsigned registerNumber)
284 {
285 bufferPrintf("%c%u", registerPrefix, registerNumber);
286 }
287
288 // 16 Bit Instructions
289
290 void 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
311 const 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
324 const char* ARMv7D16BitOpcode::defaultFormat()
325 {
326 bufferPrintf(" .word %04x", m_opcode);
327 return m_formatBuffer;
328 }
329
330 const char* ARMv7DOpcodeAddRegisterT2::format()
331 {
332 appendInstructionName("add");
333 appendRegisterName(rdn());
334 appendSeparator();
335 appendRegisterName(rm());
336
337 return m_formatBuffer;
338 }
339
340 const 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
352 const char* const ARMv7DOpcodeAddSubtract::s_opNames[2] = { "add", "sub" };
353
354 const 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
366 const 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
378 const char* ARMv7DOpcodeAddSubtractImmediate8::format()
379 {
380 appendInstructionName(opName(), !inITBlock());
381 appendRegisterName(rdn());
382 appendSeparator();
383 appendUnsignedImmediate(immediate8());
384
385 return m_formatBuffer;
386 }
387
388 const 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
406 const char* ARMv7DOpcodeBranchExchangeT1::format()
407 {
408 appendInstructionName(opName());
409 appendRegisterName(rm());
410
411 return m_formatBuffer;
412 }
413
414 const char* ARMv7DOpcodeBranchT2::format()
415 {
416 appendInstructionName("b");
417 appendPCRelativeOffset(static_cast<int32_t>(immediate11()) + 2);
418
419 return m_formatBuffer;
420 }
421
422 const char* ARMv7DOpcodeCompareImmediateT1::format()
423 {
424 appendInstructionName("cmp");
425 appendRegisterName(rn());
426 appendSeparator();
427 appendUnsignedImmediate(immediate8());
428
429 return m_formatBuffer;
430 }
431
432 const char* ARMv7DOpcodeCompareRegisterT1::format()
433 {
434 appendInstructionName("cmp");
435 appendRegisterName(rn());
436 appendSeparator();
437 appendRegisterName(rm());
438
439 return m_formatBuffer;
440 }
441
442 const char* ARMv7DOpcodeCompareRegisterT2::format()
443 {
444 appendInstructionName("compare");
445 appendRegisterName(rn());
446 appendSeparator();
447 appendRegisterName(rm());
448
449 return m_formatBuffer;
450 }
451
452 const char* const ARMv7DOpcodeDataProcessingRegisterT1::s_opNames[16] = {
453 "and", "eor", "lsl", "lsr", "asr", "adc", "sbc", "ror", "tst", "rsb", "cmp", "cmn", "orr", "mul", "bic", "mvn"
454 };
455
456 const 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
472 const 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
482 const 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
492 const char* const ARMv7DOpcodeLoadStoreRegisterImmediate::s_opNames[6] = {
493 "str", "ldr", "strb", "ldrb", "strh", "ldrh"
494 };
495
496 const 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
517 const char* const ARMv7DOpcodeLoadStoreRegisterOffsetT1::s_opNames[8] = {
518 "str", "strh", "strb", "ldrsb", "ldr", "ldrh", "ldrb", "ldrsh"
519 };
520
521 const char* ARMv7DOpcodeLoadStoreRegisterOffsetT1::format()
522 {
523 appendInstructionName(opName());
524 appendRegisterName(rt());
525 appendSeparator();
526 appendCharacter('[');
527 appendRegisterName(rn());
528 appendSeparator();
529 appendRegisterName(rm());
530 appendCharacter(']');
531
532 return m_formatBuffer;
533 }
534
535 const char* ARMv7DOpcodeLoadStoreRegisterSPRelative::format()
536 {
537 appendInstructionName(opName());
538 appendRegisterName(rt());
539 appendSeparator();
540 appendCharacter('[');
541 appendRegisterName(RegSP);
542 if (immediate8()) {
543 appendSeparator();
544 appendUnsignedImmediate(immediate8() << 2);
545 }
546 appendCharacter(']');
547
548 return m_formatBuffer;
549 }
550
551 const char* ARMv7DOpcodeLogicalImmediateT1::format()
552 {
553 if (!op() && !immediate5()) {
554 // mov T2
555 appendInstructionName("movs");
556 appendRegisterName(rd());
557 appendSeparator();
558 appendRegisterName(rm());
559
560 return m_formatBuffer;
561 }
562
563 appendInstructionName(opName(), !inITBlock());
564 appendRegisterName(rd());
565 appendSeparator();
566 appendRegisterName(rm());
567 appendSeparator();
568 appendUnsignedImmediate((op() && !immediate5()) ? 32 : immediate5());
569
570 return m_formatBuffer;
571 }
572
573 const char* ARMv7DOpcodeMiscAddSubSP::format()
574 {
575 appendInstructionName(opName());
576 appendRegisterName(RegSP);
577 appendSeparator();
578 appendRegisterName(RegSP);
579 appendSeparator();
580 appendUnsignedImmediate(immediate7());
581
582 return m_formatBuffer;
583 }
584
585 const char* ARMv7DOpcodeMiscBreakpointT1::format()
586 {
587 appendInstructionNameNoITBlock("bkpt");
588 appendUnsignedImmediate(immediate8());
589
590 return m_formatBuffer;
591 }
592
593 const char* const ARMv7DOpcodeMiscByteHalfwordOps::s_opNames[8] = {
594 "sxth", "sxb", "uxth", "uxtb", "rev", "rev16", "revsh"
595 };
596
597 const char* ARMv7DOpcodeMiscByteHalfwordOps::format()
598 {
599 const char* instructionName = opName();
600
601 if (!instructionName)
602 return defaultFormat();
603
604 appendInstructionName(instructionName);
605 appendRegisterName(rd());
606 appendSeparator();
607 appendRegisterName(rm());
608
609 return m_formatBuffer;
610 }
611
612 const char* ARMv7DOpcodeMiscCompareAndBranch::format()
613 {
614 appendInstructionName(opName());
615 appendPCRelativeOffset(immediate6() + 2);
616
617 return m_formatBuffer;
618 }
619
620 const char* const ARMv7DOpcodeMiscHint16::s_opNames[16] = {
621 "nop", "yield", "wfe", "wfi", "sev"
622 };
623
624 const char* ARMv7DOpcodeMiscHint16::format()
625 {
626 if (opA() > 4)
627 return defaultFormat();
628
629 appendInstructionName(opName());
630
631 return m_formatBuffer;
632 }
633
634 const char* ARMv7DOpcodeMiscIfThenT1::format()
635 {
636 char opName[6];
637 opName[0] = 'i';
638 opName[1] = 't';
639
640 unsigned condition = firstCondition();
641 unsigned maskBits = mask();
642 unsigned blockLength = 0;
643
644 for (unsigned i = 0; i < 4; ++i) {
645 if (maskBits & (1 << i)) {
646 blockLength = 4 - i;
647 break;
648 }
649 }
650
651 startITBlock(blockLength, condition);
652
653 for (unsigned i = 1; i < blockLength; ++i) {
654 unsigned currMaskBit = (maskBits >> (4-i)) & 0x1;
655 opName[i + 1] = (currMaskBit ^ (condition & 1)) ? 'e' : 't';
656 saveITConditionAt(i, (condition & ~1) | currMaskBit);
657 }
658 opName[blockLength + 1] = '\0';
659
660 appendInstructionNameNoITBlock(opName);
661 appendString(conditionName(condition));
662
663 return m_formatBuffer;
664 }
665
666 const char* ARMv7DOpcodeMiscPushPop::format()
667 {
668 appendInstructionName(opName());
669 appendRegisterList(registerMask());
670
671 return m_formatBuffer;
672 }
673
674 const char* ARMv7DOpcodeMoveImmediateT1::format()
675 {
676 appendInstructionName("mov", !inITBlock());
677 appendRegisterName(rd());
678 appendSeparator();
679 appendUnsignedImmediate(immediate8());
680
681 return m_formatBuffer;
682 }
683
684 const char* ARMv7DOpcodeMoveRegisterT1::format()
685 {
686 appendInstructionName("mov");
687 appendRegisterName(rd());
688 appendSeparator();
689 appendRegisterName(rm());
690
691 return m_formatBuffer;
692 }
693
694 // 32 bit Intructions
695
696 void ARMv7D32BitOpcode::init()
697 {
698 OpcodeGroup* lastGroups[OpcodeGroup::opcodeTableSize];
699
700 for (unsigned i = 0; i < OpcodeGroup::opcodeTableSize; i++) {
701 opcodeTable[i] = 0;
702 lastGroups[i] = 0;
703 }
704
705 for (unsigned i = 0; i < sizeof(opcode32BitGroupList) / sizeof(Opcode32GroupInitializer); i++) {
706 OpcodeGroup* newOpcodeGroup = new OpcodeGroup(opcode32BitGroupList[i].m_mask, opcode32BitGroupList[i].m_pattern, opcode32BitGroupList[i].m_format);
707 uint16_t opcodeGroupNumber = opcode32BitGroupList[i].m_opcodeGroupNumber;
708
709 if (!opcodeTable[opcodeGroupNumber])
710 opcodeTable[opcodeGroupNumber] = newOpcodeGroup;
711 else
712 lastGroups[opcodeGroupNumber]->setNext(newOpcodeGroup);
713 lastGroups[opcodeGroupNumber] = newOpcodeGroup;
714 }
715 }
716
717 const char* ARMv7D32BitOpcode::doDisassemble()
718 {
719 OpcodeGroup* opGroup = opcodeTable[opcodeGroupNumber(m_opcode)];
720
721 while (opGroup) {
722 if (opGroup->matches(m_opcode))
723 return opGroup->format(this);
724 opGroup = opGroup->next();
725 }
726
727 return defaultFormat();
728 }
729
730 const char* ARMv7D32BitOpcode::defaultFormat()
731 {
732 bufferPrintf(" .long %08x", m_opcode);
733 return m_formatBuffer;
734 }
735
736 const char* ARMv7DOpcodeConditionalBranchT3::format()
737 {
738 if (condition() < 0xe)
739 bufferPrintf(" b%-6.6s", conditionName(condition()));
740 else
741 appendInstructionName("b");
742 appendPCRelativeOffset(offset() + 2);
743
744 return m_formatBuffer;
745 }
746
747 const char* ARMv7DOpcodeBranchOrBranchLink::format()
748 {
749 appendInstructionName(isBL() ? "bl" : "b");
750 appendPCRelativeOffset(offset() + 2);
751
752 return m_formatBuffer;
753 }
754
755 const char* const ARMv7DOpcodeDataProcessingLogicalAndRithmetic::s_opNames[16] = {
756 "and", "bic", "orr", "orn", "eor", 0, "pkh", 0, "add", 0, "adc", "sbc", 0, "sub", "rsb", 0
757 };
758
759 void ARMv7DOpcodeDataProcessingModifiedImmediate::appendModifiedImmediate(unsigned immediate12)
760 {
761 if (!(immediate12 & 0xc00)) {
762 unsigned immediate = 0;
763 unsigned lower8Bits = immediate12 & 0xff;
764
765 switch ((immediate12 >> 8) & 3) {
766 case 0:
767 immediate = lower8Bits;
768 break;
769 case 1:
770 immediate = (lower8Bits << 16) | lower8Bits;
771 break;
772 case 2:
773 immediate = (lower8Bits << 24) | (lower8Bits << 8);
774 break;
775 case 3:
776 immediate = (lower8Bits << 24) | (lower8Bits << 16) | (lower8Bits << 8) | lower8Bits;
777 break;
778 }
779 appendUnsignedImmediate(immediate);
780 return;
781 }
782
783 unsigned immediate8 = 0x80 | (immediate12 & 0x7f);
784 unsigned shiftAmount = 32 - ((immediate12 >> 7) & 0x1f);
785
786 appendUnsignedImmediate(immediate8 << shiftAmount);
787 }
788
789 const char* ARMv7DOpcodeDataProcessingModifiedImmediate::format()
790 {
791 if ((op() == 0x5) || (op() == 0x6) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
792 return defaultFormat();
793
794 const char* instructionName = opName();
795
796 if (rn() == 15) {
797 if (op() == 2) {
798 // MOV T2
799 instructionName = sBit() ? "movs" : "mov";
800 appendInstructionName(instructionName);
801 appendRegisterName(rd());
802 appendSeparator();
803 appendModifiedImmediate(immediate12());
804
805 return m_formatBuffer;
806 }
807
808 if (op() == 3) {
809 // MVN T1
810 instructionName = sBit() ? "mvns" : "mvn";
811 appendInstructionName(instructionName);
812 appendRegisterName(rd());
813 appendSeparator();
814 appendModifiedImmediate(immediate12());
815
816 return m_formatBuffer;
817 }
818 }
819
820 if (rd() == 15) {
821 if (sBit()) {
822 bool testOrCmpInstruction = false;
823
824 switch (op()) {
825 case 0x0:
826 instructionName = "tst";
827 testOrCmpInstruction = true;
828 break;
829 case 0x4:
830 instructionName = "teq";
831 testOrCmpInstruction = true;
832 break;
833 case 0x8:
834 instructionName = "cmn";
835 testOrCmpInstruction = true;
836 break;
837 case 0xd:
838 instructionName = "cmp";
839 testOrCmpInstruction = true;
840 break;
841 }
842
843 if (testOrCmpInstruction) {
844 appendInstructionName(instructionName);
845 appendRegisterName(rn());
846 appendSeparator();
847 appendModifiedImmediate(immediate12());
848
849 return m_formatBuffer;
850 }
851 }
852 }
853
854 appendInstructionName(instructionName);
855 appendRegisterName(rd());
856 appendSeparator();
857 appendRegisterName(rn());
858 appendSeparator();
859 appendModifiedImmediate(immediate12());
860
861 return m_formatBuffer;
862 }
863
864 void ARMv7DOpcodeDataProcessingShiftedReg::appendImmShift(unsigned type, unsigned immediate)
865 {
866 if (type || immediate) {
867 appendSeparator();
868
869 if (!immediate) {
870 switch (type) {
871 case 1:
872 case 2:
873 immediate = 32;
874 break;
875 case 3:
876 appendString("rrx");
877 return;
878 }
879 }
880
881 appendShiftType(type);
882 appendUnsignedImmediate(immediate);
883 }
884 }
885
886 const char* ARMv7DOpcodeDataProcessingShiftedReg::format()
887 {
888 if ((op() == 0x5) || (op() == 0x7) || (op() == 0x9) || (op() == 0xc) || (op() == 0xf))
889 return defaultFormat();
890
891 if (op() == 6) {
892 // pkhbt or pkhtb
893 if (sBit() || tBit())
894 return defaultFormat();
895
896 if (tbBit())
897 appendInstructionName("pkhtb");
898 else
899 appendInstructionName("pkhbt");
900 appendRegisterName(rd());
901 appendSeparator();
902 appendRegisterName(rn());
903 appendSeparator();
904 appendRegisterName(rm());
905 appendImmShift(tbBit() << 1, immediate5());
906
907 return m_formatBuffer;
908 }
909
910 const char* instructionName = opName();
911
912 if (rn() == 15) {
913 if (op() == 2) {
914 if (!type() && !immediate5()) {
915 // MOV T3
916 instructionName = sBit() ? "movs" : "mov";
917 appendInstructionName(instructionName);
918 appendRegisterName(rd());
919 appendSeparator();
920 appendRegisterName(rm());
921
922 return m_formatBuffer;
923 }
924
925 if (type() == 3 && !immediate5()) {
926 // RRX T1
927 instructionName = sBit() ? "rrx" : "rrx";
928 appendInstructionName(instructionName);
929 appendRegisterName(rd());
930 appendSeparator();
931 appendRegisterName(rm());
932
933 return m_formatBuffer;
934 }
935
936 // Logical
937 if (sBit())
938 bufferPrintf("%ss ", shiftName(type()));
939 else
940 appendInstructionName(shiftName(type()));
941 appendRegisterName(rd());
942 appendSeparator();
943 appendRegisterName(rm());
944 appendSeparator();
945 appendUnsignedImmediate(immediate5());
946
947 return m_formatBuffer;
948 }
949
950 if (op() == 3) {
951 // MVN T2
952 instructionName = sBit() ? "mvns" : "mvn";
953 appendInstructionName(instructionName);
954 appendRegisterName(rd());
955 appendSeparator();
956 appendRegisterName(rm());
957 appendImmShift(type(), immediate5());
958
959 return m_formatBuffer;
960 }
961 }
962
963 if (rd() == 15) {
964 if (sBit()) {
965 bool testOrCmpInstruction = false;
966
967 switch (op()) {
968 case 0x0:
969 instructionName = "tst";
970 testOrCmpInstruction = true;
971 break;
972 case 0x4:
973 instructionName = "teq";
974 testOrCmpInstruction = true;
975 break;
976 case 0x8:
977 instructionName = "cmn";
978 testOrCmpInstruction = true;
979 break;
980 case 0xd:
981 instructionName = "cmp";
982 testOrCmpInstruction = true;
983 break;
984 }
985
986 if (testOrCmpInstruction) {
987 appendInstructionName(instructionName);
988 appendRegisterName(rn());
989 appendSeparator();
990 appendRegisterName(rm());
991 appendImmShift(type(), immediate5());
992
993 return m_formatBuffer;
994 }
995 }
996 }
997
998 appendInstructionName(instructionName);
999 appendRegisterName(rd());
1000 appendSeparator();
1001 appendRegisterName(rn());
1002 appendSeparator();
1003 appendRegisterName(rm());
1004 appendImmShift(type(), immediate5());
1005
1006 return m_formatBuffer;
1007 }
1008
1009 const char* ARMv7DOpcodeFPTransfer::format()
1010 {
1011 appendInstructionName("vmov");
1012
1013 if (opL()) {
1014 appendFPRegister();
1015 appendSeparator();
1016 }
1017
1018 appendRegisterName(rt());
1019
1020 if (!opL()) {
1021 appendSeparator();
1022 appendFPRegister();
1023 }
1024
1025 return m_formatBuffer;
1026 }
1027
1028 void ARMv7DOpcodeFPTransfer::appendFPRegister()
1029 {
1030 if (opC()) {
1031 appendFPRegisterName('d', vd());
1032 bufferPrintf("[%u]", opH());
1033 } else
1034 appendFPRegisterName('s', vn());
1035 }
1036
1037 const char* ARMv7DOpcodeDataProcessingRegShift::format()
1038 {
1039 appendInstructionName(opName());
1040 appendRegisterName(rd());
1041 appendSeparator();
1042 appendRegisterName(rn());
1043 appendSeparator();
1044 appendRegisterName(rm());
1045
1046 return m_formatBuffer;
1047 }
1048
1049 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendNames[8] = {
1050 "sxth", "uxth", "sxtb16", "uxtb16", "sxtb", "uxtb"
1051 };
1052
1053 const char* const ARMv7DOpcodeDataProcessingRegExtend::s_opExtendAndAddNames[8] = {
1054 "sxtah", "uxtah", "sxtab16", "uxtab16", "sxtab", "uxtab"
1055 };
1056
1057 const char* ARMv7DOpcodeDataProcessingRegExtend::format()
1058 {
1059 const char* instructionName;
1060
1061 if (rn() == 0xf)
1062 instructionName = opExtendName();
1063 else
1064 instructionName = opExtendAndAddName();
1065
1066 if (!instructionName)
1067 return defaultFormat();
1068
1069 appendInstructionName(instructionName);
1070 appendRegisterName(rd());
1071 appendSeparator();
1072 appendRegisterName(rn());
1073 appendSeparator();
1074 appendRegisterName(rm());
1075
1076 if (rotate()) {
1077 appendSeparator();
1078 appendString("ror ");
1079 appendUnsignedImmediate(rotate() * 8);
1080 }
1081
1082 return m_formatBuffer;
1083 }
1084
1085 const char* const ARMv7DOpcodeDataProcessingRegParallel::s_opNames[16] = {
1086 "sadd8", "sadd16", "sasx", 0, "ssub8", "ssub16", "ssax", 0,
1087 "qadd8", "qadd16", "qasx", 0, "qsub8", "qsub16", "qsax", 0
1088 };
1089
1090 const char* ARMv7DOpcodeDataProcessingRegParallel::format()
1091 {
1092 const char* instructionName;
1093
1094 instructionName = opName();
1095
1096 if (!instructionName)
1097 return defaultFormat();
1098
1099 appendInstructionName(instructionName);
1100 appendRegisterName(rd());
1101 appendSeparator();
1102 appendRegisterName(rn());
1103 appendSeparator();
1104 appendRegisterName(rm());
1105
1106 return m_formatBuffer;
1107 }
1108
1109 const char* const ARMv7DOpcodeDataProcessingRegMisc::s_opNames[16] = {
1110 "qadd", "qdadd", "qsub", "qdsub", "rev", "rev16", "rbit", "revsh",
1111 "sel", 0, 0, 0, "clz"
1112 };
1113
1114 const char* ARMv7DOpcodeDataProcessingRegMisc::format()
1115 {
1116 const char* instructionName;
1117
1118 instructionName = opName();
1119
1120 if (!instructionName)
1121 return defaultFormat();
1122
1123 if ((op1() & 0x1) && (rn() != rm()))
1124 return defaultFormat();
1125
1126 appendInstructionName(instructionName);
1127 appendRegisterName(rd());
1128 appendSeparator();
1129
1130 if (op1() == 0x2) { // sel
1131 appendRegisterName(rn());
1132 appendSeparator();
1133 appendRegisterName(rm());
1134
1135 return m_formatBuffer;
1136 }
1137
1138 appendRegisterName(rm());
1139
1140 if (!(op1() & 0x1)) {
1141 appendSeparator();
1142 appendRegisterName(rn());
1143 }
1144
1145 return m_formatBuffer;
1146 }
1147
1148 const char* const ARMv7DOpcodeHint32::s_opNames[8] = {
1149 "nop", "yield", "wfe", "wfi", "sev"
1150 };
1151
1152 const char* ARMv7DOpcodeHint32::format()
1153 {
1154 if (isDebugHint()) {
1155 appendInstructionName("debug");
1156 appendUnsignedImmediate(debugOption());
1157
1158 return m_formatBuffer;
1159 }
1160
1161 if (op() > 0x4)
1162 return defaultFormat();
1163
1164 appendInstructionName(opName());
1165
1166 return m_formatBuffer;
1167 }
1168
1169 const char* const ARMv7DOpcodeDataLoad::s_opNames[8] = {
1170 "ldrb", "ldrh", "ldr", 0, "ldrsb", "ldrsh"
1171 };
1172
1173 const char* ARMv7DOpcodeLoadRegister::format()
1174 {
1175 appendInstructionName(opName());
1176 appendRegisterName(rt());
1177 appendSeparator();
1178 appendCharacter('[');
1179 appendRegisterName(rn());
1180 appendSeparator();
1181 appendRegisterName(rm());
1182 if (immediate2()) {
1183 appendSeparator();
1184 appendUnsignedImmediate(immediate2());
1185 }
1186 appendCharacter(']');
1187
1188 return m_formatBuffer;
1189 }
1190
1191 const char* ARMv7DOpcodeLoadSignedImmediate::format()
1192 {
1193 appendInstructionName(opName());
1194 appendRegisterName(rt());
1195 appendSeparator();
1196 appendCharacter('[');
1197 appendRegisterName(rn());
1198 if (pBit()) {
1199 if (wBit() || immediate8()) {
1200 appendSeparator();
1201 if (uBit())
1202 appendUnsignedImmediate(immediate8());
1203 else
1204 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1205 }
1206 appendCharacter(']');
1207 if (wBit())
1208 appendCharacter('!');
1209 } else {
1210 appendCharacter(']');
1211 appendSeparator();
1212 if (uBit())
1213 appendUnsignedImmediate(immediate8());
1214 else
1215 appendSignedImmediate(0 - static_cast<int>(immediate8()));
1216 }
1217
1218 return m_formatBuffer;
1219 }
1220
1221 const char* ARMv7DOpcodeLoadUnsignedImmediate::format()
1222 {
1223 appendInstructionName(opName());
1224 appendRegisterName(rt());
1225 appendSeparator();
1226 appendCharacter('[');
1227 appendRegisterName(rn());
1228 if (immediate12()) {
1229 appendSeparator();
1230 appendUnsignedImmediate(immediate12());
1231 }
1232 appendCharacter(']');
1233
1234 return m_formatBuffer;
1235 }
1236
1237 const char* const ARMv7DOpcodeLongMultipleDivide::s_opNames[8] = {
1238 "smull", "sdiv", "umull", "udiv", "smlal", "smlsld", "umlal", 0
1239 };
1240
1241 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlalOpNames[4] = {
1242 "smlalbb", "smlalbt", "smlaltb", "smlaltt"
1243 };
1244
1245 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlaldOpNames[2] = {
1246 "smlald", "smlaldx"
1247 };
1248
1249 const char* const ARMv7DOpcodeLongMultipleDivide::s_smlsldOpNames[2] = {
1250 "smlsld", "smlsldx"
1251 };
1252
1253 const char* ARMv7DOpcodeLongMultipleDivide::format()
1254 {
1255 const char* instructionName = opName();
1256
1257 switch (op1()) {
1258 case 0x0:
1259 case 0x2:
1260 if (op2())
1261 return defaultFormat();
1262 break;
1263 case 0x1:
1264 case 0x3:
1265 if (op2() != 0xf)
1266 return defaultFormat();
1267 break;
1268 case 0x4:
1269 if ((op2() & 0xc) == 0x8)
1270 instructionName = smlalOpName();
1271 else if ((op2() & 0xe) == 0xc)
1272 instructionName = smlaldOpName();
1273 else if (op2())
1274 return defaultFormat();
1275 break;
1276 case 0x5:
1277 if ((op2() & 0xe) == 0xc)
1278 instructionName = smlaldOpName();
1279 else
1280 return defaultFormat();
1281 break;
1282 case 0x6:
1283 if (op2() == 0x5)
1284 instructionName = "umaal";
1285 else if (op2())
1286 return defaultFormat();
1287 break;
1288 case 0x7:
1289 return defaultFormat();
1290 break;
1291 }
1292
1293 appendInstructionName(instructionName);
1294 if ((op1() & 0x5) == 0x1) { // sdiv and udiv
1295 if (rt() != 0xf)
1296 return defaultFormat();
1297 } else {
1298 appendRegisterName(rdLo());
1299 appendSeparator();
1300 }
1301 appendRegisterName(rdHi());
1302 appendSeparator();
1303 appendRegisterName(rn());
1304 appendSeparator();
1305 appendRegisterName(rm());
1306
1307 return m_formatBuffer;
1308 }
1309
1310 const char* const ARMv7DOpcodeUnmodifiedImmediate::s_opNames[16] = {
1311 "addw", 0, "movw", 0, 0, "subw", "movt", 0,
1312 "ssat", "ssat16", "sbfx", "bfi", "usat" , "usat16", "ubfx", 0
1313 };
1314
1315 const char* ARMv7DOpcodeUnmodifiedImmediate::format()
1316 {
1317 const char* instructionName = opName();
1318
1319 switch (op() >> 1) {
1320 case 0x0:
1321 case 0x5:
1322 if (rn() == 0xf)
1323 instructionName = "adr";
1324 break;
1325 case 0x9:
1326 if (immediate5())
1327 instructionName = "ssat";
1328 break;
1329 case 0xb:
1330 if (rn() == 0xf)
1331 instructionName = "bfc";
1332 break;
1333 case 0xd:
1334 if (immediate5())
1335 instructionName = "usat";
1336 break;
1337 }
1338
1339 if (!instructionName)
1340 return defaultFormat();
1341
1342 appendInstructionName(instructionName);
1343 appendRegisterName(rd());
1344 appendSeparator();
1345
1346 if ((op() & 0x17) == 0x4) { // movw or movt
1347 appendUnsignedImmediate(immediate16());
1348
1349 return m_formatBuffer;
1350 }
1351
1352 if (!op() || (op() == 0xa)) { // addw, subw and adr
1353 if (rn() == 0xf) {
1354 int32_t offset;
1355
1356 if ((op() == 0xa) && (rn() == 0xf))
1357 offset = 0 - static_cast<int32_t>(immediate12());
1358 else
1359 offset = static_cast<int32_t>(immediate12());
1360
1361 appendPCRelativeOffset(offset);
1362
1363 return m_formatBuffer;
1364 }
1365
1366 appendRegisterName(rn());
1367 appendSeparator();
1368 appendUnsignedImmediate(immediate12());
1369
1370 return m_formatBuffer;
1371 }
1372
1373 if (((op() & 0x15) == 0x10) || (((op() & 0x17) == 0x12) && immediate5())) { // ssat, usat, ssat16 & usat16
1374 appendSeparator();
1375 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1376 appendSeparator();
1377 appendRegisterName(rn());
1378 if (shBit() || immediate5()) {
1379 appendSeparator();
1380 appendShiftType(shBit() << 1);
1381 appendUnsignedImmediate(immediate5());
1382 }
1383
1384 return m_formatBuffer;
1385 }
1386
1387 if (op() == 0x16) { // bfi or bfc
1388 int width = static_cast<int>(bitNumOrSatImmediate()) - static_cast<int>(immediate5()) + 1;
1389
1390 if (width < 0)
1391 return defaultFormat();
1392
1393 if (rn() != 0xf) {
1394 appendSeparator();
1395 appendRegisterName(rn());
1396 }
1397 appendSeparator();
1398 appendUnsignedImmediate(immediate5());
1399 appendSeparator();
1400 appendSignedImmediate(width);
1401
1402 return m_formatBuffer;
1403 }
1404
1405 // Must be sbfx or ubfx
1406 appendSeparator();
1407 appendRegisterName(rn());
1408 appendSeparator();
1409 appendUnsignedImmediate(immediate5());
1410 appendSeparator();
1411 appendUnsignedImmediate(bitNumOrSatImmediate() + 1);
1412
1413 return m_formatBuffer;
1414 }
1415
1416 const char* const ARMv7DOpcodeDataStoreSingle::s_opNames[4] = {
1417 "strb", "strh", "str", 0
1418 };
1419
1420 const char* ARMv7DOpcodeDataPushPopSingle::format()
1421 {
1422 appendInstructionName(opName());
1423 appendRegisterName(rt());
1424
1425 return m_formatBuffer;
1426 }
1427
1428 const char* ARMv7DOpcodeStoreSingleImmediate12::format()
1429 {
1430 appendInstructionName(opName());
1431 appendRegisterName(rt());
1432 appendSeparator();
1433 appendCharacter('[');
1434 appendRegisterName(rn());
1435 if (immediate12()) {
1436 appendSeparator();
1437 appendUnsignedImmediate(immediate12());
1438 }
1439 appendCharacter(']');
1440
1441 return m_formatBuffer;
1442 }
1443
1444 const char* ARMv7DOpcodeStoreSingleImmediate8::format()
1445 {
1446 if (pBit() && uBit() && !wBit()) // Really undecoded strt
1447 return defaultFormat();
1448
1449 if ((rn() == 0xf) || (!pBit() && !wBit()))
1450 return defaultFormat();
1451
1452 appendInstructionName(opName());
1453 appendRegisterName(rt());
1454 appendSeparator();
1455 appendCharacter('[');
1456 appendRegisterName(rn());
1457
1458 if (!pBit()) {
1459 appendCharacter(']');
1460 appendSeparator();
1461 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1462
1463 return m_formatBuffer;
1464 }
1465
1466 if (immediate8()) {
1467 appendSeparator();
1468 appendSignedImmediate(uBit() ? static_cast<int32_t>(immediate8()) : (0 - static_cast<int32_t>(immediate8())));
1469 }
1470 appendCharacter(']');
1471
1472 if (wBit())
1473 appendCharacter('!');
1474
1475 return m_formatBuffer;
1476 }
1477
1478 const char* ARMv7DOpcodeStoreSingleRegister::format()
1479 {
1480 appendInstructionName(opName());
1481 appendRegisterName(rt());
1482 appendSeparator();
1483 appendCharacter('[');
1484 appendRegisterName(rn());
1485 appendSeparator();
1486 appendRegisterName(rm());
1487 if (immediate2()) {
1488 appendSeparator();
1489 appendString("lsl ");
1490 appendUnsignedImmediate(immediate2());
1491 }
1492 appendCharacter(']');
1493
1494 return m_formatBuffer;
1495 }
1496
1497 const char* ARMv7DOpcodeVMOVDoublePrecision::format()
1498 {
1499 appendInstructionName("vmov");
1500 if (op()) {
1501 appendRegisterName(rt());
1502 appendSeparator();
1503 appendRegisterName(rt2());
1504 appendSeparator();
1505 }
1506
1507 appendFPRegisterName('d', vm());
1508
1509 if (!op()) {
1510 appendSeparator();
1511 appendRegisterName(rt());
1512 appendSeparator();
1513 appendRegisterName(rt2());
1514 }
1515
1516 return m_formatBuffer;
1517 }
1518
1519 const char* ARMv7DOpcodeVMOVSinglePrecision::format()
1520 {
1521 appendInstructionName("vmov");
1522 if (op()) {
1523 appendRegisterName(rt());
1524 appendSeparator();
1525 appendRegisterName(rt2());
1526 appendSeparator();
1527 }
1528
1529 appendFPRegisterName('s', vm());
1530 appendSeparator();
1531 appendFPRegisterName('s', (vm() + 1) % 32);
1532
1533 if (!op()) {
1534 appendSeparator();
1535 appendRegisterName(rt());
1536 appendSeparator();
1537 appendRegisterName(rt2());
1538 }
1539
1540 return m_formatBuffer;
1541 }
1542
1543 const char* ARMv7DOpcodeVMSR::format()
1544 {
1545 appendInstructionName("vmrs");
1546 if (opL()) {
1547 if (rt() == 0xf)
1548 appendString("apsr_nzcv");
1549 else
1550 appendRegisterName(rt());
1551 appendSeparator();
1552 }
1553
1554 appendString("fpscr");
1555
1556 if (!opL()) {
1557 appendSeparator();
1558 appendRegisterName(rt());
1559 }
1560
1561 return m_formatBuffer;
1562 }
1563
1564 } } // namespace JSC::ARMv7Disassembler
1565
1566 #endif // #if USE(ARMV7_DISASSEMBLER)