1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // A Disassembler object is used to disassemble a block of code instruction by
6 // instruction. The default implementation of the NameConverter object can be
7 // overriden to modify register names or to do symbol lookup on addresses.
9 // The example below will disassemble a block of code and print it to stdout.
11 // NameConverter converter;
12 // Disassembler d(converter);
13 // for (byte* pc = begin; pc < end;) {
14 // v8::internal::EmbeddedVector<char, 256> buffer;
15 // byte* prev_pc = pc;
16 // pc += d.InstructionDecode(buffer, pc);
17 // printf("%p %08x %s\n",
18 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
21 // The Disassembler class also has a convenience method to disassemble a block
22 // of code into a FILE*, meaning that the above functionality could also be
23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
33 #if V8_TARGET_ARCH_ARM
35 #include "src/arm/constants-arm.h"
36 #include "src/base/bits.h"
37 #include "src/base/platform/platform.h"
38 #include "src/disasm.h"
39 #include "src/macro-assembler.h"
46 //------------------------------------------------------------------------------
48 // Decoder decodes and disassembles instructions into an output buffer.
49 // It uses the converter to convert register names and call destinations into
50 // more informative description.
53 Decoder(const disasm::NameConverter& converter,
54 Vector<char> out_buffer)
55 : converter_(converter),
56 out_buffer_(out_buffer),
58 out_buffer_[out_buffer_pos_] = '\0';
63 // Writes one disassembled instruction into 'buffer' (0-terminated).
64 // Returns the length of the disassembled machine instruction in bytes.
65 int InstructionDecode(byte* instruction);
67 static bool IsConstantPoolAt(byte* instr_ptr);
68 static int ConstantPoolSizeAt(byte* instr_ptr);
71 // Bottleneck functions to print into the out_buffer.
72 void PrintChar(const char ch);
73 void Print(const char* str);
75 // Printing of common values.
76 void PrintRegister(int reg);
77 void PrintSRegister(int reg);
78 void PrintDRegister(int reg);
79 int FormatVFPRegister(Instruction* instr, const char* format);
80 void PrintMovwMovt(Instruction* instr);
81 int FormatVFPinstruction(Instruction* instr, const char* format);
82 void PrintCondition(Instruction* instr);
83 void PrintShiftRm(Instruction* instr);
84 void PrintShiftImm(Instruction* instr);
85 void PrintShiftSat(Instruction* instr);
86 void PrintPU(Instruction* instr);
87 void PrintSoftwareInterrupt(SoftwareInterruptCodes svc);
89 // Handle formatting of instructions and their options.
90 int FormatRegister(Instruction* instr, const char* option);
91 void FormatNeonList(int Vd, int type);
92 void FormatNeonMemory(int Rn, int align, int Rm);
93 int FormatOption(Instruction* instr, const char* option);
94 void Format(Instruction* instr, const char* format);
95 void Unknown(Instruction* instr);
97 // Each of these functions decodes one particular instruction type, a 3-bit
98 // field in the instruction encoding.
99 // Types 0 and 1 are combined as they are largely the same except for the way
100 // they interpret the shifter operand.
101 void DecodeType01(Instruction* instr);
102 void DecodeType2(Instruction* instr);
103 void DecodeType3(Instruction* instr);
104 void DecodeType4(Instruction* instr);
105 void DecodeType5(Instruction* instr);
106 void DecodeType6(Instruction* instr);
107 // Type 7 includes special Debugger instructions.
108 int DecodeType7(Instruction* instr);
110 void DecodeTypeVFP(Instruction* instr);
111 void DecodeType6CoprocessorIns(Instruction* instr);
113 void DecodeSpecialCondition(Instruction* instr);
115 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
116 void DecodeVCMP(Instruction* instr);
117 void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
118 void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
120 const disasm::NameConverter& converter_;
121 Vector<char> out_buffer_;
124 DISALLOW_COPY_AND_ASSIGN(Decoder);
128 // Support for assertions in the Decoder formatting functions.
129 #define STRING_STARTS_WITH(string, compare_string) \
130 (strncmp(string, compare_string, strlen(compare_string)) == 0)
133 // Append the ch to the output buffer.
134 void Decoder::PrintChar(const char ch) {
135 out_buffer_[out_buffer_pos_++] = ch;
139 // Append the str to the output buffer.
140 void Decoder::Print(const char* str) {
142 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
146 out_buffer_[out_buffer_pos_] = 0;
150 // These condition names are defined in a way to match the native disassembler
151 // formatting. See for example the command "objdump -d <binary file>".
152 static const char* const cond_names[kNumberOfConditions] = {
153 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
154 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
158 // Print the condition guarding the instruction.
159 void Decoder::PrintCondition(Instruction* instr) {
160 Print(cond_names[instr->ConditionValue()]);
164 // Print the register name according to the active name converter.
165 void Decoder::PrintRegister(int reg) {
166 Print(converter_.NameOfCPURegister(reg));
170 // Print the VFP S register name according to the active name converter.
171 void Decoder::PrintSRegister(int reg) {
172 Print(VFPRegisters::Name(reg, false));
176 // Print the VFP D register name according to the active name converter.
177 void Decoder::PrintDRegister(int reg) {
178 Print(VFPRegisters::Name(reg, true));
182 // These shift names are defined in a way to match the native disassembler
183 // formatting. See for example the command "objdump -d <binary file>".
184 static const char* const shift_names[kNumberOfShifts] = {
185 "lsl", "lsr", "asr", "ror"
189 // Print the register shift operands for the instruction. Generally used for
190 // data processing instructions.
191 void Decoder::PrintShiftRm(Instruction* instr) {
192 ShiftOp shift = instr->ShiftField();
193 int shift_index = instr->ShiftValue();
194 int shift_amount = instr->ShiftAmountValue();
195 int rm = instr->RmValue();
199 if ((instr->RegShiftValue() == 0) && (shift == LSL) && (shift_amount == 0)) {
200 // Special case for using rm only.
203 if (instr->RegShiftValue() == 0) {
205 if ((shift == ROR) && (shift_amount == 0)) {
208 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
211 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
213 shift_names[shift_index],
217 int rs = instr->RsValue();
218 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
219 ", %s ", shift_names[shift_index]);
225 // Print the immediate operand for the instruction. Generally used for data
226 // processing instructions.
227 void Decoder::PrintShiftImm(Instruction* instr) {
228 int rotate = instr->RotateValue() * 2;
229 int immed8 = instr->Immed8Value();
230 int imm = base::bits::RotateRight32(immed8, rotate);
231 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%d", imm);
235 // Print the optional shift and immediate used by saturating instructions.
236 void Decoder::PrintShiftSat(Instruction* instr) {
237 int shift = instr->Bits(11, 7);
239 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
241 shift_names[instr->Bit(6) * 2],
247 // Print PU formatting to reduce complexity of FormatOption.
248 void Decoder::PrintPU(Instruction* instr) {
249 switch (instr->PUField()) {
274 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
275 // the FormatOption method.
276 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes svc) {
278 case kCallRtRedirected:
279 Print("call rt redirected");
285 if (svc >= kStopCode) {
286 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
289 svc & kStopCodeMask);
291 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
300 // Handle all register based formatting in this function to reduce the
301 // complexity of FormatOption.
302 int Decoder::FormatRegister(Instruction* instr, const char* format) {
303 DCHECK(format[0] == 'r');
304 if (format[1] == 'n') { // 'rn: Rn register
305 int reg = instr->RnValue();
308 } else if (format[1] == 'd') { // 'rd: Rd register
309 int reg = instr->RdValue();
312 } else if (format[1] == 's') { // 'rs: Rs register
313 int reg = instr->RsValue();
316 } else if (format[1] == 'm') { // 'rm: Rm register
317 int reg = instr->RmValue();
320 } else if (format[1] == 't') { // 'rt: Rt register
321 int reg = instr->RtValue();
324 } else if (format[1] == 'l') {
325 // 'rlist: register list for load and store multiple instructions
326 DCHECK(STRING_STARTS_WITH(format, "rlist"));
327 int rlist = instr->RlistValue();
330 // Print register list in ascending order, by scanning the bit mask.
332 if ((rlist & 1) != 0) {
334 if ((rlist >> 1) != 0) {
349 // Handle all VFP register based formatting in this function to reduce the
350 // complexity of FormatOption.
351 int Decoder::FormatVFPRegister(Instruction* instr, const char* format) {
352 DCHECK((format[0] == 'S') || (format[0] == 'D'));
354 VFPRegPrecision precision =
355 format[0] == 'D' ? kDoublePrecision : kSinglePrecision;
359 if (format[1] == 'n') {
360 reg = instr->VFPNRegValue(precision);
361 } else if (format[1] == 'm') {
362 reg = instr->VFPMRegValue(precision);
363 } else if (format[1] == 'd') {
364 if ((instr->TypeValue() == 7) &&
365 (instr->Bit(24) == 0x0) &&
366 (instr->Bits(11, 9) == 0x5) &&
367 (instr->Bit(4) == 0x1)) {
368 // vmov.32 has Vd in a different place.
369 reg = instr->Bits(19, 16) | (instr->Bit(7) << 4);
371 reg = instr->VFPDRegValue(precision);
374 if (format[2] == '+') {
375 int immed8 = instr->Immed8Value();
376 if (format[0] == 'S') reg += immed8 - 1;
377 if (format[0] == 'D') reg += (immed8 / 2 - 1);
379 if (format[2] == '+') retval = 3;
384 if (precision == kSinglePrecision) {
394 int Decoder::FormatVFPinstruction(Instruction* instr, const char* format) {
400 void Decoder::FormatNeonList(int Vd, int type) {
402 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
404 } else if (type == nlt_2) {
405 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
406 "{d%d, d%d}", Vd, Vd + 1);
407 } else if (type == nlt_3) {
408 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
409 "{d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2);
410 } else if (type == nlt_4) {
411 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
412 "{d%d, d%d, d%d, d%d}", Vd, Vd + 1, Vd + 2, Vd + 3);
417 void Decoder::FormatNeonMemory(int Rn, int align, int Rm) {
418 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
421 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
422 ":%d", (1 << align) << 6);
426 } else if (Rm == 13) {
429 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
435 // Print the movw or movt instruction.
436 void Decoder::PrintMovwMovt(Instruction* instr) {
437 int imm = instr->ImmedMovwMovtValue();
438 int rd = instr->RdValue();
440 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, ", #%d", imm);
444 // FormatOption takes a formatting string and interprets it based on
445 // the current instructions. The format string points to the first
446 // character of the option string (the option escape has already been
447 // consumed by the caller.) FormatOption returns the number of
448 // characters that were consumed from the formatting string.
449 int Decoder::FormatOption(Instruction* instr, const char* format) {
451 case 'a': { // 'a: accumulate multiplies
452 if (instr->Bit(21) == 0) {
459 case 'b': { // 'b: byte loads or stores
465 case 'c': { // 'cond: conditional execution
466 DCHECK(STRING_STARTS_WITH(format, "cond"));
467 PrintCondition(instr);
470 case 'd': { // 'd: vmov double immediate.
471 double d = instr->DoubleImmedVmov();
472 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "#%g", d);
475 case 'f': { // 'f: bitfield instructions - v7 and above.
476 uint32_t lsbit = instr->Bits(11, 7);
477 uint32_t width = instr->Bits(20, 16) + 1;
478 if (instr->Bit(21) == 0) {
480 // Bits 20-16 represent most-significant bit. Covert to width.
484 DCHECK((width + lsbit) <= 32);
485 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
486 "#%d, #%d", lsbit, width);
489 case 'h': { // 'h: halfword operation for extra loads and stores
497 case 'i': { // 'i: immediate value from adjacent bits.
498 // Expects tokens in the form imm%02d@%02d, i.e. imm05@07, imm10@16
499 int width = (format[3] - '0') * 10 + (format[4] - '0');
500 int lsb = (format[6] - '0') * 10 + (format[7] - '0');
502 DCHECK((width >= 1) && (width <= 32));
503 DCHECK((lsb >= 0) && (lsb <= 31));
504 DCHECK((width + lsb) <= 32);
506 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
508 instr->Bits(width + lsb - 1, lsb));
511 case 'l': { // 'l: branch and link
512 if (instr->HasLink()) {
518 if (format[1] == 'w') {
519 // 'mw: movt/movw instructions.
520 PrintMovwMovt(instr);
523 if (format[1] == 'e') { // 'memop: load/store instructions.
524 DCHECK(STRING_STARTS_WITH(format, "memop"));
528 if ((instr->Bits(27, 25) == 0) && (instr->Bit(20) == 0) &&
529 (instr->Bits(7, 6) == 3) && (instr->Bit(4) == 1)) {
530 if (instr->Bit(5) == 1) {
541 // 'msg: for simulator break instructions
542 DCHECK(STRING_STARTS_WITH(format, "msg"));
544 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
545 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
546 "%s", converter_.NameInCode(str));
550 if ((format[3] == '1') && (format[4] == '2')) {
551 // 'off12: 12-bit offset for load and store instructions
552 DCHECK(STRING_STARTS_WITH(format, "off12"));
553 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
554 "%d", instr->Offset12Value());
556 } else if (format[3] == '0') {
557 // 'off0to3and8to19 16-bit immediate encoded in bits 19-8 and 3-0.
558 DCHECK(STRING_STARTS_WITH(format, "off0to3and8to19"));
559 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
561 (instr->Bits(19, 8) << 4) +
565 // 'off8: 8-bit offset for extra load and store instructions
566 DCHECK(STRING_STARTS_WITH(format, "off8"));
567 int offs8 = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
568 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", offs8);
571 case 'p': { // 'pu: P and U bits for load and store instructions
572 DCHECK(STRING_STARTS_WITH(format, "pu"));
577 return FormatRegister(instr, format);
580 if (format[1] == 'h') { // 'shift_op or 'shift_rm or 'shift_sat.
581 if (format[6] == 'o') { // 'shift_op
582 DCHECK(STRING_STARTS_WITH(format, "shift_op"));
583 if (instr->TypeValue() == 0) {
586 DCHECK(instr->TypeValue() == 1);
587 PrintShiftImm(instr);
590 } else if (format[6] == 's') { // 'shift_sat.
591 DCHECK(STRING_STARTS_WITH(format, "shift_sat"));
592 PrintShiftSat(instr);
594 } else { // 'shift_rm
595 DCHECK(STRING_STARTS_WITH(format, "shift_rm"));
599 } else if (format[1] == 'v') { // 'svc
600 DCHECK(STRING_STARTS_WITH(format, "svc"));
601 PrintSoftwareInterrupt(instr->SvcValue());
603 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
604 DCHECK(STRING_STARTS_WITH(format, "sign"));
605 if (instr->HasSign()) {
610 // 's: S field of data processing instructions
616 case 't': { // 'target: target of branch instructions
617 DCHECK(STRING_STARTS_WITH(format, "target"));
618 int off = (instr->SImmed24Value() << 2) + 8;
619 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
622 converter_.NameOfAddress(
623 reinterpret_cast<byte*>(instr) + off));
626 case 'u': { // 'u: signed or unsigned multiplies
627 // The manual gets the meaning of bit 22 backwards in the multiply
628 // instruction overview on page A3.16.2. The instructions that
629 // exist in u and s variants are the following:
634 // For these 0 means u and 1 means s. As can be seen on their individual
635 // pages. The other 18 mul instructions have the bit set or unset in
636 // arbitrary ways that are unrelated to the signedness of the instruction.
637 // None of these 18 instructions exist in both a 'u' and an 's' variant.
639 if (instr->Bit(22) == 0) {
647 return FormatVFPinstruction(instr, format);
651 return FormatVFPRegister(instr, format);
653 case 'w': { // 'w: W field of load and store instructions
669 // Format takes a formatting string for a whole instruction and prints it into
670 // the output buffer. All escaped options are handed to FormatOption to be
672 void Decoder::Format(Instruction* instr, const char* format) {
673 char cur = *format++;
674 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
675 if (cur == '\'') { // Single quote is used as the formatting escape.
676 format += FormatOption(instr, format);
678 out_buffer_[out_buffer_pos_++] = cur;
682 out_buffer_[out_buffer_pos_] = '\0';
686 // The disassembler may end up decoding data inlined in the code. We do not want
687 // it to crash if the data does not ressemble any known instruction.
688 #define VERIFY(condition) \
695 // For currently unimplemented decodings the disassembler calls Unknown(instr)
696 // which will just print "unknown" of the instruction bits.
697 void Decoder::Unknown(Instruction* instr) {
698 Format(instr, "unknown");
702 void Decoder::DecodeType01(Instruction* instr) {
703 int type = instr->TypeValue();
704 if ((type == 0) && instr->IsSpecialType0()) {
705 // multiply instruction or extra loads and stores
706 if (instr->Bits(7, 4) == 9) {
707 if (instr->Bit(24) == 0) {
708 // multiply instructions
709 if (instr->Bit(23) == 0) {
710 if (instr->Bit(21) == 0) {
711 // The MUL instruction description (A 4.1.33) refers to Rd as being
712 // the destination for the operation, but it confusingly uses the
713 // Rn field to encode it.
714 Format(instr, "mul'cond's 'rn, 'rm, 'rs");
716 if (instr->Bit(22) == 0) {
717 // The MLA instruction description (A 4.1.28) refers to the order
718 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
719 // Rn field to encode the Rd register and the Rd field to encode
721 Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
723 // The MLS instruction description (A 4.1.29) refers to the order
724 // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
725 // Rn field to encode the Rd register and the Rd field to encode
727 Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
731 // The signed/long multiply instructions use the terms RdHi and RdLo
732 // when referring to the target registers. They are mapped to the Rn
733 // and Rd fields as follows:
736 // The order of registers is: <RdLo>, <RdHi>, <Rm>, <Rs>
737 Format(instr, "'um'al'cond's 'rd, 'rn, 'rm, 'rs");
740 Unknown(instr); // not used by V8
742 } else if ((instr->Bit(20) == 0) && ((instr->Bits(7, 4) & 0xd) == 0xd)) {
744 switch (instr->PUField()) {
746 if (instr->Bit(22) == 0) {
747 Format(instr, "'memop'cond's 'rd, ['rn], -'rm");
749 Format(instr, "'memop'cond's 'rd, ['rn], #-'off8");
754 if (instr->Bit(22) == 0) {
755 Format(instr, "'memop'cond's 'rd, ['rn], +'rm");
757 Format(instr, "'memop'cond's 'rd, ['rn], #+'off8");
762 if (instr->Bit(22) == 0) {
763 Format(instr, "'memop'cond's 'rd, ['rn, -'rm]'w");
765 Format(instr, "'memop'cond's 'rd, ['rn, #-'off8]'w");
770 if (instr->Bit(22) == 0) {
771 Format(instr, "'memop'cond's 'rd, ['rn, +'rm]'w");
773 Format(instr, "'memop'cond's 'rd, ['rn, #+'off8]'w");
778 // The PU field is a 2-bit field.
784 // extra load/store instructions
785 switch (instr->PUField()) {
787 if (instr->Bit(22) == 0) {
788 Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
790 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
795 if (instr->Bit(22) == 0) {
796 Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
798 Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
803 if (instr->Bit(22) == 0) {
804 Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
806 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
811 if (instr->Bit(22) == 0) {
812 Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
814 Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
819 // The PU field is a 2-bit field.
826 } else if ((type == 0) && instr->IsMiscType0()) {
827 if (instr->Bits(22, 21) == 1) {
828 switch (instr->BitField(7, 4)) {
830 Format(instr, "bx'cond 'rm");
833 Format(instr, "blx'cond 'rm");
836 Format(instr, "bkpt 'off0to3and8to19");
839 Unknown(instr); // not used by V8
842 } else if (instr->Bits(22, 21) == 3) {
843 switch (instr->BitField(7, 4)) {
845 Format(instr, "clz'cond 'rd, 'rm");
848 Unknown(instr); // not used by V8
852 Unknown(instr); // not used by V8
854 } else if ((type == 1) && instr->IsNopType1()) {
855 Format(instr, "nop'cond");
857 switch (instr->OpcodeField()) {
859 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
863 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
867 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
871 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
875 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
879 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
883 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
887 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
892 Format(instr, "tst'cond 'rn, 'shift_op");
894 Format(instr, "movw'cond 'mw");
900 Format(instr, "teq'cond 'rn, 'shift_op");
902 // Other instructions matching this pattern are handled in the
903 // miscellaneous instructions part above.
910 Format(instr, "cmp'cond 'rn, 'shift_op");
912 Format(instr, "movt'cond 'mw");
918 Format(instr, "cmn'cond 'rn, 'shift_op");
920 // Other instructions matching this pattern are handled in the
921 // miscellaneous instructions part above.
927 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
931 Format(instr, "mov'cond's 'rd, 'shift_op");
935 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
939 Format(instr, "mvn'cond's 'rd, 'shift_op");
943 // The Opcode field is a 4-bit field.
952 void Decoder::DecodeType2(Instruction* instr) {
953 switch (instr->PUField()) {
956 Unknown(instr); // not used in V8
959 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
964 Unknown(instr); // not used in V8
967 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
971 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
975 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
979 // The PU field is a 2-bit field.
987 void Decoder::DecodeType3(Instruction* instr) {
988 switch (instr->PUField()) {
990 VERIFY(!instr->HasW());
991 Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
995 if (instr->Bit(4) == 0) {
996 Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
998 if (instr->Bit(5) == 0) {
999 switch (instr->Bits(22, 21)) {
1001 if (instr->Bit(20) == 0) {
1002 if (instr->Bit(6) == 0) {
1003 Format(instr, "pkhbt'cond 'rd, 'rn, 'rm, lsl #'imm05@07");
1005 if (instr->Bits(11, 7) == 0) {
1006 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #32");
1008 Format(instr, "pkhtb'cond 'rd, 'rn, 'rm, asr #'imm05@07");
1022 Format(instr, "usat 'rd, #'imm05@16, 'rm'shift_sat");
1026 switch (instr->Bits(22, 21)) {
1031 if (instr->Bits(9, 6) == 1) {
1032 if (instr->Bit(20) == 0) {
1033 if (instr->Bits(19, 16) == 0xF) {
1034 switch (instr->Bits(11, 10)) {
1036 Format(instr, "sxtb'cond 'rd, 'rm");
1039 Format(instr, "sxtb'cond 'rd, 'rm, ror #8");
1042 Format(instr, "sxtb'cond 'rd, 'rm, ror #16");
1045 Format(instr, "sxtb'cond 'rd, 'rm, ror #24");
1049 switch (instr->Bits(11, 10)) {
1051 Format(instr, "sxtab'cond 'rd, 'rn, 'rm");
1054 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #8");
1057 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #16");
1060 Format(instr, "sxtab'cond 'rd, 'rn, 'rm, ror #24");
1065 if (instr->Bits(19, 16) == 0xF) {
1066 switch (instr->Bits(11, 10)) {
1068 Format(instr, "sxth'cond 'rd, 'rm");
1071 Format(instr, "sxth'cond 'rd, 'rm, ror #8");
1074 Format(instr, "sxth'cond 'rd, 'rm, ror #16");
1077 Format(instr, "sxth'cond 'rd, 'rm, ror #24");
1081 switch (instr->Bits(11, 10)) {
1083 Format(instr, "sxtah'cond 'rd, 'rn, 'rm");
1086 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #8");
1089 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #16");
1092 Format(instr, "sxtah'cond 'rd, 'rn, 'rm, ror #24");
1102 if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
1103 if (instr->Bits(19, 16) == 0xF) {
1104 switch (instr->Bits(11, 10)) {
1106 Format(instr, "uxtb16'cond 'rd, 'rm");
1109 Format(instr, "uxtb16'cond 'rd, 'rm, ror #8");
1112 Format(instr, "uxtb16'cond 'rd, 'rm, ror #16");
1115 Format(instr, "uxtb16'cond 'rd, 'rm, ror #24");
1126 if ((instr->Bits(9, 6) == 1)) {
1127 if ((instr->Bit(20) == 0)) {
1128 if (instr->Bits(19, 16) == 0xF) {
1129 switch (instr->Bits(11, 10)) {
1131 Format(instr, "uxtb'cond 'rd, 'rm");
1134 Format(instr, "uxtb'cond 'rd, 'rm, ror #8");
1137 Format(instr, "uxtb'cond 'rd, 'rm, ror #16");
1140 Format(instr, "uxtb'cond 'rd, 'rm, ror #24");
1144 switch (instr->Bits(11, 10)) {
1146 Format(instr, "uxtab'cond 'rd, 'rn, 'rm");
1149 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #8");
1152 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #16");
1155 Format(instr, "uxtab'cond 'rd, 'rn, 'rm, ror #24");
1160 if (instr->Bits(19, 16) == 0xF) {
1161 switch (instr->Bits(11, 10)) {
1163 Format(instr, "uxth'cond 'rd, 'rm");
1166 Format(instr, "uxth'cond 'rd, 'rm, ror #8");
1169 Format(instr, "uxth'cond 'rd, 'rm, ror #16");
1172 Format(instr, "uxth'cond 'rd, 'rm, ror #24");
1176 switch (instr->Bits(11, 10)) {
1178 Format(instr, "uxtah'cond 'rd, 'rn, 'rm");
1181 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #8");
1184 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #16");
1187 Format(instr, "uxtah'cond 'rd, 'rn, 'rm, ror #24");
1202 if (instr->Bits(22, 20) == 0x5) {
1203 if (instr->Bits(7, 4) == 0x1) {
1204 if (instr->Bits(15, 12) == 0xF) {
1205 Format(instr, "smmul'cond 'rn, 'rm, 'rs");
1207 // SMMLA (in V8 notation matching ARM ISA format)
1208 Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
1213 if (FLAG_enable_sudiv) {
1214 if (instr->Bits(5, 4) == 0x1) {
1215 if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
1216 if (instr->Bit(21) == 0x1) {
1217 // UDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1218 Format(instr, "udiv'cond'b 'rn, 'rm, 'rs");
1220 // SDIV (in V8 notation matching ARM ISA format) rn = rm/rs
1221 Format(instr, "sdiv'cond'b 'rn, 'rm, 'rs");
1227 Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1231 if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
1232 uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
1233 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1234 uint32_t msbit = widthminus1 + lsbit;
1236 if (instr->Bit(22)) {
1237 Format(instr, "ubfx'cond 'rd, 'rm, 'f");
1239 Format(instr, "sbfx'cond 'rd, 'rm, 'f");
1244 } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
1245 uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
1246 uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
1247 if (msbit >= lsbit) {
1248 if (instr->RmValue() == 15) {
1249 Format(instr, "bfc'cond 'rd, 'f");
1251 Format(instr, "bfi'cond 'rd, 'rm, 'f");
1257 Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1262 // The PU field is a 2-bit field.
1270 void Decoder::DecodeType4(Instruction* instr) {
1271 if (instr->Bit(22) != 0) {
1272 // Privileged mode currently not supported.
1275 if (instr->HasL()) {
1276 Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1278 Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1284 void Decoder::DecodeType5(Instruction* instr) {
1285 Format(instr, "b'l'cond 'target");
1289 void Decoder::DecodeType6(Instruction* instr) {
1290 DecodeType6CoprocessorIns(instr);
1294 int Decoder::DecodeType7(Instruction* instr) {
1295 if (instr->Bit(24) == 1) {
1296 if (instr->SvcValue() >= kStopCode) {
1297 Format(instr, "stop'cond 'svc");
1298 // Also print the stop message. Its address is encoded
1299 // in the following 4 bytes.
1300 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1301 "\n %p %08x stop message: %s",
1302 reinterpret_cast<void*>(instr
1303 + Instruction::kInstrSize),
1304 *reinterpret_cast<uint32_t*>(instr
1305 + Instruction::kInstrSize),
1306 *reinterpret_cast<char**>(instr
1307 + Instruction::kInstrSize));
1308 // We have decoded 2 * Instruction::kInstrSize bytes.
1309 return 2 * Instruction::kInstrSize;
1311 Format(instr, "svc'cond 'svc");
1314 DecodeTypeVFP(instr);
1316 return Instruction::kInstrSize;
1320 // void Decoder::DecodeTypeVFP(Instruction* instr)
1325 // vcvt.f64.s32 Dd, Dd, #<fbits>
1328 // Dd = vadd(Dn, Dm)
1329 // Dd = vsub(Dn, Dm)
1330 // Dd = vmul(Dn, Dm)
1331 // Dd = vmla(Dn, Dm)
1332 // Dd = vmls(Dn, Dm)
1333 // Dd = vdiv(Dn, Dm)
1338 void Decoder::DecodeTypeVFP(Instruction* instr) {
1339 VERIFY((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
1340 VERIFY(instr->Bits(11, 9) == 0x5);
1342 if (instr->Bit(4) == 0) {
1343 if (instr->Opc1Value() == 0x7) {
1344 // Other data processing instructions
1345 if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
1346 // vmov register to register.
1347 if (instr->SzValue() == 0x1) {
1348 Format(instr, "vmov'cond.f64 'Dd, 'Dm");
1350 Format(instr, "vmov'cond.f32 'Sd, 'Sm");
1352 } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
1354 Format(instr, "vabs'cond.f64 'Dd, 'Dm");
1355 } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
1357 Format(instr, "vneg'cond.f64 'Dd, 'Dm");
1358 } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
1359 DecodeVCVTBetweenDoubleAndSingle(instr);
1360 } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
1361 DecodeVCVTBetweenFloatingPointAndInteger(instr);
1362 } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
1363 (instr->Bit(8) == 1)) {
1364 // vcvt.f64.s32 Dd, Dd, #<fbits>
1365 int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
1366 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Dd");
1367 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1368 ", #%d", fraction_bits);
1369 } else if (((instr->Opc2Value() >> 1) == 0x6) &&
1370 (instr->Opc3Value() & 0x1)) {
1371 DecodeVCVTBetweenFloatingPointAndInteger(instr);
1372 } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1373 (instr->Opc3Value() & 0x1)) {
1375 } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
1376 Format(instr, "vsqrt'cond.f64 'Dd, 'Dm");
1377 } else if (instr->Opc3Value() == 0x0) {
1378 if (instr->SzValue() == 0x1) {
1379 Format(instr, "vmov'cond.f64 'Dd, 'd");
1381 Unknown(instr); // Not used by V8.
1383 } else if (((instr->Opc2Value() == 0x6)) && instr->Opc3Value() == 0x3) {
1384 bool dp_operation = (instr->SzValue() == 1);
1385 // vrintz - round towards zero (truncate)
1387 Format(instr, "vrintz'cond.f64.f64 'Dd, 'Dm");
1389 Unknown(instr); // Not used by V8.
1392 Unknown(instr); // Not used by V8.
1394 } else if (instr->Opc1Value() == 0x3) {
1395 if (instr->SzValue() == 0x1) {
1396 if (instr->Opc3Value() & 0x1) {
1397 Format(instr, "vsub'cond.f64 'Dd, 'Dn, 'Dm");
1399 Format(instr, "vadd'cond.f64 'Dd, 'Dn, 'Dm");
1402 Unknown(instr); // Not used by V8.
1404 } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
1405 if (instr->SzValue() == 0x1) {
1406 Format(instr, "vmul'cond.f64 'Dd, 'Dn, 'Dm");
1408 Unknown(instr); // Not used by V8.
1410 } else if ((instr->Opc1Value() == 0x0) && !(instr->Opc3Value() & 0x1)) {
1411 if (instr->SzValue() == 0x1) {
1412 Format(instr, "vmla'cond.f64 'Dd, 'Dn, 'Dm");
1414 Unknown(instr); // Not used by V8.
1416 } else if ((instr->Opc1Value() == 0x0) && (instr->Opc3Value() & 0x1)) {
1417 if (instr->SzValue() == 0x1) {
1418 Format(instr, "vmls'cond.f64 'Dd, 'Dn, 'Dm");
1420 Unknown(instr); // Not used by V8.
1422 } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
1423 if (instr->SzValue() == 0x1) {
1424 Format(instr, "vdiv'cond.f64 'Dd, 'Dn, 'Dm");
1426 Unknown(instr); // Not used by V8.
1429 Unknown(instr); // Not used by V8.
1432 if ((instr->VCValue() == 0x0) &&
1433 (instr->VAValue() == 0x0)) {
1434 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
1435 } else if ((instr->VLValue() == 0x0) &&
1436 (instr->VCValue() == 0x1) &&
1437 (instr->Bit(23) == 0x0)) {
1438 if (instr->Bit(21) == 0x0) {
1439 Format(instr, "vmov'cond.32 'Dd[0], 'rt");
1441 Format(instr, "vmov'cond.32 'Dd[1], 'rt");
1443 } else if ((instr->VLValue() == 0x1) &&
1444 (instr->VCValue() == 0x1) &&
1445 (instr->Bit(23) == 0x0)) {
1446 if (instr->Bit(21) == 0x0) {
1447 Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
1449 Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
1451 } else if ((instr->VCValue() == 0x0) &&
1452 (instr->VAValue() == 0x7) &&
1453 (instr->Bits(19, 16) == 0x1)) {
1454 if (instr->VLValue() == 0) {
1455 if (instr->Bits(15, 12) == 0xF) {
1456 Format(instr, "vmsr'cond FPSCR, APSR");
1458 Format(instr, "vmsr'cond FPSCR, 'rt");
1461 if (instr->Bits(15, 12) == 0xF) {
1462 Format(instr, "vmrs'cond APSR, FPSCR");
1464 Format(instr, "vmrs'cond 'rt, FPSCR");
1472 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
1473 Instruction* instr) {
1474 VERIFY((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
1475 (instr->VAValue() == 0x0));
1477 bool to_arm_register = (instr->VLValue() == 0x1);
1479 if (to_arm_register) {
1480 Format(instr, "vmov'cond 'rt, 'Sn");
1482 Format(instr, "vmov'cond 'Sn, 'rt");
1487 void Decoder::DecodeVCMP(Instruction* instr) {
1488 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1489 VERIFY(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
1490 (instr->Opc3Value() & 0x1));
1493 bool dp_operation = (instr->SzValue() == 1);
1494 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1);
1496 if (dp_operation && !raise_exception_for_qnan) {
1497 if (instr->Opc2Value() == 0x4) {
1498 Format(instr, "vcmp'cond.f64 'Dd, 'Dm");
1499 } else if (instr->Opc2Value() == 0x5) {
1500 Format(instr, "vcmp'cond.f64 'Dd, #0.0");
1502 Unknown(instr); // invalid
1505 Unknown(instr); // Not used by V8.
1510 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
1511 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1512 VERIFY((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
1514 bool double_to_single = (instr->SzValue() == 1);
1516 if (double_to_single) {
1517 Format(instr, "vcvt'cond.f32.f64 'Sd, 'Dm");
1519 Format(instr, "vcvt'cond.f64.f32 'Dd, 'Sm");
1524 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
1525 VERIFY((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
1526 VERIFY(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
1527 (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
1529 bool to_integer = (instr->Bit(18) == 1);
1530 bool dp_operation = (instr->SzValue() == 1);
1532 bool unsigned_integer = (instr->Bit(16) == 0);
1535 if (unsigned_integer) {
1536 Format(instr, "vcvt'cond.u32.f64 'Sd, 'Dm");
1538 Format(instr, "vcvt'cond.s32.f64 'Sd, 'Dm");
1541 if (unsigned_integer) {
1542 Format(instr, "vcvt'cond.u32.f32 'Sd, 'Sm");
1544 Format(instr, "vcvt'cond.s32.f32 'Sd, 'Sm");
1548 bool unsigned_integer = (instr->Bit(7) == 0);
1551 if (unsigned_integer) {
1552 Format(instr, "vcvt'cond.f64.u32 'Dd, 'Sm");
1554 Format(instr, "vcvt'cond.f64.s32 'Dd, 'Sm");
1557 if (unsigned_integer) {
1558 Format(instr, "vcvt'cond.f32.u32 'Sd, 'Sm");
1560 Format(instr, "vcvt'cond.f32.s32 'Sd, 'Sm");
1567 // Decode Type 6 coprocessor instructions.
1568 // Dm = vmov(Rt, Rt2)
1569 // <Rt, Rt2> = vmov(Dm)
1570 // Ddst = MEM(Rbase + 4*offset).
1571 // MEM(Rbase + 4*offset) = Dsrc.
1572 void Decoder::DecodeType6CoprocessorIns(Instruction* instr) {
1573 VERIFY(instr->TypeValue() == 6);
1575 if (instr->CoprocessorValue() == 0xA) {
1576 switch (instr->OpcodeValue()) {
1579 if (instr->HasL()) {
1580 Format(instr, "vldr'cond 'Sd, ['rn - 4*'imm08@00]");
1582 Format(instr, "vstr'cond 'Sd, ['rn - 4*'imm08@00]");
1587 if (instr->HasL()) {
1588 Format(instr, "vldr'cond 'Sd, ['rn + 4*'imm08@00]");
1590 Format(instr, "vstr'cond 'Sd, ['rn + 4*'imm08@00]");
1599 bool to_vfp_register = (instr->VLValue() == 0x1);
1600 if (to_vfp_register) {
1601 Format(instr, "vldm'cond'pu 'rn'w, {'Sd-'Sd+}");
1603 Format(instr, "vstm'cond'pu 'rn'w, {'Sd-'Sd+}");
1608 Unknown(instr); // Not used by V8.
1610 } else if (instr->CoprocessorValue() == 0xB) {
1611 switch (instr->OpcodeValue()) {
1613 // Load and store double to two GP registers
1614 if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
1615 Unknown(instr); // Not used by V8.
1616 } else if (instr->HasL()) {
1617 Format(instr, "vmov'cond 'rt, 'rn, 'Dm");
1619 Format(instr, "vmov'cond 'Dm, 'rt, 'rn");
1624 if (instr->HasL()) {
1625 Format(instr, "vldr'cond 'Dd, ['rn - 4*'imm08@00]");
1627 Format(instr, "vstr'cond 'Dd, ['rn - 4*'imm08@00]");
1632 if (instr->HasL()) {
1633 Format(instr, "vldr'cond 'Dd, ['rn + 4*'imm08@00]");
1635 Format(instr, "vstr'cond 'Dd, ['rn + 4*'imm08@00]");
1644 bool to_vfp_register = (instr->VLValue() == 0x1);
1645 if (to_vfp_register) {
1646 Format(instr, "vldm'cond'pu 'rn'w, {'Dd-'Dd+}");
1648 Format(instr, "vstm'cond'pu 'rn'w, {'Dd-'Dd+}");
1653 Unknown(instr); // Not used by V8.
1656 Unknown(instr); // Not used by V8.
1661 void Decoder::DecodeSpecialCondition(Instruction* instr) {
1662 switch (instr->SpecialValue()) {
1664 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1665 (instr->Bit(4) == 1)) {
1667 if ((instr->VdValue() & 1) != 0) Unknown(instr);
1668 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1669 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1670 int imm3 = instr->Bits(21, 19);
1671 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1672 "vmovl.s%d q%d, d%d", imm3*8, Vd, Vm);
1678 if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
1679 (instr->Bit(4) == 1)) {
1681 if ((instr->VdValue() & 1) != 0) Unknown(instr);
1682 int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
1683 int Vm = (instr->Bit(5) << 4) | instr->VmValue();
1684 int imm3 = instr->Bits(21, 19);
1685 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1686 "vmovl.u%d q%d, d%d", imm3*8, Vd, Vm);
1692 if (instr->Bits(21, 20) == 0) {
1694 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1695 int Rn = instr->VnValue();
1696 int type = instr->Bits(11, 8);
1697 int size = instr->Bits(7, 6);
1698 int align = instr->Bits(5, 4);
1699 int Rm = instr->VmValue();
1700 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1701 "vst1.%d ", (1 << size) << 3);
1702 FormatNeonList(Vd, type);
1704 FormatNeonMemory(Rn, align, Rm);
1705 } else if (instr->Bits(21, 20) == 2) {
1707 int Vd = (instr->Bit(22) << 4) | instr->VdValue();
1708 int Rn = instr->VnValue();
1709 int type = instr->Bits(11, 8);
1710 int size = instr->Bits(7, 6);
1711 int align = instr->Bits(5, 4);
1712 int Rm = instr->VmValue();
1713 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1714 "vld1.%d ", (1 << size) << 3);
1715 FormatNeonList(Vd, type);
1717 FormatNeonMemory(Rn, align, Rm);
1724 if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
1725 int Rn = instr->Bits(19, 16);
1726 int offset = instr->Bits(11, 0);
1728 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1730 } else if (instr->Bit(23) == 0) {
1731 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1732 "pld [r%d, #-%d]", Rn, offset);
1734 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1735 "pld [r%d, #+%d]", Rn, offset);
1742 if (instr->Opc1Value() == 0x7 && instr->Bits(19, 18) == 0x2 &&
1743 instr->Bits(11, 9) == 0x5 && instr->Bits(7, 6) == 0x1 &&
1744 instr->Bit(4) == 0x0) {
1745 // VRINTA, VRINTN, VRINTP, VRINTM (floating-point)
1746 bool dp_operation = (instr->SzValue() == 1);
1747 int rounding_mode = instr->Bits(17, 16);
1748 switch (rounding_mode) {
1751 Format(instr, "vrinta.f64.f64 'Dd, 'Dm");
1758 Format(instr, "vrintn.f64.f64 'Dd, 'Dm");
1765 Format(instr, "vrintp.f64.f64 'Dd, 'Dm");
1772 Format(instr, "vrintm.f64.f64 'Dd, 'Dm");
1778 UNREACHABLE(); // Case analysis is exhaustive.
1793 bool Decoder::IsConstantPoolAt(byte* instr_ptr) {
1794 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1795 return (instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker;
1799 int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
1800 if (IsConstantPoolAt(instr_ptr)) {
1801 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1802 return DecodeConstantPoolLength(instruction_bits);
1809 // Disassemble the instruction at *instr_ptr into the output buffer.
1810 int Decoder::InstructionDecode(byte* instr_ptr) {
1811 Instruction* instr = Instruction::At(instr_ptr);
1812 // Print raw instruction bytes.
1813 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1815 instr->InstructionBits());
1816 if (instr->ConditionField() == kSpecialCondition) {
1817 DecodeSpecialCondition(instr);
1818 return Instruction::kInstrSize;
1820 int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
1821 if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker) {
1822 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
1823 "constant pool begin (length %d)",
1824 DecodeConstantPoolLength(instruction_bits));
1825 return Instruction::kInstrSize;
1826 } else if (instruction_bits == kCodeAgeJumpInstruction) {
1827 // The code age prologue has a constant immediatly following the jump
1829 Instruction* target = Instruction::At(instr_ptr + Instruction::kInstrSize);
1831 SNPrintF(out_buffer_ + out_buffer_pos_,
1832 " (0x%08x)", target->InstructionBits());
1833 return 2 * Instruction::kInstrSize;
1835 switch (instr->TypeValue()) {
1838 DecodeType01(instr);
1862 return DecodeType7(instr);
1865 // The type field is 3-bits in the ARM encoding.
1870 return Instruction::kInstrSize;
1874 } } // namespace v8::internal
1878 //------------------------------------------------------------------------------
1883 const char* NameConverter::NameOfAddress(byte* addr) const {
1884 v8::internal::SNPrintF(tmp_buffer_, "%p", addr);
1885 return tmp_buffer_.start();
1889 const char* NameConverter::NameOfConstant(byte* addr) const {
1890 return NameOfAddress(addr);
1894 const char* NameConverter::NameOfCPURegister(int reg) const {
1895 return v8::internal::Registers::Name(reg);
1899 const char* NameConverter::NameOfByteCPURegister(int reg) const {
1900 UNREACHABLE(); // ARM does not have the concept of a byte register
1905 const char* NameConverter::NameOfXMMRegister(int reg) const {
1906 UNREACHABLE(); // ARM does not have any XMM registers
1911 const char* NameConverter::NameInCode(byte* addr) const {
1912 // The default name converter is called for unknown code. So we will not try
1913 // to access any memory.
1918 //------------------------------------------------------------------------------
1920 Disassembler::Disassembler(const NameConverter& converter)
1921 : converter_(converter) {}
1924 Disassembler::~Disassembler() {}
1927 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
1928 byte* instruction) {
1929 v8::internal::Decoder d(converter_, buffer);
1930 return d.InstructionDecode(instruction);
1934 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
1935 return v8::internal::Decoder::ConstantPoolSizeAt(instruction);
1939 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
1940 NameConverter converter;
1941 Disassembler d(converter);
1942 for (byte* pc = begin; pc < end;) {
1943 v8::internal::EmbeddedVector<char, 128> buffer;
1946 pc += d.InstructionDecode(buffer, pc);
1947 v8::internal::PrintF(
1949 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
1954 } // namespace disasm
1956 #endif // V8_TARGET_ARCH_ARM