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