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